Calling Locals() In A Function Nested In A Class Method
Solution 1:
Admitting that you can compute the variables dict before running bad, you can use this:
classFoo(object):
defbar(self, x):
outer_locals = locals()
defbaz(y):
print outer_locals['self']
..
return baz(..)
If, instead, you have to compute the dictionary at runtime (inside bad
), this is the way to go:
import inspect
defouter_locals(depth=0):
"""
With depth=0 behaves like locals(), depth=1 are the locals of the
containing frame, depth=2 the locals of the frame containing the containing
frame and so on...
"""return inspect.getouterframes(inspect.currentframe())[depth+1][0].f_locals
classFoo(object):
defbar(self, x):
defbaz(y):
print outer_locals(1)
return baz(...)
Note that if not overwritten in the baz
function, all of bar
locals are available in bad
:
classFoo(object):
defbar(self, x):
defbaz(y):
print self
..
return baz(..)
Solution 2:
I get the same behavior you report in 2.7 using 2.6.6. However, I also get it using 2.5.2 and 2.4.6. (All Linux.)
Interestingly:
>>> classFoo(object):
defbar(self, x):
defbaz(y):
print self.__class__.__name__
printlocals()['self']
return baz(4)
...
>>> Foo().bar(3)
Foo
<__main__.Foo object at 0x9801f4c>
>>>
Presumably there was some optimization or alteration of the process of computing the local symbol table whereby only names actually used in a given function's scope are added to its table, even if a given symbol would be accessible (and would not be a global!) were it to be explicitly referred to.
Changing the last line of bar() to return baz
(rather than return baz(4)
) we can see that self
is not a local variable; it's a free variable:
>>> baz = Foo().bar(4)
>>> baz.func_code.co_nlocals, f.func_code.co_varnames, f.func_code.co_freevars
(1, ('y',), ('self',))
Even here, though, x
has not been included among the free variables, because when the name isn't used in the interior function, it doesn't count as free there.
That explanation, though, makes the behavior you're describing under 2.5 on Vista sound like a bug.
Solution 3:
Hmmm, I believe the KeyError
is correct; I get the same on Python 2.7.1 on OSX SnowLeopard.
Here's why. I modified your code to the following:
classFoo(object):
defbar(self, x):
quux = 4printlocals()
defbaz(y):
printlocals()#['self']return baz(3)
foo = Foo()
foo.bar(2)
and got
{'quux': 4, 'self': <__main__.Foo object at 0x1004945d0>, 'x': 2}
{'y': 3}
The issue is that in baz
the locals
dict should not include self
which is defined in an outer scope.
I'm really puzzled why this found self
in baz
's locatls under Windows. Either it is a bug in 2.5 or in the Windows implementation, or the language spec has changed between 2.5 and 2.7.
Solution 4:
The local variables are always the ones defined within the current called function, the global variables are always the ones defined at the top of your program.
In bar
self is a local variable. In baz
self is somewhere inbetween the local and global variables. You can still reference it because Python will search for it in higher scopes as it's not defined in the local one, but
you cannot access theese scopes' dictionary.
Post a Comment for "Calling Locals() In A Function Nested In A Class Method"