assigning class variable as default value to class method argument

I would like to build a method inside a class with default values arguments taken from this class. In general I do filtering on some data. Inside my class I have a method where normally I pass vector of data. Sometimes I don't have the vector and I take simulated data. Every time I do not pass a particular vector I would like to take simulated data by default. I thought it should be an easy construction where inside my method definition I say a=self.vector. But for some reason I have an error NameError: name 'self' is not defined. The simplified construction is:

class baseClass(object):  # This class takes an initial data or simulation
    def __init__(self):
        self.x = 1
        self.y = 2

class extendedClass(baseClass): # This class does some filtering
    def __init__(self):
        baseClass.__init__(self)
        self.z = 5
    def doSomething(self, a=self.z):
        self.z = 3
        self.b = a

if __name__ == '__main__':
    a = extendedClass()
    print a.__dict__
    a.doSomething()
    print a.__dict__

An output I expected should be:

{'y': 2, 'x': 1, 'z': 5}
{'y': 2, 'x': 1, 'z': 3, 'b': 5}

I tried default assignment as def doSomething(self, a=z): obviously it doesn't work ever. As far as I understand self.z is visible in this scope and should not be a problem to have it as a default value. Don't know why I have this error and how to do it. This is probably an easy question, but I try to figure it out or find the solution with no lack for sometime already. I found similar questions only for other languages.


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.


This will insert self.z if a is None/False/empty_value:

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