175

Why such structure

class A:
    def __init__(self, a):
        self.a = a

    def p(self, b=self.a):
        print b

gives an error NameError: name 'self' is not defined?

Elazar
  • 18,541
  • 4
  • 43
  • 67
chriss
  • 4,179
  • 8
  • 28
  • 36

3 Answers3

197

Default argument values are evaluated at function define-time, but self is an argument only available at function call time. Thus arguments in the argument list cannot refer each other.

It's a common pattern to default an argument to None and add a test for that in code:

def p(self, b=None):
    if b is None:
        b = self.a
    print b

Update 2022: Python developers are now considering late-bound argument defaults for future Python versions.

intgr
  • 18,847
  • 5
  • 57
  • 67
  • 7
    Although I think that the above is not very pretty (I come from ruby where things just work fine), the above actually works as a workaround. It's still awkward that python chose to make self unavailable in a parameter list. – shevy Jan 02 '18 at 11:30
  • 3
    @shevy: "self" has no special meaning in python, it's just the name _conventionally_ chosen for the first argument. You can as well replace "self" by "me" or "x". – Max May 22 '19 at 20:41
  • 1
    Is there no better way to do this? If we have a function that takes a dozen default arguments that should reference self, do we really need a dozen if statements? This is terribly awkward. – Richard J. Barbalace Feb 13 '20 at 01:33
  • If the caller *explicitly* passed in `None` for the second parameter, it gets over-ridden to `self.a`, which is unexpected and surprising. – abelenky Feb 03 '21 at 17:56
20

For cases where you also wish to have the option of setting 'b' to None:

def p(self, **kwargs):
    b = kwargs.get('b', self.a)
    print b
Andrew
  • 211
  • 1
  • 2
15

If you have arrived here via google, please make sure to check that you have given self as the first parameter to a class function. Especially if you try to reference values for that object instance inside the class function.

def foo():
    print(self.bar)

>NameError: name 'self' is not defined

def foo(self):
    print(self.bar)
Erich
  • 1,749
  • 1
  • 16
  • 21