views:

79

answers:

3

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.

A: 

One of Python's design principles is "explicit is better than implicit." Why? If you have to specify it explicitly, the reader of your code (such as yourself in six months) knows what class is being referred to without having to spend any time understanding your inheritance hierarchy or looking elsewhere in the code to figure out what's going on. Since most code is read far more frequently than it is written, Python often has been designed for readers more than writers of code. Not, of course, that it is hard for writers of code either, but that is driven by other principles.

kindall
This is a weak explanation. You don't have to specify member function classes explicitly (`ObjClass.func(object)`); you don't have to specify that a variable is local; you don't have to unbind a variable before assigning a new value over a name. These are all implicit. Implicit is often better than explicit, particularly where explicit implies *redundant*. In this particular case, there should be a way to reference the parent class from class scope, without having to keep redundantly naming it.
Glenn Maynard
+1  A: 

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

Nathan Davis
+1  A: 

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?-)

Alex Martelli
Wow, thanks for the super detailed answer!
Jeff
@Jeff, you're welcome.
Alex Martelli