4

シーケンス タイプ__setitem__への割り当てには、Python のマジック メソッドがあります。コンテナー レベルでの拡張代入のための魔法の方法はありますか? この操作は、item-type の拡張された割り当てにうまく分割されているように見えます。それは論理的です。しかし、他のほとんどすべてのものには魔法のメソッドがあります。シーケンス型のこれらの演算子には一連のメソッドが必要だと思いました。私はそれを逃しましたか?=+=

アプリケーションは一種のデータベースです。__getitem__SELECT と__setitem__INSERTを使用して実装することを考えてください。__additem__UPDATEにはetc.のようなものがあるはずですよね?

from __future__ import print_function
class Item(object):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return "Item " + str(self.value)
    def __iadd__(self, other):
        print("Item iadd", self, other)
        return Item(self.value + "+" + other.value)

class Container(object):
    def __getitem__(self, key):
        print("Container getitem", key)
        return Item(key)
    def __setitem__(self, key, value):
        print("Container setitem", key, value)
        return self
    def __additem__(self, key, value):
        print("Container additem would be nice", key, value)
        return self

SELECT は次のとおりです。

>>> c = Container()
>>> _ = c['key']
Container getitem key

挿入は次のとおりです。

>>> c['key'] = Item('other')
Container setitem key Item other

UPDATE の実装方法 SELECT と INSERT に分解せずに:

>>> c['key'] += Item('other')
Container getitem key
Item iadd Item key Item other
Container setitem key Item key+other

それでは、分割された手順とは異なる方法で拡張代入を実装する方法はありますか? すべての動作を Item クラスに入れずに?


上記のコードをコピーして Python インタープリターに貼り付けるか、次の Python フィドルで試すことができます: http://pythonfiddle.com/add-item-for-sequence/


関連する質問は、の逆コンパイルを示していますself[key] += value

4

1 に答える 1

3

いいえ、魔法の__additem__方法はありません。

c[k] += v魔法のメソッド呼び出しに変わります: c.__setitem__(c.__getitem__(k).__iadd__(v)).

__setitem__すべての Python オブジェクトがインプレース加算をサポートしているわけではないため、呼び出しが含まれています。不変オブジェクト (intや などfloat) は呼び出されないため、__add__代わりに呼び出されます__iadd__(新しい値を返す__add__ 必要があります)。

データベースを希望どおりに機能させる唯一の方法__getitem__は、特別な「アイテムプロキシ」タイプを返すように書くことだと思います。プロキシは最初は何もしません (独自の動作はありません)。ただし、属性またはメソッドが検索される (または__magic__メソッドが呼び出される) と、それを機能させるために必要なデータベース操作が実行されます。ほとんどのメソッドと属性ルックアップでは、データベースにクエリを実行して実際のデータを取得し、適切なメソッドまたは値を返す必要があります。呼び出されたのが既知のインプレース変更メソッドであった場合 (appendまたはのように、代わりに ( の代わりに のように)__iadd__別のデータベース操作を実行できます)。UPDATESELECT

そのようなプロキシ型を書くのは簡単ではありませんが、とてつもなく難しいことでもありません。多くのタイプのオブジェクトを処理したい場合は、多くのコーナー ケースをカバーする必要があります。データベースが保持できるタイプのセットの狭さによっては、プロキシがレプリケートする必要があるメソッドと属性のリストを、ほんの数個に絞り込むことができる場合が__int__あります (たとえば、算術演算子と比較演算子など)。__float__数値型をサポートするため)。

一方で、より少ないコードでaSELECTと anを実行できる場合、開発に費やす価値がないことに気付くかもしれません。INSERT

于 2016-04-02T09:32:53.400 に答える