当前位置: 首页 > 知识库问答 >
问题:

修饰函数可以访问装饰器的变量吗

宇文和同
2023-03-14

我试图理解decorator是如何工作的,我想知道一个修饰过的函数是否可以访问decorator的变量。例如,在下面的代码中,如何使f1能够访问localVariable?这可能吗?这是一种很好的做事方式吗?

def funcDec(func):
    localVariable = "I'm a local string"
    def func2Return(*args):                                                                            
        print "Calling localVariable from decorator " + localVariable
        func(*args)                                      
        print "done with calling f1"
    return func2Return

@funcDec
def f1(x, y):
    print x + y
    print localVariable

f1(2, 3)

共有3个答案

李鸿
2023-03-14

我想如果你记住一个室内设计师

@deco
def f(...): ...

只是语法上的糖

def f(...): ...
f = deco(f)

而不是某种宏观扩张。在Python中,变量的作用域是静态确定的,因此对于全局(模块级)函数,既没有作为参数传递也没有指定给的变量将在全局命名空间中查找。

因此,必须显式传递局部变量func2Return()。将f1的签名更改为f1(x,y,localvariable=None)并让包装函数fun2Return

f1(*args, localvariable=localvariable)
汤飞翮
2023-03-14

不,你不能。请看前面这个问题。仅仅因为函数是装饰器并不意味着它调用的函数对其变量有特殊的访问权限。如果你这样做:

def func():
    a = 2
    otherFunc()

然后其他Func不能访问变量a。这是所有函数调用的工作原理,也是装饰器的工作原理。

现在,您在装饰器中定义的包装器函数(在您的示例中为函数2返回)确实可以访问变量,因为该函数在词汇上与这些变量处于相同的范围内。因此,您的行打印"从装饰器调用localVariable"localVariable将起作用。您可以在某种程度上使用它来用依赖于装饰器中变量的行为包装装饰函数。但是实际上被修饰的函数(示例中的f1)没有访问这些变量的权限。

函数只能从函数定义实际所在的范围访问局部变量。函数不从调用作用域获取变量。(这是一件好事。如果他们这样做了,那将是一片混乱。)

岳浩宕
2023-03-14

由于Python的作用域规则,修饰函数通常无法访问修饰器中的任何变量。但是,由于函数可以具有指定给它们的任意属性,因此可以在decorator中执行以下操作以获得类似的效果(由于相同的作用域规则):

def funcDec(func):
    localVariable = "I'm a local string"

    def wrapped(*args):
        print("Calling localVariable from funcDec " + localVariable)
        func(*args)
        print("done with calling f1")

    wrapped.attrib = localVariable
    return wrapped

@funcDec
def f1(x, y):
    print(x + y)
    print('f1.attrib: {!r}'.format(f1.attrib))

f1(2, 3)

这将产生以下输出:

Calling localVariable from funcDec I'm a local string
5
f1.attrib: "I'm a local string"
done with calling f1

有人问这是否可以应用于类的方法:答案是“是”,但必须通过类本身或作为self参数传递的实例引用该方法。这两种技术如下所示。最好使用self,因为它使代码独立于它所在的类的名称。

class Test(object):
    @funcDec
    def f1(self):
        print('{}.f1() called'.format(self.__class__.__name__))
        print('self.f1.attrib: {!r}'.format(self.f1.attrib))  # Preferred.
        print('Test.f1.attrib: {!r}'.format(Test.f1.attrib))  # Also works.

print()
test = Test()
test.f1()

输出:

Calling localVariable from funcDec I'm a local string
Test.f1() called
self.f1.attrib: "I'm a local string"
Test.f1.attrib: "I'm a local string"
done with calling f1
 类似资料:
  • JAVA访问修饰符的可访问性 公众 在 同一班级 同一套餐 子类 宇宙/其他软件包 我在互联网上寻找这些问题的答案,因为我有多个答案。一个视频说未声明的访问修饰符是公共的,而我看到另一个书面来源说未声明的访问修饰符在子类和其他包中没有限制。试图确认哪个是真的。

  • 问题内容: 我正在学习Python。希望有人指出我正确的方法。 这是我想在下面做的事情: 任何想法?提前致谢。 问题答案: 您不能将其作为自己的名称传递,但是可以将其添加到关键字中。 另外,您可以命名自己的参数: 类方法:

  • 问题内容: 我有一个带有装饰器的函数,我正在Python Mock库的帮助下进行测试。我想用一个仅调用函数的模拟“ bypass”装饰器代替真正的装饰器。 我不知道的是如何在真正的装饰器包装功能之前应用补丁。我在补丁目标上尝试了几种不同的变体,并对补丁和导入语句重新排序,但均未成功。有任何想法吗? 问题答案: 装饰器在函数定义时应用。对于大多数功能,这是模块加载时的时间。(在其他函数中定义的函数会

  • 主要内容:带参数的函数装饰器,函数装饰器可以嵌套前面章节中,我们已经讲解了 Python 内置的 3 种函数装饰器,分别是 @staticmethod、@classmethod 和 @property,其中 staticmethod()、classmethod() 和 property() 都是 Python 的内置函数。 那么,函数装饰器的工作原理是怎样的呢?假设用 funA() 函数装饰器去装饰 funB() 函数,如下所示: 实际上,上面

  • 问题内容: 我大概有以下内容。基本上,我需要从在其定义中用于实例方法的装饰器访问实例方法的类。 原样的代码给出: AttributeError:“函数”对象没有属性“ im_class” 我发现了类似的问题/答案-Python装饰器使函数忘记了它属于Python装饰器中的类和Get类-但它们依赖于一种解决方法,该解决方法在运行时通过抢夺第一个参数来获取实例。就我而言,我将基于从其类收集的信息来调用

  • 主要内容:私有(Private)成员,实例,保护(Protected)成员,实例,公共(Public)成员,实例,作用域保护,实例Scala 访问修饰符基本和Java的一样,分别有:private,protected,public。 如果没有指定访问修饰符,默认情况下,Scala 对象的访问级别都是 public。 Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员。 私有(Private)成员 用 private 关键字修饰,带