2012-06-04 13 views
14

私は、クラス定義で__repr__メソッドを設定するための例しか見ていません。関数の定義を変更したり、定義した後に、関数のために__repr__を変更することは可能ですか?Pythonで関数のreprを変更することはできますか?

repr(f)ではなくtype(f).__repr__(f)として行われているので、私は、ありません...成功せず

>>> def f(): 
    pass 
>>> f 
<function f at 0x1026730c8> 
>>> f.__repr__ = lambda: '<New repr>' 
>>> f 
<function __main__.f> 

答えて

14

はい、関数を実際に残しておきたい場合は、関数です。

まず、私たちの新しいタイプのクラスを定義します。

import functools 
class reprwrapper(object): 
    def __init__(self, repr, func): 
     self._repr = repr 
     self._func = func 
     functools.update_wrapper(self, func) 
    def __call__(self, *args, **kw): 
     return self._func(*args, **kw) 
    def __repr__(self): 
     return self._repr(self._func) 

はデコレータ機能に追加します。

def withrepr(reprfun): 
    def _wrap(func): 
     return reprwrapper(reprfun, func) 
    return _wrap 

そして今、我々は機能と一緒にのreprを定義することができます。

@withrepr(lambda x: "<Func: %s>" % x.__name__) 
def mul42(y): 
    return y*42 

repr(mul42)は、'<Func: mul42>'

+3

デコレータに 'functools.wraps'を使って修飾された関数の名前とドキュメントストリングを更新してください。 – schlamar

+1

問題は、 'print mul42 .__ name__'は、関数に期待されないAttributeErrorを発生させることです。したがって、これを修正するには 'return wraps(func)(reprwrapper(reprfun、func))'となります。 – schlamar

+1

@ ms4pyこの場合、私は 'update_wrapper'がやや適切/直接的だと思います。私は、コンストラクタでこれを行うようにラッパークラスを変更しました。このようにして、 'withrepr'デコレータを使用する代わりにクラスを直接使用しても、更新が行われます。 – kwatford

3

これを行うには、指定されたクラス(この場合は組み込み関数クラス(types.FunctionType))の__repr__関数を変更する必要があります。 Pythonでは組み込みクラスを編集することはできないので、それらをサブクラス化するだけで済みます。

  1. kwatfordが
  2. 独自のrepr機能を備えた独自の表現プロトコルを作成して提案されているよういくつかの関数をラップ:

    はしかし、あなたが従うことができる2つの方法があります。たとえば、最初に__myrepr__メソッドを探すmyrepr関数を定義することができますが、これは関数クラスに追加することはできませんが、提案するように個々の関数オブジェクトに追加することができます(カスタムクラスやオブジェクトと同様に)。 __myrepr__が見つからない場合はrepr。このための可能な実装は次のようになります。

    def myrepr(x): 
        try: 
        x.__myrepr__ 
        except AttributeError: 
        return repr(x) 
        else: 
        return x.__myrepr__() 
    

    次にあなたが__myrepr__メソッドを定義してmyrepr機能を使用することができます。または、__builtins__.repr = myreprを使用して機能をデフォルトのreprにして、reprをそのまま使用することもできます。このアプローチは、あなたが望むものを正確に行うことに終わりますが、編集__builtins__は必ずしも望ましいとは限りません。

関連する問題