2017-11-13 16 views
3

私はコンストラクタのmemoiziationを可能にするデコレータを書いてみたいです。私はクラスを構築するとき、私はオブジェクトが可能なときにキャッシュから返されます。この場合、isinstance()はなぜFalseを返しますか?

次のコードは、hereから変更されています。

from functools import wraps 


def cachedClass(klass): 
    cache = {} 

    @wraps(klass, updated=()) 
    class wrapper: 
     def __new__(cls, *args, **kwargs): 
      key = (cls,) + args + tuple(kwargs.items()) 
      try: 
       inst = cache.get(key, None) 
      except TypeError: 
       # Can't cache this set of arguments 
       inst = key = None 
      if inst is None: 
       inst = klass.__new__(klass, *args, **kwargs) 
       inst.__init__(*args, **kwargs) 
       if key is not None: 
        cache[key] = inst 
      return inst 

    return wrapper 

小さなテストスイートには、以下をrevals:

>>> @cachedClass 
... class Foo: 
...  pass 
>>> f1 = Foo() 
>>> f2 = Foo() 
>>> f1 is f2 
True 
>>> Foo 
<class 'cache.Foo'> 
>>> type(f1) 
<class 'cache.Foo'> 
>>> isinstance(f1, Foo) 
False 

私は最後の式はTrueを返すだろうと期待しました。私は何が欠けていますか?

+0

私はPython 2.7を使用していますが、私は 'True'を取得します。しかし、インタプリタは 'type(f1)'を実行すると ''を返します。 – HFBrowning

+2

@HFBrowning 'class Foo:pass'はPython 2の古いスタイルのクラスです。 – vaultah

答えて

3
@cachedClass 
class Foo: 
    pass 
Foo

は名前が wrapperクラスであるcachedClassの戻り値を、割り当てられ

class Foo: 
    pass 

Foo = cachedClass(Foo) 

と意味的に等価です。

wrapperはコピーFoo年代__name__他のいくつかのdunderの属性とともに属性、そうwrapperクラスFooのように見えますfunctool.wrapsによって装飾順番にあります。

あなたは@wraps行を削除して印刷する場合

print(type(f1), Foo, type(f1) is Foo, sep=', ') 

あなたはf1は、元Fooクラスのインスタンスであることがわかりますが、Fooは今wrapperクラスを参照し、彼ら

<class '__main__.Foo'>, <class '__main__.cachedClass.<locals>.wrapper'>, False 
+0

これは分かりました。私は何とか 'isinstance'が' __class__'ではなく '__name__'だけをチェックすると思っていたに違いありません。ラッパーを真に透明にする簡単な方法はありますか? – polwel

+0

@polwel私が知っているものはありません。元のクラスを返さなければならないでしょう – vaultah

関連する問題