Python修饰符访问范围变量

2024-09-27 21:32:04 发布

您现在位置:Python中文网/ 问答频道 /正文

Python装饰器可以访问修饰函数范围内的所有变量吗?e、 g

@decme
def call_me():
    ...

def caller_function():
    context = context_creator()
    call_me()

在这个场景中,decme修饰符可以访问context变量吗?在

我们知道call_me将能够访问context,如果我们将其作为参数传入,有没有方法将context传递给decme函数?在

请注意,call\me函数可以在单独的模块中定义,这意味着在我们调用call_me函数时,@decme(context)可能不正常


Tags: 模块方法函数参数defcontext场景function
3条回答

函数是一个对象,可以有属性。可以将上下文作为包装器的属性直接传递:

def decme(f):
    def wrapped(*args, **kwargs):
        # here we can access the context passed as wrapped.context
        print("Before context:", wrapped.context) 
        cr = f(*args, **kwargs)
        print("After")
        return cr
    wrapped.context = None
    return wrapped

def caller_function():
    # just pass the context
    call_me.context = context_creator()
    call_me()

这里原始的call_me没有context属性的概念,但是修饰函数有。唯一的缺点是它是函数的一个属性,并且会在调用之间持续存在。特别是在多线程环境中,它将导致意外的结果。。。在


或者,可以使用decorator向函数添加一个附加参数,该参数可以在运行时传递。这种方式是线程安全的:

^{pr2}$

您可以访问调用方堆栈并查看其帧中的所有局部变量。我正使用这种技术来实现我的Stack Environment in Python,它或多或少地做到了这一点,顺便说一句,使用它,可能会以更整洁的方式解决整个问题。在

但是,除非你把这个放在一个漂亮的藏书室里,把所有丑陋的细节都藏起来,否则我会称之为一个丑陋的黑客攻击。在

把这个上下文传递到call_me()怎么样?然后它的装饰者当然会收到它。在

如果您选择使用StackEnv,这将是一种公式化方法:

from stackEnv import stackEnv

def decme(function):
    def wrapper(*args, **kwargs):
        if stackEnv.context.someValue > someOtherValue:
            doSomething()
        return function(*args, **kwargs)
    return wrapper

@decme
def call_me():
    ...

def caller_function():
    stackEnv.context = context_creator()
    call_me()

@Alfe提供了一些特殊的解决方案。在

您可能知道运行decorator和decorator之间的时间安排。在

但是,由于您的目的不明确,因此基于当前代码,您可以尝试将代码重构为以下样式:

def decme(context):
    def real_decme(function):
        def wrapper(*args, **kwargs):
            function(*args, **kwargs)
        return wrapper
    return real_decme

def call_me():
    pass

def caller_function():
    context = context_creator()
    decme(context)(call_me)()

在这种情况下,decme可以处理上下文。但它不会在decorator生成期间运行。在

相关问题 更多 >

    热门问题