How to get parent's class attributes into the scope of the derived class?

I have a class which defines multiple class attributes and multiple methods. These methods have default arguments equal to class attributes. Sometimes attributes are used from methods (with self. prepended).

class MyClass:
    VAL1 = "hello"
    VAL2 = "world"

    def foo(self, x=VAL1, y=VAL2):
        if x == self.VAL1:
            print "yay"

    def bar(self, t=VAL2):
        pass

Now, for some reason, I want to move the attributes declaration into a separate class and split the methods among its children.

class Base:
    VAL1 = "hello"
    VAL2 = "world"

class Derived1(Base):
    def foo(self, x=VAL1, y=VAL2):
        if x == self.VAL1:
            print "yay"

class Derived2(Base):
    def bar(self, t=VAL2):
        pass

However, that does not work because Base's arguments, VAL1 and VAL2, are out of scope in derived classes.

Now the important point: I cannot change the code of the methods*. So the obvious way of writing def bar(self, t=Base.VAL2) does not work.

Is there any other way of extending the scope?

I'm using Python 2.7.

(*) There are literally dozens of methods in the class, and I don't want to change the existing code too much because similar coding convention is used elsewhere in the project. If you want to argue, please think about this question as of an educational one.

1 answer

  • answered 2018-07-11 02:39 Oliver Evans

    How about:

    class Base:
        VAL1 = "hello"
    
    class Derived1(Base):
        VAL1 = Base.VAL1
    
        def foo(self, x=VAL1):
            print(x)
    
    d = Derived1()
    d.foo()
    

    edit: I'm not sure it looks pretty, but it's more automated and perhaps suits you better.

    import inspect
    
    class Base:
        VAL1 = "hello"
        VAL2 = "world"
    
    class Derived1(Base):
        for var, val in inspect.getmembers(Base):
            locals()[var] = val
    
        def foo(self, x=VAL1, y=VAL2):
            if x == self.VAL1:
                print "yay"
            if y == self.VAL2:
                print "hoorah!"
    
    d1 = Derived1()
    d1.foo()
    

    double edit:

    If you don't want to copy __doc__ and __module__, you could use

    for var, val in inspect.getmembers(Base):
        if(var[:2] != '__'):
            locals()[var] = val
    

    As far as I know, this is not a very common thing to do in Python, so I'm guessing that most solutions will be a bit ugly (but I'd be curious to see a counterexample!)