如何让我的 Python `set` 和 `frozenset` 子类在进行二元运算时保留它们的类型?
How can I make my Python `set` and `frozenset` subclasses preserve their types when engaging in binary operations?
我分别有一些set
和frozenset
子类、OCDSet
和OCDFrozenSet
。当我在二元运算中将它们与它们的祖先 类 的实例一起使用时,祖先 类 支配结果的类型——我的意思是,当我做类似减去 OCDFrozenSet
的事情时从 frozenset
,我得到一个 frozenset
… 但如果我在操作中反转类型也是如此(即从 OCDFrozenSet
.[=22 中减去 frozenset
=]
像这样:
… 令我特别反直觉的是,使用 -=
(就地减法)会改变现有实例的类型!
我对如何处理这类事情的了解完全来自 C++,其中操作的类型是在(可能是模板化的)运算符重载函数中明确指定的已成定局;在 Python 中,类型系统通常更加隐含,但它并不像我现在相信的就地操作那样可变不可预测。
那么,解决这个问题最方便的方法是什么——我假设它涉及覆盖感兴趣的子类中的一些双下划线实例方法?
就地操作不保证它们会就地更新对象,这完全取决于对象的类型。
元组、frozenset 等是不可变类型,因此无法就地更新它们。
来自 library reference 就地运算符:
For immutable targets such as strings, numbers, and tuples, the updated value is computed, but not assigned back to the input variable.
同样 frozenset
文档也提到了同样的事情 about in-place operations[source]:
The following table lists operations available for set that do not apply to immutable instances of frozenset.
现在,由于您的 OCDFrozenSet
没有实现 __isub__
,它将回退到 __sub__
方法,该方法将 return 基础类型 class frozenset
。使用基数 class 是因为 Python 不知道基数 class 对 __sub__
操作中新创建的 frozenset
期望的参数。
更重要的是,这是 bug in Python 2 where such operation returned the subclass instance, the fix was only ported to Python 3 虽然可以防止破坏现有系统。
要获得预期的输出,您可以在 subclass:
中提供所需的方法
class OCDFrozenSet(frozenset):
def __sub__(self, other):
return type(self)(super().__sub__(other))
def __rsub__(self, other):
return type(self)(super().__rsub__(other))
我分别有一些set
和frozenset
子类、OCDSet
和OCDFrozenSet
。当我在二元运算中将它们与它们的祖先 类 的实例一起使用时,祖先 类 支配结果的类型——我的意思是,当我做类似减去 OCDFrozenSet
的事情时从 frozenset
,我得到一个 frozenset
… 但如果我在操作中反转类型也是如此(即从 OCDFrozenSet
.[=22 中减去 frozenset
=]
像这样:
… 令我特别反直觉的是,使用 -=
(就地减法)会改变现有实例的类型!
我对如何处理这类事情的了解完全来自 C++,其中操作的类型是在(可能是模板化的)运算符重载函数中明确指定的已成定局;在 Python 中,类型系统通常更加隐含,但它并不像我现在相信的就地操作那样可变不可预测。
那么,解决这个问题最方便的方法是什么——我假设它涉及覆盖感兴趣的子类中的一些双下划线实例方法?
就地操作不保证它们会就地更新对象,这完全取决于对象的类型。
元组、frozenset 等是不可变类型,因此无法就地更新它们。
来自 library reference 就地运算符:
For immutable targets such as strings, numbers, and tuples, the updated value is computed, but not assigned back to the input variable.
同样 frozenset
文档也提到了同样的事情 about in-place operations[source]:
The following table lists operations available for set that do not apply to immutable instances of frozenset.
现在,由于您的 OCDFrozenSet
没有实现 __isub__
,它将回退到 __sub__
方法,该方法将 return 基础类型 class frozenset
。使用基数 class 是因为 Python 不知道基数 class 对 __sub__
操作中新创建的 frozenset
期望的参数。
更重要的是,这是 bug in Python 2 where such operation returned the subclass instance, the fix was only ported to Python 3 虽然可以防止破坏现有系统。
要获得预期的输出,您可以在 subclass:
中提供所需的方法class OCDFrozenSet(frozenset):
def __sub__(self, other):
return type(self)(super().__sub__(other))
def __rsub__(self, other):
return type(self)(super().__rsub__(other))