3
votes

While assigning num1 = self.var1 in function fiz, Python says unresolved reference. Why is that?

class Foo:

    def __init__(self):
        self.var1 = "xyz"

    def fiz(self, num1=self.var1):
        return
1
Default values cannot refer to other parameters, including self, as they are "not in the same scope". In fact, the values are resolved before the method is ever run. This is also why def f(my_list = []) does not create a new list each invocation.. one way to approach this would be to use def fiz(self, num1 = None): if num1 is None: num1 = self.var1.. If there is a difference between 'None' and 'not specified', kwargs an be used. - user2864740
self is not in scope inside the class defintion - you can't have an instance before you've finished defining the class! Just use None as a default, then set num1 = self.var1 if num1 is None else num1 inside the method. - jonrsharpe

1 Answers

4
votes

Method (and function) default parameter values are resolved when the method is defined. This leads to a common Python gotcha when those values are mutable: "Least Astonishment" and the Mutable Default Argument

In your case, there is no self available when the method is defined (and if there was such a name in scope, as you haven't actually finished defining the class Foo yet, it wouldn't be a Foo instance!) You can't refer to the class by name inside the definition either; referring to Foo would also cause a NameError: Can I use a class attribute as a default value for an instance method?

Instead, the common approach is to use None as a placeholder, then assign the default value inside the method body:

def fiz(self, num1=None):
    if num1 is None:
        num1 = self.val1
    ...