Reputation: 1003
I know that we can access class attributes with self
or the class
name.
But I am bit confused why the following also works
class Crazy(object):
VERSION = 1
def __init__(self, version=VERSION):
print version
But this doesn't
class Crazy(object):
VERSION = 1
def __init__(self):
print VERSION
Upvotes: 8
Views: 4429
Reputation: 522005
A class definition, i.e. the block inside class ...:
, is evaluated like any regular Python code block. Just at the end of the class
block, every local name which was defined inside that block becomes part of the class' __dict__
. The class
syntax is more or less just syntactic sugar over:
Crazy = type('Crazy', (object,), {'VERSION': 1, ...})
See https://docs.python.org/3/library/functions.html#type.
Given this, you'd expect this to work, right?
VERSION = 1
def foo(bar=VERSION):
print(bar)
(Also see this for more explanation on its behaviour.)
Inside a class
block this works exactly the same way, with the only special behaviour that you're not creating global names, but names which will become the class' __dict__
.
The relevant paragraph in the documentation is here:
The class’s suite is then executed in a new execution frame (see Naming and binding), using a newly created local namespace and the original global namespace. (Usually, the suite contains mostly function definitions.) When the class’s suite finishes execution, its execution frame is discarded but its local namespace is saved. A class object is then created using the inheritance list for the base classes and the saved local namespace for the attribute dictionary. The class name is bound to this class object in the original local namespace.
https://docs.python.org/3/reference/compound_stmts.html#class-definitions
After the class is defined though, that implicit namespace doesn't exist anymore, so this doesn't work:
def __init__(self):
print(VERSION)
The scoping rules follow the regular lookup chain:
None of these are true, since VERSION
is just an attribute of Crazy
at this point, so is only accessible as Crazy.VERSION
or self.VERSION
, the latter of which actually also doesn't exist and falls back onto its own lookup chain and traverses up to Crazy.VERSION
.
Upvotes: 8