2011-04-07 11 views
6

私はPythonのリストからメソッドを継承するクラスを構築しようとしていますが、上にいくつかの追加のことをしています...この時点で...list.insert()メソッドをPythonのリストのサブクラスとしてエミュレートする

class Host(object): 
    """Emulate a virtual host attached to a physical interface""" 
    def __init__(self): 
    # Insert class properties here... 
    pass 

class HostList(list): 
    """A container for managing lists of hosts""" 
    def __init__(self): 
     self = [] 

    def append(self, hostobj): 
     """append to the list...""" 
     if hostobj.__class__.__name__ == 'Host': 
      self.insert(len(self), hostobj) 
     else: 
      _classname = hostobj.__class__.__name__ 
      raise RuntimeError, "Cannot append a '%s' object to a HostList" % _classname 

私の問題はこれです...私はappend()に行ったようにinsert()上のオブジェクトの入学テストの同じ種類を実行したい場合は、私はコーディングする方法を見つけることができません1つのリスト拡張メソッド(つまりlist.append()list.insert()、またはlist.extend())のサポートを犠牲にすることなく、新しいメソッドを追加できます。私がそれらをすべてサポートしようとすると、私は再帰的なループに巻き込まれます。この問題を回避する最善の方法は何ですか?

EDIT:私は...代わりにPythonのリスト()

結果のコードが...場合にはここに投稿し、それは誰か助けのcollections.MutableSequenceをサブクラス化について提案をした

from collections import MutableSequence 
class HostList(MutableSequence): 
    """A container for manipulating lists of hosts""" 
    def __init__(self, data): 
     super(HostList, self).__init__() 
     if (data is not None): 
      self._list = list(data) 
     else: 
      self._list = list() 

    def __repr__(self): 
     return "<{0} {1}>".format(self.__class__.__name__, self._list) 

    def __len__(self): 
     """List length""" 
     return len(self._list) 

    def __getitem__(self, ii): 
     """Get a list item""" 
     return self._list[ii] 

    def __delitem__(self, ii): 
     """Delete an item""" 
     del self._list[ii] 

    def __setitem__(self, ii, val): 
     # optional: self._acl_check(val) 
     return self._list[ii] 
    def __str__(self): 
     return str(self._list) 
    def insert(self, ii, val): 
     # optional: self._acl_check(val) 
     self._list.insert(ii, val) 
    def append(self, val): 
     self.insert(len(self._list), val) 
+4

'self = []'あなたが思っていることをしません。 –

+1

'super(HostList、self).__ init __(self)'はこのトリックを行います。あなたのコードが(引数)変数 'self'を' [] 'に再割り当てします。 –

+0

スライスが指定されている場合、 '__getitem__'はリストオブジェクトを返します。あなたは、初期化子を '__init __(self、l = None)'に変更することができます。次に、 'HostList(self._list [ii])'を返します。 –

答えて

7

可能性がある場合は、組み込みクラスから継承しないでください。 (あなたはことができますが、それは本当に魅力的な理由もなくべきあなたを意味するものではありません)

これらのクラスは、速度のために最適化され、それはあなたがオーバーライドを持って終了するので、かなり退屈正しく継承ますほとんど全て。

collections.MutableSequenceから継承することで、ほんのいくつかの重要なメソッドを実装し、listを継承するすべての特徴と警告がなくても、完全な機能を備えたシーケンスAPIの実装を得ることができます。

+0

グレートポイント+1 ...いくつかの苦労の後、私は 'collections.MutableSequence'で作業しています...ありがとう! –

6

isinstanceを使用してオブジェクトをチェックして、オブジェクトがHostのインスタンスであるかどうかを確認し、(例:super(HostList, self).insert(...))を使用して、自分で再実装するのではなくlistの機能を使用します。あなたがsuper()で、あなたの方法からlistのメソッドを呼び出すことができ

def append(self, obj): 
    """append to the list...""" 
    if not isinstance(obj, Host): 
     raise RuntimeError, "Cannot append a '%s' object to a HostList" % obj.__class__.__name__ 
    super(HostList, self).append(obj) 
+1

さらに、ホストの場合は 'x'を返す静的メソッド' as_host(x) 'を定義し、それ以外の場合は適切な例外をスローします。その後、「スーパー」コールは1ライナーになります。 –

0

はあなたのようなもので終わる必要があります。そうすれば、他の方法でそれをクラッシュさせる必要はありません。

3

HostListコンテナが変更可能なコンテナインターフェイスを完全にサポートする魅力的な理由がない場合は、is-aではなくhas-aモデルを使用することをお勧めします。スライシング(リストではなく、HostListコンテナを返す)などの操作で、型の一貫性を確保するという余計な負担があります。

関連する問題