如何在 Python 中获取传递给装饰器的参数值?
How do I get the value of an argument passed to a decorator in Python?
根据下面的代码,我正在尝试识别发送给 class.
使用的装饰器的参数
具体来说,我正在尝试识别传递给 make_hyper
装饰器的值 100
,该装饰器在 Dog
class.[=19= 中使用]
最佳情况下,我需要能够在不直接 运行 方法的情况下获取此值,因为我正在使用的实际方法代码需要很长时间才能 运行。
import inspect
def make_hyper(new_volume):
def decorator(decorated_method):
def wrapped_method(self, *args, **kwargs):
self.volume = new_volume
return decorated_method(self, *args, **kwargs)
return wrapped_method
return decorator
class Dog(object):
def __init__(self, name):
self.name = name
self.volume = 1
@make_hyper(new_volume=100)
def bark(self):
if self.volume >= 10:
print('[{}]: BARK!!'.format(self.name))
elif self.volume >= 5:
print('[{}]: Bark!'.format(self.name))
else:
print('[{}]: Bark'.format(self.name))
我尝试使用 inspect.getargspec 和其他一些东西,并且(尽我所能)搜索 Whosebug 和整个互联网,但我找不到解决方案。
如有任何帮助,我们将不胜感激!感谢您的宝贵时间!
更新:
有人要我澄清我想做什么。抱歉没有说清楚。
上述玩具所代表的实际代码是一个测试自动化框架,其中包括指定测试标签的装饰器:
class TestTags(object):
WIFI = 'wifi'
BLE = 'ble'
NIGHTLY = 'nightly'
REGRESSION = 'regression'
class TestBase(unittest.TestCase):
<define common test stuff and test decorators>
class ThingTester(TestBase):
@TestBase.tags(TestTags.WIFI, TestTags.BLE, TestTags.REGRESSION)
def test_all_the_things(self):
<test all the things>
# what I'm trying to get
test_tags = ???
print(test_tags) # prints out ('wifi', 'ble', 'regression')
我编写了一个实用程序,它遍历所有测试模块、classes 和单个测试,并创建一个定义测试计划的 HTML+JavaScript 页面。我想添加到页面的一项数据是与每个测试关联的标签。
我发现我可以让 tags
装饰器将属性保存到 class(即 self.tags = tags
),但这需要测试在 运行 之前值保存到 TestBase
对象,我需要能够独立于 运行 测试生成测试计划。
我不确定我是否完全理解你想要的,但如果你打算检查现有测试以创建计划或报告,那么你可能希望将装饰器参数存储在测试函数中,而不是 class 实例,对吧?例如:
def TestTags(*tags):
def decorator(f):
def wrapper(*args, **kwargs):
# ...
return f(*args, **kwargs)
wrapper.tags = tags
return wrapper
return decorator
@TestTags(TAG1, TAG2)
def myTest(...):
...
print(myTest.tags)
>>> (TAG1, TAG2)
编辑:刚刚意识到对于实例方法来说,它不是开箱即用的。你仍然可以像这样使用它:
def TestTags(*tags):
def decorator(f):
def wrapper(*args, **kwargs):
# ...
return f(*args, **kwargs)
wrapper.tags = tags
return wrapper
return decorator
class TestSuite(...):
@TestTags(TAG1, TAG2)
def myTest(...):
...
print(TestSuite.myTest.tags) # From class function
>>> (TAG1, TAG2)
myTestSuite = TestSuite()
print(myTestSuite.myTest.__func__.tags) # From instance method
>>> (TAG1, TAG2)
根据下面的代码,我正在尝试识别发送给 class.
使用的装饰器的参数具体来说,我正在尝试识别传递给 make_hyper
装饰器的值 100
,该装饰器在 Dog
class.[=19= 中使用]
最佳情况下,我需要能够在不直接 运行 方法的情况下获取此值,因为我正在使用的实际方法代码需要很长时间才能 运行。
import inspect
def make_hyper(new_volume):
def decorator(decorated_method):
def wrapped_method(self, *args, **kwargs):
self.volume = new_volume
return decorated_method(self, *args, **kwargs)
return wrapped_method
return decorator
class Dog(object):
def __init__(self, name):
self.name = name
self.volume = 1
@make_hyper(new_volume=100)
def bark(self):
if self.volume >= 10:
print('[{}]: BARK!!'.format(self.name))
elif self.volume >= 5:
print('[{}]: Bark!'.format(self.name))
else:
print('[{}]: Bark'.format(self.name))
我尝试使用 inspect.getargspec 和其他一些东西,并且(尽我所能)搜索 Whosebug 和整个互联网,但我找不到解决方案。
如有任何帮助,我们将不胜感激!感谢您的宝贵时间!
更新: 有人要我澄清我想做什么。抱歉没有说清楚。
上述玩具所代表的实际代码是一个测试自动化框架,其中包括指定测试标签的装饰器:
class TestTags(object):
WIFI = 'wifi'
BLE = 'ble'
NIGHTLY = 'nightly'
REGRESSION = 'regression'
class TestBase(unittest.TestCase):
<define common test stuff and test decorators>
class ThingTester(TestBase):
@TestBase.tags(TestTags.WIFI, TestTags.BLE, TestTags.REGRESSION)
def test_all_the_things(self):
<test all the things>
# what I'm trying to get
test_tags = ???
print(test_tags) # prints out ('wifi', 'ble', 'regression')
我编写了一个实用程序,它遍历所有测试模块、classes 和单个测试,并创建一个定义测试计划的 HTML+JavaScript 页面。我想添加到页面的一项数据是与每个测试关联的标签。
我发现我可以让 tags
装饰器将属性保存到 class(即 self.tags = tags
),但这需要测试在 运行 之前值保存到 TestBase
对象,我需要能够独立于 运行 测试生成测试计划。
我不确定我是否完全理解你想要的,但如果你打算检查现有测试以创建计划或报告,那么你可能希望将装饰器参数存储在测试函数中,而不是 class 实例,对吧?例如:
def TestTags(*tags):
def decorator(f):
def wrapper(*args, **kwargs):
# ...
return f(*args, **kwargs)
wrapper.tags = tags
return wrapper
return decorator
@TestTags(TAG1, TAG2)
def myTest(...):
...
print(myTest.tags)
>>> (TAG1, TAG2)
编辑:刚刚意识到对于实例方法来说,它不是开箱即用的。你仍然可以像这样使用它:
def TestTags(*tags):
def decorator(f):
def wrapper(*args, **kwargs):
# ...
return f(*args, **kwargs)
wrapper.tags = tags
return wrapper
return decorator
class TestSuite(...):
@TestTags(TAG1, TAG2)
def myTest(...):
...
print(TestSuite.myTest.tags) # From class function
>>> (TAG1, TAG2)
myTestSuite = TestSuite()
print(myTestSuite.myTest.__func__.tags) # From instance method
>>> (TAG1, TAG2)