3

isinstancePython関数は内部でどのように機能しますか? クラス内で特別な関数を定義するなど、結果を変更するためにできることはありますか? これが私のユースケースです:

class Decorator:
    def __init__(self, decorated):
        self._decorated = decorated

    def __call__(self):
        return self._decorated()

@Decorator
class Foo:
    pass

f = Foo()

# How can I make this be true?
isinstance(f, Foo)

Decoratorここではミキシングが適切ではないことを除いて、ほとんどミックスインのように機能します。上記のコードを機能させる方法はありますか? isinstanceまた、この行には次のエラーも表示されることに注意してください。

    isinstance(f, Foo)
TypeError: isinstance() arg 2 は型または型のタプルでなければなりません

4

4 に答える 4

6

以下はどうでしょう。

def Decorator(decorated):
    class Dec(decorated):
        def __call__(self):
            print 'in decorated __call__'
            return decorated.__call__(self)
    return Dec

@Decorator
class Foo(object):
    def __call__(self):
        print 'in original __call__'

f = Foo()

# How can I make this be true?
print isinstance(f, Foo)

上記のコードで:

  • isinstance(f, Foo)動作します。
  • f()装飾されたメソッドを呼び出し、それが元のメソッドに転送されます。

基本的な考え方は、装飾されたFooものがまだクラスであることを確認し、装飾されたものが元Fooの のサブクラスFooであることも確認することです。

PS これらすべての目的は、私には完全には明らかではありません。あなたがやろうとしていることを達成するには、メタクラスがより良い方法かもしれません。

于 2011-09-22T12:59:43.227 に答える
1

問題はFoo、あなたの例ではクラスではないということです。

このコード:

@Decorator
class Foo:
    pass

次と同等です。

class Foo:
    pass
Foo = Decorator(Foo)

つまり、それFooは class のインスタンスですDecoratorFooはクラスでも型でもないのでisinstance文句を言います。

于 2011-09-22T13:00:23.563 に答える
0

クラスを装飾するとき、装飾された戻り値も型にすることが有用である、または望ましいことがよくあります。これを実現する最も明白な方法は、デコレータで新しいクラスを構築して直接返すことです。

その機能は、メタクラスによって既に処理されています。実際、デコレートされたクラスが構築される前に新しいクラスを記述できるため、メタクラスはデコレータよりも少し強力です。

もう 1 つのオプションは、渡されたものと同じオブジェクトを返すことです。しかし、いくつかの変更があります。デコレータを入れ子にするときにうまく機能するため、これはデコレータのより良い使用方法です。が使用されているときの動作を変更しているのでFoo()、おそらく Foo の を変更したいと思うでしょう。これは次の__init__ようになります。

>>> def Decorator(cls):
...     assert isinstance(cls, type)
...     try:
...         old_init = cls.__init__.im_func
...     except AttributeError:
...         def old_init(self): pass
...     def new_init(self):
...         # do some clever stuff:
...         old_init(self)
...     cls.__init__ = new_init
...     return cls
... 
>>> @Decorator
... class Foo(object):
...     def __init__(self): pass
... 
>>> @Decorator
... class Bar(object):
...     pass
... 
>>> f = Foo()
>>> isinstance(f, Foo)
True
于 2011-09-22T13:24:36.540 に答える