如何在 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.user1
和self.user2
的分配应修改为发生在__init__(self)
内,或者user1
和user2
应成为类属性.在后一种情况下,您的代码必须变为 getattr(TestFoo, input)
但我认为 OP 想要前者(否则为什么不将 input
值“Foo”和“Bar”硬编码到装饰器中)。
@jez 我相信这是按原样工作的。 self.user1
和 self.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中的property类和@property装饰器