2

func can refer it itself if func is a global function.

def func(y):
    result = func.x + y
    # `func.x` does not raise an errors
    return result   
func.x = 5  

func(100)

However, it seems that a class method cannot refer to itself:

class K:        
    def mthd(self, y):
        return mthd.x + y
    mthd.x = 5

K.mthd() # raises an exception

The exception raised is a NameError:

[Drive Letter]:\[path]
Traceback (most recent call last):
  File "[Path]/[filename].py", line 35, in <module>
    K.mthd()
  File "[Path]/[filename].py", line 40, in mthd
    return mthd.x + y
NameError: name 'mthd' is not defined

Process finished with exit code 1

Why is this?

Is it because "func" is in globals whereas "mthd" is in K.__dict__?

functions can refer to variables outside of themselves, such as:

x = 3
def f():
    print(x)

Is the error caused because K.mthd has access to the names locals and globals, but not K.__dict__?

Toothpick Anemone
  • 4,290
  • 2
  • 20
  • 42
  • Related: [How can I access “static” class variables within class methods](https://stackoverflow.com/questions/707380/in-python-how-can-i-access-static-class-variables-within-class-methods) – Aran-Fey May 08 '18 at 17:26

1 Answers1

3

func is a global name, mthd is not. Methods are an attribute on the class object, which is available as a global:

K.mthd.x

In the class body (suite) itself, mthd is a local name; at the end of the class statement all locals are taken to form the class body; once the class is created, the local names are no longer available.

From the Class definitions section of the Python reference documentation:

The class’s suite is then executed in a new execution frame [...], using a newly created local namespace and the original global namespace. (Usually, the suite contains mostly function definitions.) When the class’s suite finishes execution, its execution frame is discarded but its local namespace is saved. A class object is then created using the inheritance list for the base classes and the saved local namespace for the attribute dictionary.

So in your code, the line mthd.x = 5 is analogous to accessing locals in a function body. Just like result is not available outside of the func() function scope, mthd is not available outside of the namespace available during class creation.

The class suite can otherwise refer to globals just fine, as can methods:

>>> x = 42
>>> class Demo:
...     print('Class body, globals are available, like x =', x)
...     def method(self):
...         print('Method body, globals are available, like x =', x)
...
Class body, globals are available, like x = 42
>>> Demo().method()
Method body, globals are available, like x = 42
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343