如何在 Python 中访问装饰器中的类属性?

Posted

技术标签:

【中文标题】如何在 Python 中访问装饰器中的类属性?【英文标题】:How to access class property in decorator in Python? 【发布时间】:2016-03-17 17:18:48 【问题描述】:

我正在尝试使用 nose_parameterized 测试并希望将其用于单元测试方法。

from nose.tools import assert_equal
from nose_parameterized import parameterized
import unittest

Class TestFoo(unittest.TestCase):
      def setUp(self):
           self.user1 = "Bar"
           self.user2 = "Foo"

      @parameterized.expand([
               ("testuser1",self.user1,"Bar"),
               ("testuser2",self.user2,"Foo")
                ]
      def test_param(self,name,input,expected):
          assert_equal(input,expected)

但是 self 没有在装饰器函数中定义。有解决方法吗?我知道我可以使用全局类变量,但我需要在setUp 中使用变量。

【问题讨论】:

相关:***.com/questions/7590682/access-self-from-decorator 和 ***.com/questions/11731136/…。 【参考方案1】:

一种解决方法是在装饰器中使用包含属性名称的字符串,在测试函数中使用getattr

@parameterized.expand([
           ("testuser1", "user1", "Bar"),
           ("testuser2", "user2", "Foo")
            ])
def test_param(self, name, input, expected):
    assert_equal(getattr(self, input), expected)

使用这种方法,test_param 假定其 input 参数的值是属性名称,其值应与 expected 进行检查。

【讨论】:

要完成这项工作,OP 代码中对self.user1self.user2 的分配应修改为发生在__init__(self) 内,或者user1user2 应成为类属性.在后一种情况下,您的代码必须变为 getattr(TestFoo, input) 但我认为 OP 想要前者(否则为什么不将 input 值“Foo”和“Bar”硬编码到装饰器中)。 @jez 我相信这是按原样工作的。 self.user1self.user2 在每次测试之前运行的 setUp 方法中分配。 啊,我明白了,那么这只是 OP 代码中 setUp 之前缺少关键字 def 的情况。【参考方案2】:

当你认为装饰器会运行时,它并没有运行。在以下示例中:

class spam:
    @eggs
    def beans( self ):
        pass

记住装饰器的使用和说的一样:

beans = eggs( beans )

spam 范围内,def 语句本身执行后立即def 语句何时执行?当时定义了类及其方法。装饰器修改方法spam.beans 的类级定义,而不是self.beans 的实例级值。当然,这发生在该类的任何 实例 被创建之前很久,即在对任何特定实例 self 的引用变得有意义之前。

如果你想将一个特定的可调用对象(例如,修改后的 test_param 可调用对象,它使用 functools.partial 预先烘焙了某些参数)到一个实例 self,你当然可以这样做 inside 实例方法之一(例如__init__setUp)。

有些人会将类定义代码描述为发生在“解析时”,而将实例级代码描述为发生在“运行时”。尽管实际上几乎所有内容在 Python 中都是“运行时”的,但您可能会也可能不会发现这是一种有用的思考方式。

【讨论】:

以上是关于如何在 Python 中访问装饰器中的类属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 的方法装饰器中使用类属性?

Python - 在装饰器中获取原始函数参数

在装饰器中使用全局嵌套模块

Python中的property类和@property装饰器

python装饰器中@wraps作用--修复被装饰后的函数名等属性的改变

Python 联合 - 在另一个装饰器中收集多个 @patch 装饰器