假设以下课程:
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__
背后的魔力是什么?
答案 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