gpt4 book ai didi

python - 让一元运算符与 Python 类一起工作

转载 作者:太空狗 更新时间:2023-10-30 01:56:48 34 4
gpt4 key购买 nike

代码:

>>> class Negative: 
... pass

>>> class Positive:
... @classmethod
... def __neg__(cls):
... return Negative

所以我试试

>>> -Positive is Negative
TypeError: bad operand type for unary -: 'type'

这虽然有效

>>> -Positive() is Negative
True

其他一元运算符及其相关的“魔术”方法也是如此(例如~__invert__+__pos__ 等)。

为什么它适用于实例而不适用于类?我怎样才能让它发挥作用?

编辑:我已经按照建议修改了代码,以在元类中移动魔法方法。

class Negative: pass

class PositiveMeta(type):
def __neg__(cls):
return Negative

class Positive(metaclass=PositiveMeta): pass

最佳答案

你的代码不能像最初写的那样工作的原因是你不能在实例中定义魔术方法。根据docs :

For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.

这适用于类(它们是某些元类的实例),就像它适用于“常规”对象一样。从这个意义上说,这个问题等同于以下任何一个:Overriding special methods on an instance , Why does Python's bool builtin only look at the class-level __bool__ method , Assigning (instead of defining) a __getitem__ magic method breaks indexing .

@classmethod 装饰你的魔法方法类似于将通过__get__ 获得的绑定(bind)方法分配给一个实例。在这两种情况下,Python 都会简单地忽略类中未定义的任何描述符。

这也是 -Positive() is Negative 起作用的原因。当您否定 Positive 的实例时,解释器会在类中查找 __neg__。用 @classmethod 装饰在这里完全是多余的,因为您无论如何都会忽略输入参数。但现在您有了一个返回类对象的神奇方法。

要在类对象上正确定义魔术方法,您需要在元类上定义它:

class MetaPositive(type):
def __neg__(self):
return Negative

class Negative: pass

class Positive(metaclass=MetaPositive): pass

有趣的是,这并不局限于一元运算符。您可以在元类上定义任何 dunder 方法并让您的类支持相应的操作:

class MetaPositive(type):
def __gt__(self, other):
if other is Negative:
return True
return False

现在您可以使用 > 运算符来比较您的类。我并不是在暗示你应该做那样的事情,但这种可能性肯定存在。

问题仍然存在,就像它经常发生的那样,即为什么您首先要做这样的事情。

关于python - 让一元运算符与 Python 类一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48003943/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com