2016-12-08 9 views
3

あるクラスの__getitem__をそれと他のリストの同じインデックスにあるアイテムの合計にしたいと考えています。オーバーロードされた__getitem__別の引数を受け入れる

>>> class Test(list): 
    def __init__(self): 
     self.extend([1, 2, 3]) 
    def __getitem__(self, index, other): 
     return self[index] + other[index] 
>>> t = Test() 
>>> t2 = [4, 5, 6] 

はしかし、私の2回の試行は、エラーをもたらした:

>>> t[5, t2] 
Traceback (most recent call last): 
    File "<pyshell#24>", line 1, in <module> 
    t[5, t2] 
TypeError: __getitem__() missing 1 required positional argument: 'other' 
>>> t.__getitem__(5, t2) 
Traceback (most recent call last): 
    File "<pyshell#26>", line 1, in <module> 
    t.__getitem__(5, t2) 
    File "<pyshell#17>", line 5, in __getitem__ 
    return self[index] + other[index] 
TypeError: __getitem__() missing 1 required positional argument: 'other' 

__getitem__複数の引数を与えることが可能ですか?もしそうなら、どうですか?そうでない場合は、それをエミュレートする方法はありますか?

答えて

2

あなたが__getitem__ない複数のパラメータに「インデックス」のタプルを取得するので、それが可能である:

class Test(list): 
    def __init__(self): 
     self.extend([1, 2, 3]) 

    def __getitem__(self, value): 
     # this makes sure that a sequence with exactly 2 elements is passed in: (thanks @ShadowRanger) 
     index, other = value 
     return super().__getitem__(index) + other[index] 

>>> t = Test() 
>>> t2 = [4, 5, 6] 
>>> t[2, t2] 
9 # 3 + 6 
>>> t[1, t2] 
7 # 2 + 5 
>>> t[0, t2] 
5 # 1 + 4 

しかし、いくつかの注意点があります:あなたが明示的にあなたドンをsuper().__getitem__を呼び出す必要があり

  • 再帰で終わることはない。
  • 通常のスライスを許可する場合は、__getitem__に渡される引数の数に注意する必要があります。
  • この現象はユーザーを混乱させるので、実際には使用しないことをおすすめします。
+1

期待以上に多くの引数を取らないようにするには、明示的なインデックス作成をスキップして、シーケンスアンパックを使用してください: 'index、other = value'。高速です(Pythonは安価な 'tuple'パッキングとアンパック用に最適化されており、索引付けにはあまり適していません)。私はこれが奇妙なことに同意します...言い換えれば、私は混乱の危険があるので、反対することをお勧めします。 – ShadowRanger

+0

@ShadowRanger投稿を編集しました。ありがとうございました! – MSeifert

1

それは、のGetItem複数の引数を与えることは可能ですか?もしそうなら、どうですか?そうでない場合は、それをエミュレートする方法はありますか?

なぜこれをエミュレートしたいですか?あなたは "魔法の方法"のポイントを見逃しています。 Pythonでは、これらのメソッドを使用して、演算子のオーバーロードを行うことができます。 Pythonのドキュメントセクション3.3からの抜粋です。 「魔法の方法は」ために使用されることを意図しているものについて説明特別なメソッド名

クラスは、メソッドを定義することによって(例えば算術演算や添え字及びスライスなど)特別な構文によって呼び出される特定の操作を実装することができ特別な名前で。 これは、オペレータのオーバーロードに対するPythonのアプローチです。クラスでは、言語演算子に対して独自の動作を定義できます。

(強調鉱山)

さらに、これは、単一の要素を返すこと__getitem__を期待されているコードの読者にあなたのクラスがあいまいになります。

@MSeifertは既にあなたに必要な振る舞いを実現する方法を与えてくれたので、私は解決策を投稿しません。しかし、独自のカスタムメソッドを作成することを強くお勧めします。 __getitem__メソッドの機能を変更する場合は、少なくともこれらの変更を文書化し、__getiem__の実装が通常の実装と異なる動作をすることを強くお勧めします。

関連する問題