Strange Python function area behavior

I am confused by 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 result:

 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 expect func_wrapper always be the right function. I know that the scope of func_wrapper applies to the entire function, but I redefine it in each iteration of the loop, and the last instance in the attribute. I also tried adding func_wrapper = None below setattr , but that doesn't help (would also ask me a question ...).

I am blind? I don’t even see how to get around / fixing this.

+6
source share
1 answer

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 reliably, 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 external variable fn , which changes each time the loop starts. In the corrected examples, this is prevented.

+6
source

Source: https://habr.com/ru/post/918798/


All Articles