1

次のコードがあります。

import threading
from functools import wraps
class Synchronized(object):
    def __init__(self):
        self.lock = threading.Lock()

    def synchronized(f):
        @wraps(f)
        def wrapper(self, *args, **kwargs):
            with self.lock:
                print "here"
                return f(self, *args, **kwargs)
        return wrapper

    @synchronized
    def go(self):
        print 1

class B(Synchronized):
    @synchronized
    def foo(self):
        return 1

このコードは、インポートの不平を言うと失敗します:

  File "a.py", line XXX, in B
    @synchronized
NameError: name 'synchronized' is not defined

ただし、Bをコメントアウトして使用するSyncrhonized().go()と、うまく機能します。

質問: python はどのように@synchronizedして基底クラスにあるものを認識し、その派生クラスでそれを解決できませんか?

4

1 に答える 1

4

synchronizedSynchronized のみのクラス本体で関数として定義されています。

クラス本体は、クラスを定義する関数のように実行されます。結果のローカル名前空間は、クラス属性を形成するために使用されます。これが、 でデコレータとして使用される場合synchronizedでも 内でローカル名である理由です。これは、関数内でデコレータを定義してから、その関数のに適用しようとすることと比較できます。デコレータはローカル変数であるため、機能しません。Synchronizedgo

@Syncronized.synchronized.im_funcクラスで使用できますB.im_funcメソッドラッパーから関数をアンラップするため):

class B(Synchronized):
    @Synchronized.synchronized.im_func
    def foo(self):
        return 1

さらに良いことに、クラス内でデコレータをまったく定義せず代わりにの外部で定義しSynchronizedます。結局のところ、これはメソッドではありません。

def synchronized(f):
    @wraps(f)
    def wrapper(self, *args, **kwargs):
        with self.lock:
            print "here"
            return f(self, *args, **kwargs)
    return wrapper

class Synchronized(object):
    def __init__(self):
        self.lock = threading.Lock()

    @synchronized
    def go(self):
        print 1

class B(Synchronized):
    @synchronized
    def foo(self):
        return 1
于 2013-07-23T13:15:13.353 に答える