Override Python metaclass __getitem__

你。 提交于 2021-02-11 06:29:29

问题


Given the following code, I expect a return value of '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'

What do I need to change?


回答1:


__getitem__ refers to the item-getting behaviors of the instances of the class it is defined on.

So, if you define a __getitem__ on the metaclass, it will work for the classes - if you write a __getitem__ on the class itself, it will only work for instances of that class.

You can however, write the metaclass __getitem__ so that it calls the class' __getitem__ if it exists - and then emulate this behavior:

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'

Note that in this way, you could even use any other method name for a "class_getitem" in our hierarchy and still leave the usual __getitem__ available to be used by instances.




回答2:


You need to subclass the metaclass, override __getitem__ there, and set that metaclass in a new regular class.



来源:https://stackoverflow.com/questions/60781584/override-python-metaclass-getitem

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!