gpt4 book ai didi

python - 为什么 `x[i]` 不等于 `x.__getitem__(x)` ?

转载 作者:行者123 更新时间:2023-12-04 13:26:22 24 4
gpt4 key购买 nike

来自 documentation :

x[i] is roughly equivalent to type(x).__getitem__(x, i).


上面有什么好处而不是看起来更简单 x.__getitem__(i) ?
编辑:为什么 Python 会这样?
作为标准行为的一个缺点,让我展示这个示例代码,我惊讶地发现最后一个断言失败,而倒数第二个断言(直接调用 __getitem__)通过。
def poww_bar(base):
class Bar():
def __getitem__(self, x):
return lambda: base**x
return Bar()

def poww_foo(base):
class Foo():
pass
f = Foo()
f.__getitem__ = lambda x: lambda: base ** x
return f

pow_bar2 = poww_bar(2)
pow_foo2 = poww_foo(2)


assert pow_bar2.__getitem__(3)() == 8 # OK
assert pow_bar2[3]() == 8 # OK

assert pow_foo2.__getitem__(3)() == 8 # OK
assert pow_foo2[3]() == 8 # TypeError: 'Foo' object is not subscriptable

最佳答案

方法是类属性,而不是实例属性。
没有名为 __getitem__ 的实例属性与 pow_bar2 相关联.因此查找继续检查类中是否有该名称的属性,并成功找到 Bar.__getitem__ .
但这个过程并没有就此结束。 pow_bar2.__getitem__(i)不等于 Bar.__getitem__(i) ,因为 Python 首先检查属性查找会生成一个实现 descriptor protocol 的对象。 .自 Bar.__getitem__function 的一个实例,它确实实现了描述符协议(protocol)。
下一步不是返回函数本身,而是返回 Bar.__dict__['__getitem__'].__get__(pow_bar2, Bar) 的结果。 . (我切换到使用 Bar.__dict__ 来强调我们不会进入触发描述符协议(protocol)的无限循环。)这是 method 的一个实例。 ,它本身是一个可调用的,它传递的是自己的参数,以及 pow_bar2 , 作为原始函数的参数。
因此,pow_bar2.__getitem__(i)相当于 Bar.__dict__['__getitem__'].__get__(pow_bar2, Bar)(i) ,大致相当于 Bar.__dict__['__getitem__'](pow_bar2, i) .

但真的,pow_bar2[i]只是比 pow_bar2.__getitem__(i) 更短且更容易识别(由于其他语言对此语法的数十年支持) . __getitem__是什么使用了 []可扩展到其他类,而不是将其限制为内置类型。

描述符协议(protocol)不仅仅是一个一次性特性,它使实例方法行为看起来比必要的更复杂。它还确定类方法、静态方法和属性的工作方式,并可进一步用于以其他方式自定义属性行为。

关于python - 为什么 `x[i]` 不等于 `x.__getitem__(x)` ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68346125/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com