覆盖 __add__method

Override __add__method

我正在尝试覆盖 __add__ 方法,以便不会添加重复项。我的代码出了什么问题?

class Ulist(UserList):

    def __init__(self,value=[]):
        UserList.__init__(self)
        self.value = value

    def __add__(self,addvalue):
        for x in addvalue:
            if x in self.value:
                print("It already exists")
            else:
                return self.value.__add__(addvalue)

如果 Ulist=[1,2,3],而我 Ulist.__add__([3]),我期待一条消息“它已经存在 ”。但是我得到了 [1,2,3,3].

您已将 Ulist 初始化为变量,因此它将充当列表的对象:

要使用您的代码,您需要实例化 class 的对象,请参见下面的示例

class Ulist():

    def __init__(self, value=[]):

        self.value = value

    def __add__(self, addvalue):
        for x in addvalue:
            if x in self.value:
                print("It already exists")
            else:
                return self.value.__add__(addvalue)


o = Ulist(value=[1, 2, 3])

o.__add__([3])

print o.value

输出

It already exists
[1, 2, 3]

在 Python 中一切都是对象,包括 classes、模块、列表等。您可以通过绑定到的名称访问对象。

当您编写 class Ulist(UserList): ... 时,您将 class 对象绑定到名称 Ulist。由于 classes 是常规对象,您可以执行类似

Vlist = Ulist
x = Vlist()

这将产生与直接调用 Ulist 相同的结果,因为第一个赋值只是将 class 绑定到另一个名称。

当您随后执行 Ulist = [1, 2, 3] 时,您会丢弃名称 Ulist 最初绑定到的 class 对象,并将其绑定到列表对象。这是因为方括号中的表达式总是被解释为普通 list.

要创建 Ulist 和 class 的实例,您必须调用初始化程序:

x = Ulist([1, 2, 3])

现在操作 x + [3] 应该会打印出您最初预期的结果。请注意,您通常不应该直接调用 __add__ 等特殊方法。要么使用 +,要么更少地使用 operator.add.

要记住的另一件事是 UserList already exposes the underlying list via the data 属性。您的 value 属性在这一点上有点矫枉过正,实际上会阻止您使用 UserList 的所有其他不错的功能。更好的实现看起来像

class Ulist(UserList):

    def __init__(self, value=[]):
        super().__init__(value)

    def __add__(self, addvalue):
        for x in addvalue:
            if x in self:
                print(f"{x!r} already exists")
            else:
                return super().__add__(addvalue)

总而言之,您可能正在寻找的是 set