How can I refer to a base class attribute in a derived class?

I can do it:

class Blah2:
    atttr = 5
    aa = atttr


ob = Blah2
print(ob.aa)

      

http://ideone.com/pKxMc2

So, I assumed I could do this:

class Blah1:
    atttr = 5


class Blah2(Blah1):
    aa = atttr


ob = Blah2
print(ob.aa)

      

No, I can't: http://ideone.com/6HS1MO

Throws the following error:

Traceback (most recent call last):
  File "./prog.py", line 5, in <module>
  File "./prog.py", line 6, in Blah2
NameError: name 'atttr' is not defined

      

Why doesn't this work and how does it work?

+3


source to share


2 answers


The classroom scope only exists at the time of class definition. After defining the class, you will have to access this attribute through the class object, i.e. Blah1.atttr

...

This is described in the Execution Model section .



The blocks and class definition arguments for exec () and eval () are special in the context of name resolution. A class definition is an executable statement that can use and define names. These references follow normal name resolution rules, except that unrelated local variables are looked up in the global namespace. The namespace of the class definition becomes an attribute of the class dictionary. The scope of names defined in a class block is limited by the class block ; it does not apply to method codeblocks - this includes generator expressions and expressions as they are implemented using scope.

+2


source


Your problem is fixed as follows:

class Blah1:
    atttr = 5


class Blah2(Blah1):
    aa = BLah1.atttr

      

However, as pointed out in the comments, this is weird. You now have this:

>>> ob = Blah2()
>>> assert ob.aa == ob.atttr
True

      

EDIT: As pointed out in wim's answer, the reason for this is how the scope works inside the class definition. When you do this:

class C():
    a = 1

      

It's pretty much equivalent to this:



C = type('C', (), {}) # <--- dynamic class creation function
C.a = 1

      

As you can see, to access this a

anywhere outside the body of a class definition, you need to refer to it with a class (or an instance of a class): C.a

or c().a

. But notice this "gotcha":

class C():
    a = 1

c = C()
c.a = 2
print(C.a) #  prints 1!!!

      

It prints 1 because there is now an attribute c

a

and after the second line above c

a

, and they are two different objects:

>>> vars(c)
{'a': 2}
>>> vars(C)
{'a': 1}

      

If you want C.a

not to override C.a

, you need to learn about properties and descriptors. Maybe start here .

+1


source







All Articles