在Python中对列表进行子类化.为什么切片和空列表不起作用?

daw*_*awg 4 python list subclass

我对我认为是Python中列表的一个非常简单和直接的子类感到困惑.

假设我想要列表的所有功能.我想在列表的默认集中添加几个方法.

以下是一个例子:

class Mylist(list):

    def cm1(self):
        self[0]=10

    def cm2(self):
        for i,v in enumerate(self):
            self[i]=self[i]+10        

    def cm3(self):
        self=[]         

    def cm4(self):
        self=self[::-1]

    def cm5(self):
        self=[1,2,3,4,5]       

ml=Mylist([1,2,3,4])
ml.append(5)
print "ml, an instance of Mylist: ",ml
ml.cm1()
print "cm1() works: ",ml

ml.cm2()
print "cm2() works: ",ml

ml.cm3() 
print "cm3() does NOT work as expected: ",ml     

ml.cm4()
print "cm4() does NOT work as expected: ",ml     

ml.cm5()
print "cm5() does NOT work as expected: ",ml  
Run Code Online (Sandbox Code Playgroud)

输出:

Mylist:  [1, 2, 3, 4, 5]
cm1() works:  [10, 2, 3, 4, 5]
cm2() works:  [20, 12, 13, 14, 15]
cm3() does NOT work as expected:  [20, 12, 13, 14, 15]
cm4() does NOT work as expected:  [20, 12, 13, 14, 15]
cm5() does NOT work as expected:  [20, 12, 13, 14, 15]
Run Code Online (Sandbox Code Playgroud)

因此,标量赋值看起来像我期望和理解的那样有效.列表或切片不能像我理解的那样工作.通过"不起作用",我的意思是方法中的代码不会像前两个方法那样改变ml的实例.

我需要做什么做的,这样cm3() cm4()cm5()工作?

Don*_*ner 6

这里的问题是,在cm3,cm4cm5,你没有修改对象!您正在成员函数的范围内创建一个新的,然后将其分配给self.外部范围不尊重这一点.在cm1和中cm2,您正在修改同一个对象,因此该对象保持不变.

尝试使用该id函数来调试:

def cm4(self):
    self=self[::-1]
    print 'DEBUG', id(self)

...

m1.cm4()
print 'DEBUG', id(self)
Run Code Online (Sandbox Code Playgroud)

你会发现它id是不同的.

所以,你可能会问,我该怎么做?您很幸运,您可以将列表分配到拼接中.对于其他数据结构,这可能不那么容易.这样做是保持相同的列表,但替换项目.为此,请执行以下操作:

self[:] = ...
Run Code Online (Sandbox Code Playgroud)

所以,例如:

self[:] = self[::-1]
Run Code Online (Sandbox Code Playgroud)

  • 这就是为什么`self`必须在成员函数的签名中(你可以随意调用它,只要它的第一个位置).在幕后,`ml.cm3`变成`cm3(ml)`(如果有参数,它们每个都会被推回一个位置).所以`self`就像其他对象参数一样是传递引用,而你只是改变你的本地引用. (2认同)