2012-02-27 11 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] 

だから、私が期待し、理解とスカラー割り当てが機能しているようです。リストやスライスがわかりません。 「うまくいかない」とは、メソッドのコードが最初の2つのメソッドのようにmlのインスタンスを変更しないことを意味します。

cm3()cm4()cm5()が機能するにはどうすればよいですか?

+3

それはリストに固有ではありません。これは、名前と代入がPythonでどのように動作するかということです。代入は名前を再バインドし、名前が現在バインドされているオブジェクトを変更することはありません。 –

+0

@Cat Plus Plus:はい、私はそれを疑って理解しています。確かに、サブクラス化されたリストの再割り当てやスライス構文の使用は可能ですか?私はちょうどゴーグルやPythonのドキュメントをどのように見つけられないのかわかりません。私はまだPythonクラスで少し緑色です... – dawg

+0

「再割り当て」が意味するものに依存します。 –

答えて

6

ここでの問題はcm3cm4、およびcm5に、あなたがオブジェクトを変更していないということです!メンバー関数のスコープ内で新しいものを作成し、それを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'は他のオブジェクト引数と同様に参照渡しであり、ローカル参照を変更するだけです。 –

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] 
関連する問題