问题
I have the following class:
class MyInt:
def __init__(self, v):
if type(v) != int:
raise ValueError('value must be an int')
self.v = v
def __getattr__(self, attr):
return getattr(self.v, attr)
i = MyInt(0)
print(i + 1)
I get the error: TypeError: unsupported operand type(s) for +: 'MyInt' and 'int'
Shouldn't i.__add__(1)
be called? And shouldn't __getattr__
be called when no such method is found in the MyInt
class?
回答1:
__getattr__
cannot be used to generate other magic methods. You'll need to implement all of them individually.
When the Python language internals look up magic methods like __add__
, they completely bypass __getattr__
, __getattribute__
, and the instance dict. The lookup goes roughly like
def find_magic_method(object, method_name):
for klass in type(object).__mro__:
if method_name in klass.__dict__:
return klass.__dict__[method_name]
raise AttributeError
If you want to see the exact lookup procedure, it's _PyObject_LookupSpecial
in Objects/typeobject.c.
If you're wondering why Python does this, there are a lot of magic methods for which it would be really awkward or impossible to do what you were expecting. For example, Python couldn't possibly use __getattribute__
to look up __getattribute__
, as that would cause infinite recursion with no base case.
来源:https://stackoverflow.com/questions/38294904/how-to-use-getattr-to-delegate-methods-to-attribute