Python中逆向集合操作符的实际用途

8

在Python中使用反向并集或交集运算符有什么区别吗?

例如,

s & z 对应于 s.__and__(z)

z & s 对应于 s.__rand__(z)

如果这些操作都应该返回相同的结果,为什么需要第一个操作符的反向版本呢?我有什么遗漏的吗?


这是用于左侧对象未实现__and__方法的情况。 - juanpa.arrivillaga
2个回答

3
setfrozenset 遵循数字协议,它们没有明确定义反向操作,但是它们可以通过实现普通方法(如__and__)来获得这些操作。

然而,当处理子类时,反向操作特别有用,因为如果右操作数是左操作数的子类,则首先尝试反向操作。 但是,在普通的setfrozenset中,这没有任何区别,因为它们彼此之间没有继承关系。

如果第一个操作数在其__add__中返回NotImplemented,则这些反向操作也会被使用。但是对于setfrozenset来说,这并不真正有用,因为它们只允许与其他set类似的对象进行操作,并且至少当另一个操作数是另一个set时,setfrozenset不会返回NotImplemented
此外,z & s不对应于s.__rand__(z),除非sz的子类。否则,在尝试s.__rand__(z)之前,将尝试z.__and__(s)
因此,我怀疑反向并集和交集是否有用例,但这应该解释了“为什么存在这些方法”。

你是说如果我创建自定义类,继承自setfrozenset,并且这些类有不同的__and__方法,那么就需要注意顺序和__rand__方法的内容了吗? - MadPhysicist
1
使用setfrozenset时,当你子类化其中一个并尝试与另一个进行操作时,需要注意顺序。如果你子类化了set并实现了__and____rand__方法,当你尝试执行set() & subclass()(=>首先调用subclass.__rand__)或者subclass() & set()(=>首先调用subclass.__and__)时,将会首先调用你的子类方法。但是如果你尝试将这个子类与frozenset一起使用,你需要注意顺序:frozenset() & subclass()将首先调用frozenset.__and__ - MSeifert

0

__rand__ 只有在左操作数不支持相应的操作且操作数类型不同时才会被调用。

我想 s.__rand__(z) 只是在底层调用 z.__and__(s)


由于该操作仅在两个集合之间有效,因此可以保证另一个参数具有正确的方法,否则会出现错误,并且 rand 方法不需要产生它。 - zondo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接