[英]Python __index__ special method
>>> class Thing(object):
... def __index__(self):
... return 1
...
>>> thing = Thing()
>>> list_ = ['abc', 'def', 'ghi']
>>> list_[thing]
'def'
>>> dict_ = {1: 'potato'}
>>> dict_[thing]
# KeyError
How does thing
know to represent itself as 1 when accessed by a list, but not by a dict? 当通过列表访问时, thing
如何知道将自己表示为1,而不是通过字典来表示? Don't both magic methods go through __getitem__
? 这两种魔术方法都不能通过__getitem__
吗? The usage shown for lists could go through __int__
instead so what is the raison d'être for __index__
anyway? 列表显示的用法可以通过__int__
代替__int__
的存在理由是__index__
?
@BenoîtLatinier was correct when he said: 当他说:@BenoîtLatinier是正确的
Dict and List does not implement
__getitem__
the same way. Dict和List没有以相同的方式实现__getitem__
。
However, I'd like to add a little more information. 但是,我想补充一点信息。 According to the documentation : 根据文件 :
object.__index__(self)
Called to implement
operator.index()
, and whenever Python needs to losslessly convert the numeric object to an integer object ( such as in slicing , or in the built-inbin()
,hex()
andoct()
functions). 调用实现operator.index()
,并且只要Python需要无损地将数字对象转换为整数对象( 例如在切片中 ,或在内置bin()
,hex()
和oct()
函数中)。 Presence of this method indicates that the numeric object is an integer type. 此方法的存在表明数字对象是整数类型。 Must return an integer. 必须返回一个整数。
The part I bolded is important. 我加粗的部分很重要。 Indexing and slicing on a list are both handled by the same method (namely, __getitem__
). 列表上的索引和切片都由相同的方法处理(即__getitem__
)。 So, if Thing.__index__
is called for slicing, it will likewise be called for indexing since we are using the same method. 因此,如果调用Thing.__index__
进行切片,则同样会调用它进行索引,因为我们使用相同的方法。 This means that: 这意味着:
list_[thing]
is roughly equivalent to: 大致相当于:
list_[thing.__index__()]
For the dictionary however, Thing.__index__
is not being called (there is no reason to call it since you cannot slice a dictionary). 然而,对于字典,没有调用Thing.__index__
(因为你不能对字典进行切片,所以没有理由调用它)。 Instead, doing dict_[thing]
is telling Python to find a key in the dictionary that is the thing
instance itself. 相反,做dict_[thing]
告诉Python在字典中查找thing
本身的一个键。 Since this doesn't exist, a KeyError
is raised. 由于这不存在,因此引发了KeyError
。
Perhaps a demonstration will be helpful: 也许演示会有所帮助:
>>> class Thing(object):
... def __index__(self):
... print '__index__ called!'
... return 1
...
>>> thing = Thing()
>>> list_ = ['abc', 'def', 'ghi']
>>> list_[thing] # __index__ is called
__index__ called!
'def'
>>>
>>> dict_ = {1: 'potato'}
>>> dict_[thing] # __index__ is not called
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: <__main__.Thing object at 0x01ACFC70>
>>>
>>> dict_ = {thing: 'potato'} # Works if thing is a key
>>> dict_[thing]
'potato'
>>>
As for why __index__
exists in the first place, the reason is thoroughly listed in PEP 0375 . 至于为什么__index__
存在,原因在PEP 0375中彻底列出。 I won't repeat all of it here, but basically it is so that you can allow arbitrary objects to serve as integers, which is needed in slicing as well as a few other applications. 我不会在这里重复所有这些,但基本上它是这样你可以允许任意对象作为整数,这在切片以及一些其他应用程序中是必需的。
Dict and List does not implement __getitem__
the same way. Dict和List没有以相同的方式实现__getitem__
。 Dict objects uses a comparison ( __eq__
) on __hash__
of objects as key to use in __getitem__
. Dict对象使用对象的__hash__
上的比较( __eq__
)作为__getitem__
使用的键。
To make Thing
usable for dict you have to implement both hash and eq. 为了使Thing
可用于dict,你必须同时实现hash和eq。
Another example to understand it further, here _MolsToGridSVG takes a list argument. 进一步理解它的另一个例子,这里_MolsToGridSVG采用list参数。 I wanted to limit the list to some length. 我想将列表限制到一定程度。 Now here for python list, slice indices have to be used. 现在这里是python列表,必须使用切片索引。 The following implementation solved it. 以下实现解决了它。 Basically here index is getting used for Python List. 基本上这里索引被用于Python List。
def __index__(self):
return 1
imagesInOneFile = int(len(smilesMolList) / noOfFiles)
svg = Draw._MolsToGridSVG(smilesMolList[:imagesInOneFile.__index__()], subImgSize=(400, 200), molsPerRow=2)
Also one needs to remember that imagesInOneFile
has to be integer. 还需要记住imagesInOneFile
必须是整数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.