spiritedExit0
spiritedExit0

Reputation: 93

Why is the __dict__ attribute of this function an empty dictionary?

I was testing out the pre-defined dict attribute on a function, and I got a result I didn't expect to get. Consider the following code:

>>> def func():
       x = 7
       a = 0
       print(func.__dict__)

    
>>> func()
{}

After all, I did define two variables in the namespace of the function. So why aren't these names appearing in the dict attribute of the function?

Upvotes: 0

Views: 1151

Answers (3)

Manu Valdés
Manu Valdés

Reputation: 2372

__dict__ is there to support function attributes, it's not a namespace nor a symbol table for the function body scope. You can read PEP-232 for further information regarding function attributes.

Upvotes: 1

MisterMiyagi
MisterMiyagi

Reputation: 50146

The __dict__ attribute of a function object stores attributes assigned to the function object.

>>> def foo():
...     a = 2
...     return a
...
>>> foo.bar = 12
>>> foo.__dict__
{'bar': 12}

Attributes of the function object are not related to the local variables that exist during the function call. The former is unique (there is one __dict__ per function object) the latter are not (a function may be called multiple times with separate local variables).

>>> def nfoo(n: int):
...     print(f'level {n} before:', locals())
...     if n > 0:
...        nfoo(n - 1)
...     print(f'level {n} after: ', locals())
...
>>> nfoo(2)
level 2 before: {'n': 2}
level 1 before: {'n': 1}
level 0 before: {'n': 0}
level 0 after:  {'n': 0}
level 1 after:  {'n': 1}
level 2 after:  {'n': 2}

Note how the locals of each level exist at the same time but hold separate values for the same name.

Upvotes: 1

user2357112
user2357112

Reputation: 281287

A function's __dict__ holds attributes, not local variables. Local variables are specific to each execution of a function, not to the function itself, so you can't get local variable values by inspecting a function.

If you assigned an attribute:

func.blah = 3

that would show up in the __dict__.

(A __dict__ doesn't hold all attributes - there are other ways to create attributes, which is why __dict__ itself doesn't show up in the __dict__, for example.)

Upvotes: 2

Related Questions