在新式类中实现 __getitem__ [英] Implementing __getitem__ in new-style classes

查看:70
本文介绍了在新式类中实现 __getitem__的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码:

A 类:def __init__(self):定义方法(自我,项目):打印自我,:正在获取项目",项目self.__getitem__ = types.MethodType(method, self, self.__class__)B类(对象):def __init__(self):定义方法(自我,项目):打印自我,:正在获取项目",项目self.__getitem__ = types.MethodType(method, self, self.__class__)

然后这工作正常:

a = A()[0]

但这不会:

b = B()乙[0]

引发 TypeError.

我发现新式类在类 __dict__ 中寻找魔术方法,而不是在实例 __dict__ 中.这是正确的吗?为什么会这样?你知道任何解释背后想法的文章吗?我试过 RTFM,但可能不是正确的或没有抓住的东西...

非常感谢!保罗

解决方案

这在 Python 数据模型文档中有说明:新式类的特殊方法查找:

<块引用>

对于新样式的类,特殊方法的隐式调用只有在对象类型上定义时才能保证正常工作,而不是在对象的实例字典中.

<块引用>

这种行为背后的基本原理在于许多特殊方法,例如 __hash__()__repr__(),这些方法由所有对象(包括类型对象)实现.如果这些方法的隐式查找使用传统的查找过程,则在类型对象本身上调用它们时会失败[.]

所以,因为 hash(int) hash(1) 都必须工作,所以在类型上查找特殊方法而不是在实例上.如果在对象上直接查找 __hash__()hash(int) 将被转换为 int.__hash__(),然后失败,因为 int.__hash__() 是一个未绑定的方法,它期望在 int() 的实际实例上调用(例如 <代码>1);所以对于 hash(int)type.__hash__() 应该改为调用:

<预><代码>>>>hash(1) == int.__hash__(1)真的>>>hash(int) == type.__hash__(int)真的>>>int.__hash__()回溯(最近一次调用最后一次):文件<stdin>",第 1 行,位于 <module>类型错误:int"对象的描述符__hash__"需要一个参数

这是一个向后不兼容的更改,因此它仅适用于新样式的对象.

I have this code:

class A:
    def __init__(self):
        def method(self, item):
            print self, ": Getting item", item
        self.__getitem__ = types.MethodType(method, self, self.__class__)

class B(object):
    def __init__(self):
        def method(self, item):
            print self, ": Getting item", item
        self.__getitem__ = types.MethodType(method, self, self.__class__)

Then this works fine:

a = A()
a[0]

But this does not:

b = B()
b[0]

raising TypeError.

I found that new-style classes look for magic methods in class __dict__ instead of instance __dict__ . Is this right? Why is it so? Do you know about any article explaining the ideas behind? I tried RTFM, but maybe not the right ones or did not catch the thing...

Thank you very much! Paul

解决方案

This is documented in the Python datamodel documentation: Special method lookup for new-style classes:

For new-style classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.

and

The rationale behind this behaviour lies with a number of special methods such as __hash__() and __repr__() that are implemented by all objects, including type objects. If the implicit lookup of these methods used the conventional lookup process, they would fail when invoked on the type object itself[.]

So, because both hash(int) and hash(1) must work, special methods are looked up on the type instead of on the instance. If __hash__() was looked up straight on the object, hash(int) would be translated to int.__hash__(), and that would fail, because int.__hash__() is an unbound method and it expects to be called on an actual instance of int() (e.g. 1); so for hash(int), type.__hash__() should called instead:

>>> hash(1) == int.__hash__(1)
True
>>> hash(int) == type.__hash__(int)
True
>>> int.__hash__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument

This is a backwards-incompatible change, so it only applies to new-style objects.

这篇关于在新式类中实现 __getitem__的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆