5

classmethod次のようにデコレータを使用したいコードがあります。

import functools

def mydeco(function):
    @classmethod
    def wrapper(cls):
        return function(cls) 
    return functools.update_wrapper(wrapper, function)
    # return wrapper

class BaseClass(object):
    @classmethod
    @mydeco
    def foo(cls):
        return "42" 

print BaseClass.foo()

行をコメントアウトすると@mydeco、コードが機能します。つまり、テキスト42が出力されます。このデコレータを含めると、いくつかの問題があります。

  • より単純な行return wrapperを使用すると、エラーが発生します

    TypeError: 'classmethod' object is not callable
    

それを正しく行う方法、つまり、指定された例では、元の関数が変更されずに返されます。

  • より複雑な呼び出しreturn functools.update_wrapper(wrapper, function)を使用して元の関数の一部を保持すると、エラーが発生します

    AttributeError: 'classmethod' object has no attribute '__module__'
    

このエラーが最初の問題に関連しているかどうかはわかりませんが、別の問題に見えます。これらの問題を解決するための具体的な提案は大歓迎です。

上記の例は実際に何かを「行う」わけではなく、私が抱えている問題を示すための可能な限り最小の例にすぎません。

4

4 に答える 4

1

デコレータに関する興味深い投稿を見ました。ここに説明がありますが、回避策はありません。

デコレーターが @classmethod または @staticmethod の周りに適用されると、例外で失敗する可能性があります。これは、これらによって作成されたラッパーには、コピーされる属性の一部がないためです。

静的/クラスメソッドを正しく装飾する方法もわかりませんが、同様の例外が発生した場合、洞察なしでコードを機能させるために、次のいずれかを実行します。

  • @mydeco と @staticmethod の順序を変更
  • @staticmethod を破棄

アップデート

これは、記述子を正しく実装する方法に関する別の素晴らしい投稿です

于 2014-09-04T17:40:07.620 に答える
-2

たぶん問題は@classmethod前にあるdef wrapper...mydecoクラス定義ではなく関数定義のように)

于 2013-03-05T18:43:43.293 に答える
-3
from functools import wraps

def mydeco(function):
    @wraps(function)
    def wrapper(*args, **kwargs):
        print "Calling Decorated Function"
        return function(*args, **kwargs) 
    #return functools.update_wrapper(wrapper(function), function)
    return wrapper


@mydeco
class BaseClass():
    def foo(self, cls):
        return "42" 

a = BaseClass()
print a.foo(22)

それは今動作します

于 2013-03-05T18:59:38.033 に答える