0

Instead of doing the following:

def MyFunc(self, a, b, c)
    self.a = a
    self.b = b
    self.c = c

I want to do the following:

def MyFunc(self, self.a, self.b, self.c)

Why does this not work?

If I have to use the first approach, is there any good way to make sure I don't unintentionally overwrite variables used elsewhere in the project with the same names (e.g. perhaps "a" is a variable used by another object).

martineau
  • 119,623
  • 25
  • 170
  • 301
PProteus
  • 549
  • 1
  • 10
  • 23
  • 2
    Why should it work? a, b, c are parameters to the function that are sent by the caller, not values from the class. And why do you care what names other objects use? – Daniel Roseman Sep 30 '16 at 15:46
  • 4
    Function/method variables' (including their arguments) scope is limited to the function they are used in. You will not be conflicting with anything else in the project. – djhoese Sep 30 '16 at 15:46
  • 1
    Why do you want to do this? It doesn't work because a function in a class is created before the class object, and `self` is *just another argument name*. – Martijn Pieters Sep 30 '16 at 15:46
  • And argument names in a function are *local* variables. Are you afraid you'll shadow a global somewhere? – Martijn Pieters Sep 30 '16 at 15:47
  • Yes, I'm afraid I'll shadow a global variable somewhere. Also, it seems much cleaner than having the additional three lines of assignments. – PProteus Sep 30 '16 at 15:49
  • I'm also not sure why this has gotten so many downvotes. It is an honest question from someone who is new to Python. – PProteus Sep 30 '16 at 15:50
  • 2
    @PProteus: why do you think shadowing a global is an issue? Only *that one function* that shadows the name won't be able to access the global object. If that's an issue in that one function, just rename that one argument at a later time. – Martijn Pieters Sep 30 '16 at 15:54
  • Thank you, Martijn. Your explanation was helpful. I was under the impression that **all** variables were global in scope. – PProteus Sep 30 '16 at 16:04
  • 1
    @PProteus: no, Python has [proper scoping](http://stackoverflow.com/questions/291978/short-description-of-python-scoping-rules). – Martijn Pieters Sep 30 '16 at 16:39

1 Answers1

1

Instead of doing the following:

def MyFunc(self, a, b, c)
    self.a = a
    self.b = b
    self.c = c

I want to do the following:

def MyFunc(self, self.a, self.b, self.c)

Why does this not work?

This doesn't work because it simply invalid syntax. Python will not allow for you to use self. because your syntax is not valid. Lets take look at the EBNF for function arguments in Python:

parameters: '(' [typedargslist] ')'

typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [','
  ['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' >tfpdef]]
|  '*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' >tfpdef)

tfpdef: NAME [':' test]

You may or may not be able to tell from the above snippet of EBNF, but Python does not allow the . operator in parameters. That is why your second method doesn't work.

Lets assume though, that your second example was valid Python syntax. Would it work? The short answer is still no. This is simple because of how Python parses function/method parameters. Lets look at this example:

>>> class Foo:
    def __init__(self):
        pass
    def bar(self, x=self):
        pass

    
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    class Foo:
  File "<pyshell#13>", line 4, in Foo
    def bar(self, x=self):
NameError: name 'self' is not defined
>>> 

What happened? Why did Python raise a NameError when self is clearly defined.

While Python is in the middle of parsing bar is sees the parameter self. But while Python has "seen" the self parameter, it had not defined it as a name. So when Python tries to parse the second parameter, it becomes confused, and raises a NameError. This behavior is not just exclusive to methods however. Functions have the same problems as well:

>>> def foo(a, b=a+1):
    return a, b

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    def foo(a, b=a+1):
NameError: name 'a' is not defined

To sum it up; The real reason that your second examples doesn't work is because it's invalid Python syntax. But even if it did somehow work, Python would still raise an error due to the way it parses parameters.

Community
  • 1
  • 1
Christian Dean
  • 22,138
  • 7
  • 54
  • 87