2012-02-27 17 views
4

我對我認爲Python是一個非常簡單直接的列表子類感到困惑。在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 

輸出:

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] 

如此看來,一個標量分配工作,我期望和理解。根據我的理解,列表或切片不起作用。由'不起作用',我的意思是方法中的代碼不會像前兩種方法那樣更改ml的實例。

我該怎麼做才能使cm3()cm4()cm5()工作?

+3

它不是具體到列表中。這就是名稱和賦值如何在Python中工作 - 賦值重新綁定名稱,並且永遠不會修改名稱當前綁定的對象。 – 2012-02-27 03:24:57

+0

@Cat Plus Plus:是的,我懷疑並理解。當然,可以重新分配一個子類列表或使用分片語法?我只是不知道如何通過護目鏡或Python文檔找不到。我仍然對Python類有點綠色...... – dawg 2012-02-27 03:30:06

+0

這取決於你期望「重新分配」的含義。 – 2012-02-27 07:53:54

回答

6

這裏的問題是,在cm3cm4cm5,你是不是修改的對象!您正在成員函數的範圍內創建一個新的,然後將其分配給self。外部範圍不尊重這一點。在cm1cm2中,您正在修改同一個對象,所以對象保持不變。

嘗試使用id功能調試此:

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

... 

m1.cm4() 
print 'DEBUG', id(self) 

你會看到id是不同的。

所以,你可能會問,那麼我該怎麼做呢?您很幸運,您可以使用列表分配拼接。其他數據結構可能不那麼容易。它所做的是保持相同的列表,但替換項目。要做到這一點,這樣做:

self[:] = ... 

因此,舉例來說:

self[:] = self[::-1] 
+2

這就是爲什麼'self'必須在成員函數的簽名中(只要它是第一個位置,您可以隨心所欲地調用它)。在幕後,'ml.cm3'變成了'cm3(ml)'(如果有參數,它們每個都被推回一個位置)。所以'self'就像其他對象參數一樣是通過引用傳遞的,而你只是改變你的本地引用。 – 2012-02-27 04:06:05

2

使用self[:]而不是自己,self = ...只會將自變量重新綁定到其他對象,而不會更改列表對象。

def cm3(self): 
    self[:]=[]   

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

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

你的誤解是self這個詞有一些特殊之處。在這些方法中,它只是一個名稱,就像Python中的任何其他名稱一樣,所以當您重新分配名稱時,您只需將名稱self重新綁定到某個其他對象,而不會改變父對象。事實上,這個論點甚至不需要命名爲self,這只是python程序員使用的一個約定。

這裏是你的會員重新實現正常變異:

def cm3(self): 
    self[:] = [] 

def cm4(self): 
    self.reverse() 

def cm5(self): 
    self[:] = [1,2,3,4,5] 
相關問題