6

私は、Python が機能を他のオブジェクトに委任するためのいくつかの巧妙なトリックを許可していることに慣れています。1 つの例は、含まれているオブジェクトへの委任です。

しかし、__contains __ をデリゲートしたい場合、運が悪いと思われます:

class A(object):
    def __init__(self):
       self.mydict = {}
       self.__contains__ = self.mydict.__contains__

a = A()
1 in a

私は得る:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argument of type 'A' is not iterable

私が間違っていることは何ですか?a.__contains __(1) を呼び出すと、すべてがスムーズに進みます。A に __iter __ メソッドを定義して、A をイテラブルに見えるようにしようとさえしましたが、役に立ちませんでした。ここで何が欠けていますか?

4

1 に答える 1

18

のような特別なメソッド__contains__は、インスタンスではなく、クラスで定義された場合にのみ特別です (ただし、Python 2 のレガシー クラスは例外であり、いずれにせよ使用すべきではありません)。

したがって、クラス レベルで委任を行います。

class A(object):
    def __init__(self):
       self.mydict = {}

    def __contains__(self, other):
       return self.mydict.__contains__(other)

私は実際には後者を と綴りたいと思ってreturn other in self.mydictいますが、それは小さなスタイルの問題です.

編集:「特別なメソッドの完全に動的なインスタンスごとのリダイレクト」(提供される古いスタイルのクラスなど)が不可欠な場合、新しいスタイルのクラスでそれを実装することは難しくありません。そのような独特の必要性を持つ各インスタンスが必要なだけです独自の特別なクラスにラップされます。例えば:

class BlackMagic(object):
    def __init__(self):
        self.mydict = {}
        self.__class__ = type(self.__class__.__name__, (self.__class__,), {})
        self.__class__.__contains__ = self.mydict.__contains__

self.__class__基本的に、新しいクラス オブジェクト (前のクラス オブジェクトと同じように動作しますが、空の dict があり、これ以外のインスタンスはありません) に再割り当てする黒魔術を少し行った後、self古いスタイルのクラスのどこにでもself.__magicname__割り当てます。代わりにself.__class__.__magicname__(また、通常の Python 関数ではなく、組み込みの orstaticmethodであることを確認してください。もちろん、別のケースで、インスタンスで呼び出されたときに を受け取りたい場合を除きselfます)。

ちなみに、このクラスinのインスタンスの演算子は、たまたま以前に提案されたソリューションのどれよりも高速です継承と記述子を含むルートは、オーバーヘッドを少し削減します)。BlackMagic-mtimeitbuilt-in method

インスタンスごとのアイデアを自動化するメタクラスをself.__class__書くのは難しくありません (生成されたクラスのメソッドで汚い仕事をすることができ__new__、インスタンスに割り当てられている場合は、すべてのマジック名をクラスに実際に割り当てるように設定することもできます。__setattr__または多くの、多くのプロパティ)。しかし、それは、この機能の必要性が本当に広まった場合にのみ正当化されます (たとえば、「インスタンスごとの特別なメソッド」を自由に使用する巨大な古代の Python 1.5.2 プロジェクトを、Python 3 を含む最新の Python に移植する場合)。

「賢い」または「黒魔術」のソリューションをお勧めしますか? いいえ、そうではありません。ほとんどの場合、物事を単純明快な方法で行う方が優れています。しかし、ここでは「ほぼ」という言葉が重要であり、その使用が実際に正当化される可能性がある、まれではあるが存在しないわけではない状況のために、このような高度な「フック」を手元に用意しておくと便利です。

于 2009-06-20T20:42:37.457 に答える