您可以通过将可调用对象动态分配给类的同名属性来模拟方法。这基本上适用于常见方法和dunder方法。但是lambda版本不能作为解释器机制的钩子:
>>> class Foo:
... def bar(self):
... return 'bar'
... def __repr__(self):
... return 'repr'
... f = Foo()
>>> f.bar()
'bar'
>>> f.__repr__()
'repr'
>>> print(f)
repr
>>> class Foo:
... def __init__(self):
... self.bar = lambda: 'bar'
... self.__repr__ = lambda: 'repr'
... f = Foo()
>>> f.bar()
'bar'
>>> f.__repr__()
'repr'
>>> print(f)
<__main__.Foo object at 0x000000FC7A879EB8>
那是为什么?
答案 0 :(得分:1)
因为C函数PyObject_Repr()
only looks at the repr
declared by the object's type, not in the object's dict。
答案 1 :(得分:-1)
TLDR:该假设是错误的。将可调用对象绑定为属性与创建方法不同。
方法是类上的一个函数,通过实例进行查找-这将调用函数的__get__
method将实例绑定到第一个参数。
>>> class Foo:
... ...
... def bar(self):
... print(self)
...
>>> foo = Foo()
>>> bar.__get__(foo, Foo)
<bound method bar of <__main__.Foo object at 0x10c08df50>>
将函数直接存储在实例上可以避免描述符协议-该属性的值为初始的未绑定函数。
>>> foo.bar = bar
>>> foo.bar
<function __main__.bar(self)>
这相当于在实例上存储属性,类方法或其他描述符类型。
必须将函数 存储在实际类或基类中,才能使其成为方法。
>>> foo = Foo()
>>> type(foo).bar = bar
>>> foo.bar
<bound method bar of <__main__.Foo object at 0x10c524090>>