在python类上重写_或_运算符

在python类上重写_或_运算符,python,operator-overloading,Python,Operator Overloading,作为一个人为的例子,假设我正在用python生成一个随机的果篮。我创建了一个篮子: basket = FruitBasket() 现在我想指定篮子中可能出现的水果的特定组合。假设我是一个非常挑剔的家伙,篮子里要么装满苹果、石榴、桔子和葡萄柚,要么只有香蕉 我在阅读python操作符重载,似乎我可以定义\uuuuu或类别(类型): ... 定义或(自身、其他): ... 返回或(自身、其他) ... >>>类水果(对象): ... __元类\水果元 ..

作为一个人为的例子,假设我正在用python生成一个随机的果篮。我创建了一个篮子:

basket = FruitBasket()
现在我想指定篮子中可能出现的水果的特定组合。假设我是一个非常挑剔的家伙,篮子里要么装满苹果、石榴、桔子和葡萄柚,要么只有香蕉

我在阅读python操作符重载,似乎我可以定义
\uuuuu或
\uuu和
来获得我想要的行为。我想我可以这样做:

basket.fruits = (Apple() & Pomegranate()) | (Banana()) | (Orange() & Grapefruit())
TypeError: unsupported operand type(s) for |: 'type' and 'type'
这在创建两个类(
)时非常有效。当调用
\uuuuu或
\uuuuu和时,我只需返回一个新的
对象:

def __or__(self, other):
    return Or(self, other)

def __and__(self, other):
    return And(self, other)
我想弄明白的是,我如何做到这一点,而不必先实例化水果?为什么我不能在base
Fruit
类上使用静态的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu或
方法?我试过这个,但不起作用:

class Fruit(object):
    @classmethod
    def __or__(self, other):
        return Or(self, other)
分配水果:

basket.fruits = (Apple & Pomegranate) | (Orange & Grapefruit) | (Banana)
我得到一个类似这样的错误:

basket.fruits = (Apple() & Pomegranate()) | (Banana()) | (Orange() & Grapefruit())
TypeError: unsupported operand type(s) for |: 'type' and 'type'
关于如何实现这一点有什么想法吗?

您不能将特殊(hook)方法作为类方法添加到类中,因为它们总是根据当前对象的类型进行查找;对于类中的实例,对于类,将在
type
上查找它们。请参阅,了解其动机,了解其原因

这意味着您需要在服务器上实现这一点;元类充当类的类型:

class FruitMeta(type):
    def __or__(cls, other):
        return Or(cls, other)

    def __and__(cls, other):
        return And(cls, other)
然后对于Python 3:

class Fruit(metaclass=FruitMeta):
或Python 2:

class Fruit(object):
    __metaclass__ = FruitMeta

\uuuu或uuu
是根据对象的类型查找的;对于
水果
实例,这将是
水果
;对于
水果
,即
类型
。不过,您可以使用元类更改
水果的类型:

class FruitMeta(type):

    def __or__(self, other):
        return Or(self, other)


class Fruit(object):
    __metaclass__ = FruitMeta
(对于Python3,语法是
classfruit(metaclass=FruitMeta):

这样你就可以随心所欲了
Apple | Banana
(假设这两个是
Fruit
的子类)将产生
或(Apple,Banana)

不过,对这种设计要非常小心。它倾向于魔法领域,很容易引起混乱

(完整演示,使用Python 2.7:)

类或(对象): ... 定义初始化(self,a,b): ... self.a=a ... self.b=b ... 定义报告(自我): ... 返回'Or({!r},{!r})'.format(self.a,self.b) ... >>>类别(类型): ... 定义或(自身、其他): ... 返回或(自身、其他) ... >>>类水果(对象): ... __元类\水果元 ... >>>苹果(水果)班:及格 ... >>>香蕉(水果)班:通过 ... >>>苹果香蕉 或(,)
正是我想要找到的!谢谢效果很好