有没有简单的方法在不重新定义所有运算符的情况下子类化Python的集合?
有没有办法去创建一个新的类,基于 set
这个集合类型,并且在使用二元运算符时返回这个新类的类型,而不需要重新定义这些运算符?
举个例子:
class A(set):
pass
a = A([1,2,3]) & A([1,2,4])
a.__class__ == A # it's False, and I would like it to be true without redefining all operators
注意,这个问题:如何正确(或最佳)地创建一个新的 Python 集合类,并添加一个新的实例变量? 已经有10年了,提供的答案只适用于 Python 2.x。这就是我为什么要问一个关于 Python 3.x(特别是 Python ≥ 3.8)的新问题。
2 个回答
1
看起来你确实需要重新定义一些集合方法,但只需要重新定义那些返回set
对象的方法,这一共只有13个方法,而且这些方法的代码都是模板代码。
下面是一个例子:
class ASet(set):
def __repr__(self):
return f'ASet({set(self)})'
def __and__(self, other):
return self.__class__(super().__and__(other))
def __or__(self, other):
return self.__class__(super().__or__(other))
def __rand__(self, other):
return self.__class__(super().__rand__(other))
def __ror__(self, other):
return self.__class__(super().__ror__(other))
def __rsub__(self, other):
return self.__class__(super().__rsub__(other))
def __rxor__(self, other):
return self.__class__(super().__rxor__(other))
def __sub__(self, other):
return self.__class__(super().__sub__(other))
def __xor__(self, other):
return self.__class__(super().__xor__(other))
def copy(self, other):
return self.__class__(super().copy(other))
def difference(self, other):
return self.__class__(super().difference(other))
def intersection(self, other):
return self.__class__(super().intersection(other))
def symmetric_difference(self, other):
return self.__class__(super().symmetric_difference(other))
def union(self, other):
return self.__class__(super().union(other))
3
我认为答案是“没有”。
我快速浏览了一下参考实现,发现对于 set_and()
的所有路径,最终都返回 NULL
或者调用 make_new_set_basetype()
的结果。
这个方法目前是 这样实现的:
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
{
if (type != &PySet_Type && type != &PyFrozenSet_Type) {
if (PyType_IsSubtype(type, &PySet_Type))
type = &PySet_Type;
else
type = &PyFrozenSet_Type;
}
return make_new_set(type, iterable);
}
所以,如果你没有在子类中重写 __and__()
,你得到的结果将是一个 set()
或者一个 frozenset()
。