assigning class variable as default value to class method argument assigning class variable as default value to class method argument python python

assigning class variable as default value to class method argument


Your understanding is wrong. self is itself a parameter to that function definition, so there's no way it can be in scope at that point. It's only in scope within the function itself.

The answer is simply to default the argument to None, and then check for that inside the method:

def doSomething(self, a=None):    if a is None:        a = self.z    self.z = 3    self.b = a


Here's the disassembly of the code for a simple example module. A code object is a read-only container for bytecode, the constants and names it uses, and metadata about the number of local variables, required stack size, etc. Notice that all of the code objects are compiled as constants. These are created at compilation time. But the objects class A and function test are instantiated at execution time (e.g. when the module is imported).

To make the class, BUILD_CLASS takes the name 'A', the bases tuple (object,), and a dict that contains the attributes of the class namespace. This is like manually instantiating a type by calling type(name, bases, dict). To make the dict, a function is created from code object A and called. Finally, the class object is stored in the module namespace via STORE_NAME.

In code object A, self.z is loaded on the stack as the argument to MAKE_FUNCTION. The bytecode op LOAD_NAME will search for self in the current locals (i.e. the class namespace being defined), the module globals, and builtins. This will obviously fail if self isn't defined in the global or builtins scope; it clearly isn't defined in the local scope.

If it did succeed, however, the function would be created with (self.z,) as its __defaults__ attribute, and then stored to the local name test.

>>> code = compile('''... class A(object):...   def test(self, a=self.z): pass... ''', '<input>', 'exec')>>> dis.dis(code)  2           0 LOAD_CONST               0 ('A')              3 LOAD_NAME                0 (object)              6 BUILD_TUPLE              1              9 LOAD_CONST               1 (<code object A ...>)             12 MAKE_FUNCTION            0             15 CALL_FUNCTION            0             18 BUILD_CLASS                      19 STORE_NAME               1 (A)             22 LOAD_CONST               2 (None)             25 RETURN_VALUE>>> dis.dis(code.co_consts[1]) # code object A  2           0 LOAD_NAME                0 (__name__)              3 STORE_NAME               1 (__module__)  3           6 LOAD_NAME                2 (self)              9 LOAD_ATTR                3 (z)             12 LOAD_CONST               0 (<code object test ...>)             15 MAKE_FUNCTION            1             18 STORE_NAME               4 (test)             21 LOAD_LOCALS                      22 RETURN_VALUE       

@uselpa: Your pastebin example (rewritten for 2.x):

>>> code = compile('''... default = 1... class Cl(object):...     def __init__(self, a=default):...         print a... Cl()... default = 2... Cl()... ''', '<input>', 'exec')>>> dis.dis(code)  2           0 LOAD_CONST               0 (1)              3 STORE_NAME               0 (default)  3           6 LOAD_CONST               1 ('Cl')              9 LOAD_NAME                1 (object)             12 BUILD_TUPLE              1             15 LOAD_CONST               2 (<code object Cl ...>)             18 MAKE_FUNCTION            0             21 CALL_FUNCTION            0             24 BUILD_CLASS                      25 STORE_NAME               2 (Cl)  6          28 LOAD_NAME                2 (Cl)             31 CALL_FUNCTION            0             34 POP_TOP               7          35 LOAD_CONST               3 (2)             38 STORE_NAME               0 (default)  8          41 LOAD_NAME                2 (Cl)             44 CALL_FUNCTION            0             47 POP_TOP                          48 LOAD_CONST               4 (None)             51 RETURN_VALUE        

As you can see, class object Cl (and function object __init__) is only instantiated and stored to the local name 'Cl' once. The module executes sequentially at run time, so subsequently rebinding the name default will have no effect on the default value in __init__.

You could dynamically instantiate a new function using the previously compiled code and a new default value:

>>> default = 1>>> class Cl(object):...     def __init__(self, a=default):...         print a... >>> from types import FunctionType>>> default = 2>>> Cl.__init__ = FunctionType(...   Cl.__init__.__code__, globals(), '__init__', (default,), None)>>> c = Cl()2

This reuses the already compiled code object from __init__.__code__ to create a function with a new __defaults__ tuple:

>>> Cl.__init__.__defaults__(2,)


Default arguments get evaluated only once, when the definition is executed. Instead, do this:

def doSomething(self, a=None):    if a is None:        a = self.z    self.z = 3    self.b = a

See also http://docs.python.org/release/3.3.0/tutorial/controlflow.html#more-on-defining-functions.