您的代码不能像最初编写的那样工作的原因是您无法在实例中定义魔术方法。根据docs:
对于自定义类,只有在对象的类型上定义,而不是在对象的实例字典中,才能保证特殊方法的隐式调用正常工作。
使用@classmethod来装饰你的魔法方法是将通过__get__获得的绑定方法分配给一个实例。在这两种情况下,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
现在您可以使用>运算符来比较您的类。我并不是说你应该做那样的事情,但肯定存在这种可能性。
问题仍然存在,就像往常一样,为什么你想要首先做这样的事情。