是否可以覆盖 Python 元类中的运算符(如 __add__)?
Is it possible to override operators (like __add__) in a Python metaclass?
在我的用例中,如果我可以实现添加 类,而不是它们的对象,那就太好了。 Python 有可能吗?我的 IDE 将 __add__
显示为 type
的方法。
我怎样才能正确覆盖它?
否则,我正在考虑跟随可怕的forbidden way of doing things,也许是猴子补丁type
。
class MyClass:
def __add__(self, other):
return "some funny result"
# Works fine!
MyClass() + MyClass()
class MyClassOperand(type):
def __new__(cls, *args, **kwargs):
"""Here, there will be things to instantiate the real MyClass ..."""
# return object.__new__(cls)
def __add__(self, other):
return "some funny result"
# TypeError: unsupported operand type(s) for +: 'type' and 'type'
MyClassOperand + MyClassOperand
基于,我是这样做的:
class MyMetaClass(type):
def __add__(self, other):
return "some META funny result"
class MyClass(metaclass=MyMetaClass):
def __add__(self, other):
return "some funny result"
# Works fine: "some funny result"
print(MyClass() + MyClass())
# Works fine: "some META funny result"
print(MyClass + MyClass)
有效 -
一个更实用的例子是简单的元类,它将创建一个新的组合子类,添加 类。前提是 类 有效
协同使用 super()
调用,它确实可以正常工作:
class Addable(type):
def __add__(cls, other_cls): # All metaclass methods receive classes as their "self" parameters
# so they are effectively "class methods" for those
meta = type(cls) # this should be "Addable" itself, or a composed subclass of it
new_cls = meta(
f"Composed{cls.__name__}{other_cls.__name__}",
(cls, other_cls), # base classes
{}, # empty namespace
)
return new_cls
# Example:
class Base(metaclass=Addable):
pass
class Cls1(Base):
def __init__(self, *args, **kwargs):
self.parameter1 = kwargs.pop("parameter1", None)
super().__init__(*args, **kwargs)
def m1(self):
print("method 1")
class Cls2(Base):
def __init__(self, *args, **kwargs):
self.parameter2 = kwargs.pop("parameter2", None)
super().__init__(*args, **kwargs)
def m2(self):
print("method 2")
Cls3 = Cls1 + Cls2
并将其粘贴到终端上:
In [8]: Cls3().m2()
method 2
In [9]: Cls3(parameter1 = "bla").parameter1
Out[9]: 'bla'
在我的用例中,如果我可以实现添加 类,而不是它们的对象,那就太好了。 Python 有可能吗?我的 IDE 将 __add__
显示为 type
的方法。
我怎样才能正确覆盖它?
否则,我正在考虑跟随可怕的forbidden way of doing things,也许是猴子补丁type
。
class MyClass:
def __add__(self, other):
return "some funny result"
# Works fine!
MyClass() + MyClass()
class MyClassOperand(type):
def __new__(cls, *args, **kwargs):
"""Here, there will be things to instantiate the real MyClass ..."""
# return object.__new__(cls)
def __add__(self, other):
return "some funny result"
# TypeError: unsupported operand type(s) for +: 'type' and 'type'
MyClassOperand + MyClassOperand
基于
class MyMetaClass(type):
def __add__(self, other):
return "some META funny result"
class MyClass(metaclass=MyMetaClass):
def __add__(self, other):
return "some funny result"
# Works fine: "some funny result"
print(MyClass() + MyClass())
# Works fine: "some META funny result"
print(MyClass + MyClass)
有效 -
一个更实用的例子是简单的元类,它将创建一个新的组合子类,添加 类。前提是 类 有效
协同使用 super()
调用,它确实可以正常工作:
class Addable(type):
def __add__(cls, other_cls): # All metaclass methods receive classes as their "self" parameters
# so they are effectively "class methods" for those
meta = type(cls) # this should be "Addable" itself, or a composed subclass of it
new_cls = meta(
f"Composed{cls.__name__}{other_cls.__name__}",
(cls, other_cls), # base classes
{}, # empty namespace
)
return new_cls
# Example:
class Base(metaclass=Addable):
pass
class Cls1(Base):
def __init__(self, *args, **kwargs):
self.parameter1 = kwargs.pop("parameter1", None)
super().__init__(*args, **kwargs)
def m1(self):
print("method 1")
class Cls2(Base):
def __init__(self, *args, **kwargs):
self.parameter2 = kwargs.pop("parameter2", None)
super().__init__(*args, **kwargs)
def m2(self):
print("method 2")
Cls3 = Cls1 + Cls2
并将其粘贴到终端上:
In [8]: Cls3().m2()
method 2
In [9]: Cls3(parameter1 = "bla").parameter1
Out[9]: 'bla'