17

假设以下类:

class Class(object):
    @classmethod
    def getitem(*args):
        print 'getitem %s' % (args,)
    @classmethod
    def __getitem__(*args):
        print '__getitem__ %s' % (args,)

getitem 方法的行为符合预期:它作为第一个 arg接收Class,但作为第一个 arg 接收:__getitem__type

calling Class.getitem(test)
getitem (<class '__main__.Class'>, 'test')

calling obj.getitem(test)
getitem (<class '__main__.Class'>, 'test')

calling Class[test]
'type' object has no attribute '__getitem__'

calling obj[test]
__getitem__ (<class '__main__.Class'>, 'test')

背后有什么魔力__getitem__

4

2 回答 2

26

在类上查找特殊方法,而不是在实例上查找 - 与首先在实例上查找的常规方法不同。请参阅Python 数据模型文档中的特殊方法查找

考虑Class作为 的一个实例type,这意味着当您这样做时

Class.getitem(test)

它首先查找您告诉它的内容:在Class自己的属性中调用的方法getitem。但是,当你使用

Class[test]

它跳过这个,直接进入type(作为 的类Class,或其元类),因此调用type.__getitem__(Class, test). 所以,发生的事情不是作为它的第一个参数__getitem__得到type(它仍然会得到Class,如果你明确地这样做Class.__getitem__(test)),它是__getitem__Python 在这种情况下寻找的不存在。要使其存在,您需要定义自己的元类Class,将其定义为实例方法,而不是将其定义Class为类方法。

于 2012-09-16T13:03:45.867 回答
16

当您调用x[test]时,解释器会检查type(x)__getitem__属性。如果是Class[test]Class元类,即type. 如果你想拥有一个类范围的__getitem__,在一个新的元类中定义它。(不用说,这是一种魔法,就像你对元类所做的任何事情一样)

class Meta(type):
    def __getitem__(self, arg):
        print "__getitem__:", arg


class X(object):
    __metaclass__ = Meta

X['hello'] # output: __getitem__ hello
于 2012-09-16T13:02:48.393 回答