when I use any class variable in class code blocks, I'm getting not defined error. how can I fix it ?
example
class A():
__hidden_number__ = 5
__no_hidden_number__ = A.__hidden_number__ + 4 # to cause error. why ?
Thanks.
when I use any class variable in class code blocks, I'm getting not defined error. how can I fix it ?
example
class A():
__hidden_number__ = 5
__no_hidden_number__ = A.__hidden_number__ + 4 # to cause error. why ?
Thanks.
your class variable is already in A
namespace.
So you just have to do:
__no_hidden_number__ = __hidden_number__ + 4
else you're trying to access A.A
and it doesn't exist yet.
To illustrate what I'm stating, that "works" (but not what you want):
class A():
class A():
__hidden_number__ = 4
__no_hidden_number__ = A.__hidden_number__ + 4
A() # that works
that doesn't:
class A():
class B():
__hidden_number__ = 4
__no_hidden_number__ = A.__hidden_number__ + 4 # B.__... would've worked
A() # beeep: NameError: name 'A' is not defined
note that you should avoid to define private attributes with trailing double underscore (__xxx__
). It works, but this is generally reserved for python special class members (__class__
, __file__
, __eq__
, etc...). Name mangling (making the object "private") already occurs with 2 leading underscores.
Since this might be a little unclear (the existing answer is fine), let me add to that:
class A:
pass
A = type('A', (object,), {})
What we write inside the class declaration is essentially building that (here empty) dictionary and that happens before the variable A
gets assigned. And since we have --not yet-- a variable of the name A
in the namespace hierarchy while the class declaration runs, A
isn't available.
The class exists, it also has the type name 'A'
, but it hasn't gotten assigned to the variable A
, yet.
The difference between the class A: pass
-version and the explicit type
call is syntactic sugar: When using class
, everything nested inside the class is automatically namespaced into the class dictionary.
This is why this works:
class A:
var = 1
var2 = var + 1
But as we can see above, the local variable A
that will finally hold our new class is assigned only after the class declaration has already been evaluated and thus isn't available inside of it.
If we disassemble a class decl, we get:
import codeop, dis
dis.disassemble(codeop.compile_command('class A:\r\n pass'))
1 0 LOAD_CONST 0 ('A')
3 LOAD_CONST 3 (())
6 LOAD_CONST 1 (<code object A at 0x80076ff30, file "<input>", line 1>)
9 MAKE_FUNCTION 0
12 CALL_FUNCTION 0
15 BUILD_CLASS
16 STORE_NAME 0 (A)
19 LOAD_CONST 2 (None)
22 RETURN_VALUE
19
and 22
are added automatically, since code objects must return a value. We can ignore those for our example.
What else is happening here?
0
: pushes the string 'A'
onto the stack. This will become the name of the class (the first argument to type()
).3
: pushes an empty tuple, the list of parent classes6
: Loads the code object for the class declaration.9
and 12
run the class declaration code object. This is what e.g. does our (class) variable assignments. It returns the class dictionary.15
builds the class onto the stack. This is equivalent to type('A', (), class_dict)
, where the parameters are exactly the values on the stack at this point.And finally:
16
stores the freshly created class into the local namespace under the name A
.As we can see, the class declaration is run (12
), before the class is assigned to its variable A
(16
).
Note that the disassembly is different in Python 3, because python as a special builtin class builder function.
And yes, this is far too long an answer ;-).