为什么__getitem__不能成为classmethod?

时间:2012-09-16 12:56:56

标签: python class-method

假设以下课程:

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

getitem方法按预期运行:它接收Class作为第一个arg,但__getitem__接收type作为第一个arg:

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__背后的魔力是什么?

2 个答案:

答案 0 :(得分:21)

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

Class视为type的实例,这意味着何时执行

Class.getitem(test)

首先看看你告诉它的确切内容:Class自己的属性getitem中的方法。但是,当你使用

Class[test]

它会跳过这个,然后直接转到type(作为Class或其元类的类),因此调用type.__getitem__(Class, test)。那么,正在发生的事情不是__getitem__得到type作为它的第一个参数(它仍然会得到Class,就像你明确地Class.__getitem__(test))那样,它就是在这种情况下Python查找的__getitem__不存在。要使它存在,您需要为Class定义自己的元类,将其定义为实例方法,而不是在Class上将其定义为类方法。

答案 1 :(得分:11)

当您致电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