通过Python中的子类扩展类型

yan*_*u90 3 python

这是从Learning Python第4版中提取的.它的功能是使用list子类设置.但我不明白第5行list.__init__([]),请帮忙.即使我注释掉这行代码,代码也能正常工作.为什么?

### file: setsubclass.py

class Set(list):
    def __init__(self, value = []):      # Constructor
        list.__init__([])                # Customizes list 
        self.concat(value)               # Copies mutable defaults

    def intersect(self, other):          # other is any sequence
        res = []                         # self is the subject
        for x in self:
            if x in other:               # Pick common items
                res.append(x)
        return Set(res)                  # Return a new Set

    def union(self, other):              # other is any sequence
        res = Set(self)                  # Copy me and my list
        res.concat(other)
        return res

    def concat(self, value):             # value: list, Set . . .
        for x in value:                  # Removes duplicates
            if not x in self:
                self.append(x)

    def __and__(self, other): return self.intersect(other)
    def __or__(self, other):  return self.union(other)
    def __repr__(self):       return 'Set:' + list.__repr__(self)

if __name__ == '__main__':
    x = Set([1,3,5,7])
    y = Set([2,1,4,5,6])
    print(x, y, len(x))
    print(x.intersect(y), y.union(x))
    print(x & y, x | y)
    x.reverse(); print(x)
    x
Run Code Online (Sandbox Code Playgroud)

Lau*_*low 6

书中的代码包含错误.我已经向O'Reilly书籍提交了勘误表,您可以在此页面上阅读作者的回复(搜索982).这是他的回应的一小部分:

自第二版(2003年 - 10年前!)以来,该代码行显然出现在本书中,并且直到现在还没有被成千上万的读者所忽视.

该生产线list.__init__([])缺少变量,并注释掉它使没有任何区别,只是稍微加快你的程序.这是更正后的行:

        list.__init__(self, [])
Run Code Online (Sandbox Code Playgroud)

在类对象上直接调用非静态方法或类方法的方法时,self必须显式提供通常隐式的第一个参数.如果这条线被这样纠正,那么它将遵循Antonis在他的回答中谈到的良好做法.纠正这条线的另一种方法是使用super,这再次使得self参数隐含.

        super(Set, self).__init__([])
Run Code Online (Sandbox Code Playgroud)

书中的代码提供了一个不同的空列表([])作为self参数,这会导致列表再次初始化,因此很快就会被垃圾回收.换句话说,整行是死代码.

要验证原线没有效果很简单:临时改变[]list.__init__([])一个非空列表,并观察所产生的Set实例不包含这些元素.然后插入self第一个参数,并观察列表中的项目现在已添加到Set实例中.