覆盖 Python 元类 __getitem__

Override Python metaclass __getitem__

给定以下代码,我期望 return 值为 'overridden' not 'value1':

class MyMetaclass(type):
  def __new__(cls, name, bases, attrs):
    attrs.update({'_my_dict': {'key1': 'value1', 'key2': 'value2'}})
    return super().__new__(cls, name, bases, attrs)
  def __getitem__(cls, value):
    return cls._my_dict[str(value)]


class MyBaseClass(metaclass=MyMetaclass):
  pass


class MyClass(MyBaseClass):
  @classmethod
  def __getitem__(cls, value):
    return 'overridden'


>>> MyClass['key1']
'value1'  # I expect: 'overridden'

我需要更改什么?

您需要子class元class,在那里覆盖__getitem__,并在新的正则class中设置元class。

__getitem__指的是它所定义的class实例的物品获取行为。

因此,如果您在 metaclass 上定义 __getitem__,它将适用于 classes - 如果您在 [=] 上定义 __getitem__ 28=] 本身,它只适用于 class 的 个实例

但是,您可以编写元class __getitem__,以便它调用 class' __getitem__(如果存在)- 然后模拟此行为:

class MyMetaclass(type):
  def __new__(cls, name, bases, attrs):
    attrs.update({'_my_dict': {'key1': 'value1', 'key2': 'value2'}})
    return super().__new__(cls, name, bases, attrs)
  def __getitem__(cls, value):
    for supercls in cls.__mro__:
         if "__getitem__" in supercls.__dict__:
               # getting the value straight from "__dict__" will prevent Python's mechanisms of converting it to a bound instance method:
               return supercls.__dict__["__getitem__"](cls, value)
    return cls._my_dict[str(value)]


class MyBaseClass(metaclass=MyMetaclass):
  pass


class MyClass(MyBaseClass):
  def __getitem__(cls, value):
    return 'overridden'

请注意,通过这种方式,您甚至可以在我们的层次结构中为 "class_getitem" 使用任何其他方法名称,并且仍然保留通常的 __getitem__ 可供实例使用。