为什么__repr__不能成为__init__中定义的属性?

时间:2019-10-18 10:52:17

标签: python

您可以通过将可调用对象动态分配给类的同名属性来模拟方法。这基本上适用于常见方法和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>

那是为什么?

2 个答案:

答案 0 :(得分:1)

答案 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>>