Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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

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

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...