【问题标题】:why __getitem__ cannot be classmethod?为什么 __getitem__ 不能是类方法?
【发布时间】:2012-09-08 22:44:51
【问题描述】:

假设以下类:

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

getitem 方法的行为符合预期:它接收Class 作为第一个参数,但__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__ 背后有什么魔力?

【问题讨论】:

    标签: python class-method


    【解决方案1】:

    在类上查找特殊方法,而不是在实例上查找 - 与首先在实例上查找的常规方法不同。请参阅 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 上将其定义为类方法。

    【讨论】:

    • Thinking about Class as an instance of type。谢谢你。谢谢你。谢谢。
    【解决方案2】:

    当您调用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
    

    【讨论】:

    • 这就是上述问题的解决方案,但是对于这种语法糖来说编码太多了。在实际代码中,我试图 getitem 对元类本身 :)
    猜你喜欢
    • 1970-01-01
    • 2021-05-21
    • 2011-09-08
    • 1970-01-01
    • 2014-01-03
    • 2011-03-12
    • 1970-01-01
    • 2019-11-15
    • 2010-12-31
    相关资源
    最近更新 更多