Reputation: 68140
I'm confused about this scope behavior:
class Bar:
def __init__(self):
for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]:
print "register", fn
def func_wrapper(filename):
print "called func wrapper", fn, filename
setattr(self, fn, func_wrapper)
bar = Bar()
bar.open("a")
bar.remove("b")
bar.listdir("c")
This gives the output:
register open
register openW
register remove
register mkdir
register exists
register isdir
register listdir
called func wrapper listdir a
called func wrapper listdir b
called func wrapper listdir c
But I would have expected that func_wrapper
would always be the correct function. I know that the scope of func_wrapper
is to the whole function but I redefine it in every loop iteration and the last instance got saved away in the attrib. I also tried to add func_wrapper = None
below the setattr
but that doesn't help (would also have wondered me...).
Am I blind? I don't even really see how to work around / fix this.
Upvotes: 6
Views: 190
Reputation: 91017
Either with
class Bar:
def __init__(self):
for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]:
print "register", fn
def func_wrapper(filename, fn=fn):
print "called func wrapper", fn, filename
setattr(self, fn, func_wrapper)
or, more robustly, with
def mkwrapper(fn):
def func_wrapper(filename):
print "called func wrapper", fn, filename
func_wrapper.__name__ = fn
return func_wrapper
class Bar:
def __init__(self):
for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]:
print "register", fn
func_wrapper = mkwrapper(fn)
setattr(self, fn, func_wrapper)
In your original example, all generated functions access the same outer variable fn
, which changes in every loop run. In the corrected examples, this is prevented.
Upvotes: 6