python subclass access to class variable of parent
I was surprised to to learn that a class variable of a subclass can't access a class variable of the parent without specifically indicating the class name of the parent:
>>> class A(object):
... x = 0
...
>>> class B(A):
... y = x+1
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in B
NameError: name 'x' is not defined
>>> class B(A):
... y = A.x + 1
...
>>> B.x
0
>>> B.y
1
Why is it that in defining B.y I have to refer to A.x and not just x? This is counter to my开发者_运维技巧 intuition from instance variables, and since I can refer to B.x after B is defined.
Python's scoping rules for barenames are very simple and straightforward: local namespace first, then (if any) outer functions in which the current one is nested, then globals, finally built-ins. That's all that ever happens when a barename is looked up, and there's no need to memorize or apply any complicated rules (nor is there any need for a Python compiler to enforce more complicated rules).
Any time you want a different lookup, you'll be using a qualified name, not a bare name. Qualified names are vastly more powerful because the lookup can always be delegated to the objects whose attributes can be requested, and those object can implement whatever lookup rules they need. In particular, in an instance method within a class, self.x
is the way to ask the self
object to look up attribute name 'x'
-- and in that lookup it can delegate to classes, including the implementation of the concept of inheritance (and multiple inheritance, method resolution order, and so on).
The body of a class (as opposed to the bodies of the methods defined in a class) executes as part of the class
statement, before the class object is created or its name is bound (in particular, before any of the bases have been defined as being bases -- though this latest detail can never matter when referring to barenames, anyway!-).
So, in your example, in class B
, barename x
is looked up with the universal rules -- is it a name bound locally? If no, is it bound in any outer function in which this scope is nested? If no, is it bound as a global or built-in? If none of the above, using the barename in question of course causes a name-error exception.
Since you want a different lookup sequence than the barename lookup rules universally enforce, then clearly you need to use a qualified name, not a barename; and a moment's reflection will clearly show that the "one obvious choice" for a qualified name to use for your purpose has to be A.x
-- since that's where you want it to be looked up (the bases haven't been recorded anywhere yet at that point, after all... it will be the metaclass, normally type
, that will do the bases-binding as part of its job when it gets called after the class body is done executing!-).
Some people are so keenly attached to other "magical" rules for the lookup of barenames that they just can't stand this aspect of Python (originally inspired, I believe, by Modula-3, a little known language that's very well considered in theoreticians' circles;-) -- having to write self.x
in a method to specify that x
must be looked up on self
rather than using the universal barename rules, for example, drives such people batty.
Me, I love the simplicity and universality of the barename lookup rules, and I love using qualified names instead of barenames any time I want any other form of lookup... but then, it's not a secret that I'm madly in love with Python (I have my own grumbles -- e.g., global x
as a statement always makes my skin crawl, where I'd much rather write global.x
, i.e., have global
be a built-in name for "the currently executing module"... I do love qualified names!-), is it?-)
In Python, the body of a class is executed in its own namespace before the class is created (after which, the members of that namespace become the members of the class). So when the interpreter reaches y = x+1, class B does not exist yet at that point and, therefore, has no parent.
For more details, see http://docs.python.org/reference/compound_stmts.html#class-definitions
精彩评论