Using an attribute of the current class instance as a default value for method's parameter [duplicate] Using an attribute of the current class instance as a default value for method's parameter [duplicate] python python

Using an attribute of the current class instance as a default value for method's parameter [duplicate]


It's written as:

def my_function(self, param_one=None): # Or custom sentinel if None is vaild    if param_one is None:        param_one = self.one_of_the_vars

And I think it's safe to say that will never happen in Python due to the nature that self doesn't really exist until the function starts... (you can't reference it, in its own definition - like everything else)

For example: you can't do d = {'x': 3, 'y': d['x'] * 5}


There is much more to it than you think. Consider the defaults to be static (=constant reference pointing to one object) and stored somewhere in the definition; evaluated at method definition time; as part of the class, not the instance. As they are constant, they cannot depend on self.

Here is an example. It is counterintuitive, but actually makes perfect sense:

def add(item, s=[]):    s.append(item)    print len(s)add(1)     # 1add(1)     # 2add(1, []) # 1add(1, []) # 1add(1)     # 3

This will print 1 2 1 1 3.

Because it works the same way as

default_s=[]def add(item, s=default_s):    s.append(item)

Obviously, if you modify default_s, it retains these modifications.

There are various workarounds, including

def add(item, s=None):    if not s: s = []    s.append(item)

or you could do this:

def add(self, item, s=None):    if not s: s = self.makeDefaultS()    s.append(item)

Then the method makeDefaultS will have access to self.

Another variation:

import typesdef add(item, s=lambda self:[]):    if isinstance(s, types.FunctionType): s = s("example")    s.append(item)

here the default value of s is a factory function.

You can combine all these techniques:

class Foo:    import types    def add(self, item, s=Foo.defaultFactory):        if isinstance(s, types.FunctionType): s = s(self)        s.append(item)    def defaultFactory(self):        """ Can be overridden in a subclass, too!"""        return []


Default value for parameters are evaluated at "compilation", once. So obviously you can't access self. The classic example is list as default parameter. If you add elements into it, the default value for the parameter changes!

The workaround is to use another default parameter, typically None, and then check and update the variable.