185

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
  • 20,415
  • 4
  • 46
  • 67
chriss
  • 4,349
  • 8
  • 29
  • 36

3 Answers3

202

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
  • 19,834
  • 5
  • 59
  • 69
  • 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
  • 4
    @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
  • 2
    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
16

A self NameError can also occur if you fail to define self inside a method signature. This error typically will appear as TypeError, as there will be a mismatch between expected and given arguments[1]. However, if you accept a variable number of arguments, self will be arg[0], and the variable self will be undefined.

A minimal example.

class Obj:
    def foo(*args):
        print(self.bar)

>NameError: name 'self' is not defined

Correction:

class Obj:
    def baz(self, *args):
        print(self.bar)

[1] http://neopythonic.blogspot.com/2008/10/why-explicit-self-has-to-stay.html

Erich
  • 1,902
  • 1
  • 17
  • 23
  • This example doesn't make sense in ordinary cases. Omitting a `self` parameter **from a method** will normally result in a `TypeError` complaining about a wrong number of arguments. – Karl Knechtel Sep 05 '22 at 09:40
  • Not necessarily, consider the case where a method should be `foo(self, *args, **kwargs)` but self is omitted. – Erich Sep 06 '22 at 19:25
  • Plausible, but uncommon, and certainly doesn't match this example. – Karl Knechtel Sep 06 '22 at 19:36
  • You are correct. However, the error message given in my case is the titular one. An internet query would bring you here. Is there a different question on stackoverflow that you would point to? I am happy to replace this answer as a question comment pointing to another topic. – Erich Sep 07 '22 at 20:46
  • " However, the error message given in my case is the titular one." By the code shown, yes; but in this case, `foo` cannot be called a "class function" (did you mean *method*?) as there is no class to be seen anywhere. If the code is indented into a class and then used as a method, the error message will be different - getting this message *also* requires calling `foo` as a plain function namespaced within the class, in which case the author of the code has serious conceptual difficulties beyond just a typo. – Karl Knechtel Sep 07 '22 at 20:50
  • I've rewritten my answer, PTAL. My prior example was sufficient to generate a `NameError` for self, but was not reflective of the real world example I was describing. My example now is aligned with a definite case. The reason for not defining a class prior was to highlight the fact that self is just a varible, and that a NameError just means that a variable is undefined. My example produced such an error. As in the title. This is the first page in some search engine results for "NameError: 'self' ...". I believe mentioning this here is important for early python learners. – Erich Sep 08 '22 at 22:47