Subclassing `frozenset` with multiple `__init__` parameters, and strange behaviour of `__new__`

牧云@^-^@ 提交于 2019-12-12 03:27:39

问题


Before you mark this a duplicate, I have read this question and this question and they don't answer my question (and even seem to confuse me more, not to mention that they're both in Python 2 and I want to know about Python 3). From this question, understand why the following code,

from typing import Hashable


class UnorderedPair(frozenset):
    def __init__(self, left: Hashable, right: Hashable):
        self.left = left
        self.right = right
        super().__init__((left, right))
        if len(self) != 2:
            raise TypeError("There must be 2 distinct elements. Possible duplicate in {{{}, {}}}.".format(left, right))

    def __str__(self):
        return "{{left: {}, right: {}}}".format(self.left, self.right)


if __name__ == '__main__':
    p = UnorderedPair(1, 2)
    print(p)

produces the following error.

TypeError: UnorderedPair expected at most 1 arguments, got 2

It's because I need to override __new__() as well as __init__(). However, this is where it gets confusing for me. Following the answers to the aforementioned question, it looks like I should override __new__() as follows.

from typing import Hashable


class UnorderedPair(frozenset):
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, left: Hashable, right: Hashable):
        self.left = left
        self.right = right
        super().__init__((left, right))
        if len(self) != 2:
            raise TypeError("There must be 2 distinct elements. Possible duplicate in {{{}, {}}}.".format(left, right))

    def __str__(self):
        return "{{left: {}, right: {}}}".format(self.left, self.right)


if __name__ == '__main__':
    p = UnorderedPair(1, 2)
    print(p)

But this gives me the same error. So maybe I should override it as follows (some code omitted because it's the same as before).

def __new__(cls, left: Hashable, right: Hashable):
    return super().__new__(cls, (left, right))

But this gives the following very cryptic error.

    super().__init__((left, right))
TypeError: object.__init__() takes no parameters

What does it have to do with object.__init__()!?!?!? Anyway, perhaps then I should override like the following.

def __new__(cls, left: Hashable, right: Hashable):
    return super().__new__(cls)

But this still gives the same error.

    super().__init__((left, right))
TypeError: object.__init__() takes no parameters

So, how do I do this properly and make it work? (I think my intentions are clear from the non-working definition of the class.)

来源:https://stackoverflow.com/questions/45720451/subclassing-frozenset-with-multiple-init-parameters-and-strange-behavio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!