0

Code

class Foo:

    bar = 1

    def run(self, arg1=bar):        # ok
#    def run(self, arg1=Foo.bar):    # fail
#    def run(self, arg1=self.bar):   # fail

#        print(bar)                  # fail
        print(Foo.bar)              # ok
        print(self.bar)             # ok

Foo().run()

Question

Why do argument list and function body require different access patterns? Do they have different namespace rules? Where can I find authentic documentation about this?

Cyker
  • 9,946
  • 8
  • 65
  • 93
  • In the documentation: [9.1 and 9.2 in the Classes section of the Tutorial](https://docs.python.org/3/tutorial/classes.html). [Naming and Binding](in the Execution Model](https://docs.python.org/3/reference/executionmodel.html#execution-model) section of the Language Reference. – wwii Aug 18 '18 at 03:29
  • 1
    There is no `Foo` on the line where you attempt to define the default parameter value. The name `Foo` becomes known when the class body is successfully parsed and compiled, which won't happen until the blank line. Why do you want to do to this at all? – DYZ Aug 18 '18 at 03:29
  • @juanpa.arrivillaga Where does it mention about argument list of a class method? – Cyker Aug 18 '18 at 03:44
  • @DYZ What do you mean by *class body* here? Do you mean the line with `def` is within class body but the method body has a new scope? I'm not seeing anywhere using a class variable as default argument for a class method as an anti-pattern, is that so? – Cyker Aug 18 '18 at 03:47
  • There are a lot of similar, I can't figure out which is The duplicate. Those two links really don't cover the answer: I have looked in the docs for this but haven't found it. When trying to use a class attribute as a default argument for a method of that class, default arguments are evaluated while/when the method is being *constructed* /compiled and since the whole class isn't *finished* yet, it doesn't exist yet. Basically what @DYZ said. Not a scoping issue but order of execution. At least for `arg1=Foo.bar`, and `arg1=self.bar` – wwii Aug 18 '18 at 03:47
  • @wwii The weird thing here is, it might be surprising that you have to use a different access pattern for default argument. The equivalent writing of the above code is to check `arg1` in the method body and assign with `Foo.bar` if it's empty. However if you are writing this as a default argument, then you have discard the quantifier `Foo.`. – Cyker Aug 18 '18 at 03:53
  • @Cyker read this [answer](https://stackoverflow.com/questions/291978/short-description-of-the-scoping-rules/23471004#23471004) it goes into detail. The class here is a red herring. python class definition statements and function definition statements are evaluated at *run time*, and the scoping rules are mostly consistent with the rest of python, except that class bodies do no create an enclosing scope over the functions defined inside of them. But that isn't relevant here. What is the different access pattern exactly? – juanpa.arrivillaga Aug 18 '18 at 04:20
  • The common idiom is to use a default argument of `None` or some other sentinel value and check `if arg is None: arg = Foo.bar` – juanpa.arrivillaga Aug 18 '18 at 04:22

0 Answers0