can't rebind magic methods
aleaxit at yahoo.com
Tue Mar 21 03:51:50 CET 2006
Michael Tobis <mtobis at gmail.com> wrote:
> Still a bit confused actually. Any explanation of the following?
I believe the problem you're having is with WHEN a name is looked up --
which tends to be 'as late as possible, but no later'.
> def getf(method,name):
> def f(self, *a, **k): return method(self.val, *a, **k)
> f.func_name = name
> return f
Here, 'method' is looked up at each execution of f -- but each instance
of f is separate and has a separate closure, so 'method' is what it's
worth in THAT call to getf (as desired).
> for spec in 'str repr hash hex oct pow add'.split():
> name = '__%s__' % spec
> method = getattr(int, name)
Here, we're rebinding method in the same scope at each pass; in the end,
it's left bound to the last value it had -- the getaddr of 'add' in int.
> # comment this out to get the non-working case
> setattr(myint,name,getf(method,name)) # works
> # uncomment three lines to get the non-working case
> # raises TypeError: "expected 1 arguments, got 0" at method
> # why isn't this equivalent to the setattr above?
Because it's looking up 'method' in the scope of the "def f" -- and in
that scope, at the time f executes, the loop is over, so name 'method'
is always bound to 'getattr(int, "add")'.
> # def f(self, *a, **k): return method(self.val, *a, **k)
> # f.func_name = name
> # setattr(myint,name,f) # doesn't work
More information about the Python-list