0

私はこれをしたい(ダミーの例):

def func():
    nonlocal var
    print (var)

class A:
    var = 'hola'
    func()

しかし、「SyntaxError:非ローカル 'var' のバインディングが見つかりませんでした」というメッセージが表示されます。

私が実際にやろうとしているのは、そのメソッドが装飾されている場合、クラスのスコープ内のリストにメソッド名を追加することです。このようなもの:

def decorator(func):
    nonlocal decorated
    decorated.append(func.__name__)
    return func

class A:
    decorated = []
    @decorate
    def f(self):
        pass
4

4 に答える 4

2

デコレータを使用して関数をマークし、装飾されたすべての関数を返すクラス メソッドに装飾します。

import inspect

def decorate(func):
    func.decorated = True
    return func

class A:
    def foo():
        print('foo')

    @decorate
    def bar():
        print('bar')

    @classmethod
    def decorated(cls):
        def is_decorated_method(obj):
            try:
                return inspect.isfunction(obj) and obj.decorated
            except AttributeError:
                # The object has no decorated attribute
                return False

        return [result[1] for result in inspect.getmembers(cls, predicate=is_decorated_method)]

print(A.decorated())
# [<function A.bar at 0x6ffffc0aa60>]
于 2016-04-11T17:38:53.537 に答える
2

Python では、これを行うことはできません。を使用して、クラスの名前空間にアクセスできますlocals()。しかし、この時点では、関心のある変数をデコレーターに渡すだけでも構いません。

# using locals()

def decorator(class_namespace):
    def _decorator(func):
        class_namespace["decorated"].append(func)
        return func
    return _decorator

class A:
    store = decorator(locals())

    decorated = []

    @store
    def func(self):
        pass

    del store

一般に、一対のデコレーターを使用するのは簡単です。1 つは興味のある機能をマークするためのもので、もう 1 つはそれらを収集するためのものです。

from types import FunctionType

def collect(cls):
    for item in vars(cls).values():
        print(item)
        if isinstance(item, FunctionType) and getattr(item, "marked", False):
            cls.marked_funcs.append(item)
    return cls

def mark(func):
    func.marked = True
    return func

@collect
class B:
    marked_funcs = []

    @mark
    def func(self):
        pass

しかし、あなたの場合、クラスの最後に一連の関数名を作成する方が簡単かもしれません。例えば。

class C:
    def func(self):
        pass

    func_names = [f.__name__ for f in [func]]
于 2016-04-11T18:14:02.480 に答える
1
y = 20
def f():
    x = 7
    def g():
        nonlocal x # 7
        global y # 20

nonlocal修飾子は、モジュール スコープを含まない外側の関数スコープ内の名前を参照します。一方global、補完的です。だから使い方をnonlocal間違っている。

于 2016-04-11T17:06:52.620 に答える
0

どのようにそのことについて?

decorated = []

def decorator(func):
    decorated.append(func.__name__)
    def wrapper(self):
        print('wrapper called')
        func(self)
    return wrapper

class A:
    @decorator
    def f(self): print('function called')

print(decorated)
A().f()

出力:

['f']
wrapper called
function called

ノート:

説明した問題が発生しているコードvarは、クラス変数であるため、として参照する必要がありますが、定義されるA.var前に使用しようとするため、コードでそれを行うことはできません。Aそれが異なるクラスである場合、それは可能です:

class X:
    decorated = []

def decorator(func):
    X.decorated.append(func.__name__)
    return func

class A:

    @decorator
    def f(self):
        pass

print(X.decorated)

nonlocal変数に代入せず、 などのメソッドを呼び出す場合は指定する必要がないことに注意してくださいappend()

于 2016-04-11T16:59:30.740 に答える