set 和 freezeset 的继承行为似乎不同

发布于 2024-10-15 08:49:37 字数 579 浏览 14 评论 0原文

有人可以解释以下行为:令

class derivedset1(frozenset):
    def __new__(cls,*args):
        return frozenset.__new__(cls,args)  

class derivedset2(set):
    def __new__(cls,*args):
        return set.__new__(cls,args)    

a=derivedset1('item1','item2') # WORKS 
b=derivedset2('item1','item2') # DOESN'T WORK

Traceback (most recent call last):
  File "inheriting-behaviours.py", line 12, in <module>
    b=derivedset2('item1','item2') # DOESN'T WORK
TypeError: derivedset2 expected at most 1 arguments, got 2

我惊讶的是,您可以更改冻结集的构造函数,而可变集的构造函数则不可能。

Can someone explain the following behaviour:

class derivedset1(frozenset):
    def __new__(cls,*args):
        return frozenset.__new__(cls,args)  

class derivedset2(set):
    def __new__(cls,*args):
        return set.__new__(cls,args)    

a=derivedset1('item1','item2') # WORKS 
b=derivedset2('item1','item2') # DOESN'T WORK

Traceback (most recent call last):
  File "inheriting-behaviours.py", line 12, in <module>
    b=derivedset2('item1','item2') # DOESN'T WORK
TypeError: derivedset2 expected at most 1 arguments, got 2

This is surprising to me that you can alter the constructor of a frozen set whereas it is not possible for the constructor of a mutable set.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

野心澎湃 2024-10-22 08:49:37

来自 Python 文档

如果__new__()返回cls的实例,那么新实例的__init__()方法将像__init__一样被调用(self[, ...]),其中 self 是新实例,其余参数与传递给 __new__() 的参数相同。< /p>

set.__init__ 仅采用一个参数,即一个指定初始设置内容的可迭代对象。因此,您应该添加自己的初始化程序,它接受所有附加参数并将它们提供为初始设置值:

class derivedset2(set):
    def __new__(cls,*args):
        return set.__new__(cls,*args)

    def __init__(self, *initial_values):
        set.__init__(self, initial_values)

请注意,您应该覆盖 __init__ 并避免实现 __new__ ,除非您想要实现对象缓存、单例或类似奇怪的东西。您的子类化适用于 frozenset 正是因为 frozenset 确实从对象缓存中获益,即 Python 解释器只需要一个 frozenset具有相同内容的两个 frozenset 对象的实例。

一般来说,您应该避免对内置类进行子类化,特别是如果您的语义不兼容(在本例中为 set([])衍生集2([]) 返回完全不同的结果)。

From the Python documentation:

If __new__() returns an instance of cls, then the new instance’s __init__() method will be invoked like __init__(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to __new__().

set.__init__ only takes one argument, an iterable specifying the initial set contents. Therefore, you should add your own initializer which takes all additional arguments and supplies them as the initial set values:

class derivedset2(set):
    def __new__(cls,*args):
        return set.__new__(cls,*args)

    def __init__(self, *initial_values):
        set.__init__(self, initial_values)

Notice that you should overwrite __init__ and refrain from implementing __new__ unless you want to implement object caching, singletons, or similar weird stuff. Your subclassing works for frozenset precisely because frozenset does profit from object caching, i.e. the Python interpreter only needs one frozenset instance for two frozenset objects with the same content.

In general, you should refrain from sub-classing built-in classes, especially if your semantics are incompatible (in this case, set([]) and derivedset2([]) return totally different results).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文