Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
842 views
in Technique[技术] by (71.8m points)

python - Why Can't I Override this Magic Method?

I was working on making a wrapper object that would take an instance of an arbitrary class and then automatically wrap all of its own magic methods to simply use the magic method (and value) of the wrapped object. For some reason, this doesn't work:

class Wrapper:
    def __init__(self, wrapped):
        self.wrapped = wrapped
        for method in filter(lambda x: x.startswith("__") and (x not in 
        ["__init__", "__new__", "__class__", "__metaclass__"]), 
        dir(wrapped)):
            if hasattr(getattr(wrapped, method), "__call__"):
                new_func = functools.partial(getattr(type(wrapped), method), self.wrapped)
                setattr(self, method, new_func)


t = Wrapper(7)
t + 8
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  TypeError: unsupported operand type(s) for +: 'Wrapper' and 'int'

class Tester:
    def __init__(self):
        self.v = 5
    def __add__(self, other):
        return self.v + other

y = Tester()
y + 7
12
t = Wrapper(y)
t + 9
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Wrapper' and 'int'

9 + t
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'Wrapper'

t.__add__
functools.partial(<function Tester.__add__ at 0x7fbec6372170>, <__main__.Tester object at 0x7fbec6392990>)

t.__add__(7)
12

I thought maybe the partial wasn't working properly with the distinction between the type's method and an instance method, but when I directly call my wrapper's magic add, it works properly. (This is tested in CPython 3.3)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Special methods are always looked up on the type of the instance (here the class object), not on the instance. Otherwise a __repr__ on a class would be used when you tried to print the representation of the class itself; type(class).__repr__(class) would use the correct magic method, while class.__repr__() would raise an exception because self was not provided.

You'll need to implement these special methods directly on the wrapper, propagating any exceptions that might be raised when called on the wrapped object.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...