用户列表重载 python 3.x

UserList overloading python 3.x

我正在尝试重载 UserList 方法(添加、追加、扩展)以避免重复。出于某种原因,我仍然得到 alpha 两次。如果我只是尝试打印 original_list,我什至会得到一个空列表 这是我写的代码:

#!/usr/bin/env python
#coding: utf-8

from collections import UserList

class Ulist(UserList):
    def __init__(self, info = []):
        UserList.__init__(self)
        self.info = info

    def __add__(self, something_new):
        for i in something_new:
            if i in self:
                print('%r This is already in the list.' % (i))
            else:
                return UserList.__add__(self, something_new)

    def append(self, something_new):
        if something_new in self:
            print('%r This is already in the list.' % (i))
        else:
            return UserList.append(self, something_new)

    def extend(self, something_new):
        for i in something_new:
            if i in self:
                print('%r This is already in the list.' % (i))
            else:
                return UserList.extend(self, something_new)


# let's test how it works

original_list = Ulist(['alpha'])

original_list.__add__([444])
original_list.append('alpha')
original_list.append('I_dont_exist_yet')
original_list.append(0)
original_list.extend([98, 98, 234,'alpha','beta','I_am_totally_new',33])


print(original_list)

免责声明:我知道有人问过关于 UserList 和方法重载的类似问题。我分析了这些问题,但仍然无法弄清楚为什么我的代码不起作用。另外,我是 Python.

的新手

你想做这样的事情吗?

from collections import UserList

class Ulist(UserList):
    def __init__(self, info = []):
        UserList.__init__(self)
        self.info = info

    def add_iterable(self, iterable):
        for i in iterable:
            if i in self:
                print('%r This is already in the list.' % (i))
            else:
                UserList.append(self, i)
        return self

    def __add__(self, something_new):
        if hasattr(something_new, '__iter__'):
            return self.add_iterable(something_new)
        else:
            return UserList.append(self, something_new)

    def append(self, something_new):
        if something_new in self:
            print('%r This is already in the list.' % (i))
        else:
            return UserList.append(self, something_new)

    def extend(self, something_new):        
        return self.add_iterable(something_new)

测试输出:

98 This is already in the list.

'alpha' This is already in the list.

[444, 'alpha', 'I_dont_exist_yet', 0, 98, 234, 'beta', 'I_am_totally_new', 33]

这只是一个切向的答案,但我强烈建议尝试相互实施类似的操作。例如,__add__ 实际上只是构造后跟一个 extend 操作。而 extend 实际上只是重复了 appends。如果性能不是绝对重要的(并且当您实现自己的 UserList 时,您基本上已经放弃了性能),那么拥有一个已知的良好实现并在术语方面实现其他操作要容易得多那个已知的良好操作。

因此,例如,__add__ 可以实现为:

def __add__(self, other):
    ret = self.__class__(self)  # Alt: self.copy()
    ret.extend(other)
    return ret

所以现在只要你的构造函数和extend方法是正确的,__add__就会自动正确。

然后根据 append:

实施 extend
def extend(self, other):
    for x in other:
        self.append(x)

现在,如果 append 是正确的,那么 extend__add__ 也是正确的。现在,您需要做的就是 append 正确(并且您可以单独测试它,直到您确定它是正确的)。

碰巧,您的 append 已经是正确的(假设 print 是报告错误的合理方式,但通常情况下并非如此)。因此,有了这个 __add__extend,以及一个有效的初始化方法,你就会有有效的代码。

尽管如此,您现有的代码实际上不会正确运行。你的初始化程序是错误的;您将 self.info 设置为可迭代输入,但 self.info 从未被 collections.UserList 使用(它使用 data 属性)。如果你想做一个安全的初始化器,做这样的事情:

def __init__(self, info=()):  # Never use mutable default arguments
    UserList.__init__(self)
    self.extend(info)  # Reuse known good code

同样,这重用了已知的好代码;如果 extend 有效(这又取决于 append),那么这个初始化程序是好的。如果您希望它针对复制场景进行优化,您可以使用 class internals:

来节省重复检查工作
def __init__(self, info=()):
    UserList.__init__(self)
    if isinstance(info, Ulist):
        # Already deduped, copy without duplicate checking
        self.data[:] = info.data
    else:
        self.extend(info)

这个答案的要点是:以零碎碎,don't repeat yourself (mnemonic: DRY)。当它们都是彼此的变体时,不要试图从头开始实现每一种方法。确定单个 "common denominator" 功能,并在此基础上构建,因此任何给定的方法要么只做一件简单的事情,要么根据另一种方法以最小化自定义代码的方式实现。