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