根据我的理解,我们可以用两种方式调用对象的魔术方法。第一,像这样,像调用普通方法一样调用魔法方法。
x = (1, 2, 3, 4)
print(x.__len__())
#prints 4
第二种,像这样,魔法方法的调用是 "特别的"。
x = (1, 2, 3, 4)
print((len(x)))
#prints 4
正如我们所看到的,两种方法都是等价的 然而,当我调用神奇的方法 reversed()
的元组时,我遇到了一个错误。
x = (1, 2, 3, 4)
x.__reversed__()
#causes an attribute error
然而用 "特殊 "的方式调用反转的方法却完全正常。
x = (1, 2, 3, 4)
reversed(x)
#returns a reversed object
为什么会出现这种情况? 我是否对dunder方法有什么误解?
大多数魔术方法 不是 等同于其他任何看起来应该等同的东西。__add__
并不等同于 +
. __iadd__
不等于 +=
. __iter__
不等于 iter
. 也不 __getattribute__
也不 __getattr__
相当于 getattr
或普通属性访问)。
继续这个模式。__reversed__
不等于 reversed
. 如果 reversed
发现 __reversed__
方法,它就会使用该方法,但如果不使用,它就只做一个迭代器,用普通的索引从后往前访问参数。这个序列不需要 __reversed__
方法,以及 tuple
不存在的。
你的假设是,必须有一个 __reversed__
方法是错误的。
reversed(seq)
seq必须是一个有__reversed__()方法的对象。或 支持序列协议(__len__()方法和__getitem__()方法,参数从0开始为整数。).
因为 reversed
根据参数的不同,做以下操作之一。
__reversed__
妙法和 reversed
只是调用它并返回给定的迭代器。>>> class A:
... def __reversed__(self):
... yield 17
... yield 42
>>> a = A()
>>> reversed(a)
<generator object A.__reversed__ at 0x7fa1283e8e40>
>>> list(reversed(a))
[17, 42]
tuple
或 str
),具有 __len__
和 __getitem__
和 __reversed__
创建一个中间对象,产生从最后一个到第一个序列的元素。>>> t = (42, 17)
>>> reversed(t)
<reversed object at 0x7fa12840fc40>
>>> list(reversed(t))
[17, 42]
从 文件
reversed(seq)
返回一个反向迭代器。seq
必须是一个有__reversed__()
方法或支持序列协议(the__len__()
方法和__getitem__()
方法的整数参数以`0开始)。)
一般来说,你可能不应该调用dunder方法(因为这是非常危险的方式,特别是在生产代码中),而应该使用特殊的函数类来访问这些方法,如 reversed
len
.