这是从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)
书中的代码包含错误.我已经向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实例中.