python - 用装饰函数填充字典

标签 python python-3.x

我正在创建一个基本上运行一堆测试的应用程序,每个测试都是一个单独的函数。我有一个像这样的字典形式的测试/功能列表。

test = {
    "test 1": f1,
    "test 2": f2,
    "test 3": f3
}

我可以这样执行函数:

for testn, _ in test.items():
    test[testn]()

但是我想做这样的事情:

tests = {}

@task("test 1")
def f1():
   ...

@task("test 2")
def f1():
   ...

def run():
    for testn, _ in tests:
        tests[test]()

我想知道这怎么可能。任何帮助,将不胜感激。

最佳答案

您可以创建一个简单的装饰器来填充您的函数注册表测试:

tests = {}
def task(name):
   def wrapper(funct):
      tests[name] = funct
      return funct
   return wrapper

@task("test 1")
def f1():
  ...

@task("test 2")
def f2():
  ...

def run():
  for testn, _ in tests.items():
    tests[test]()

现在,在调用 run 之前,在遍历字典时,可以观察到结构是正确的:

print({a:b.__name__ for a, b in tests.items()})

输出:

{'test 2': 'f2', 'test 1': 'f1'}

但是请注意,tests 确实包含所有函数实例:

{'test 2': <function f2 at 0x10de0e5f0>, 'test 1': <function f1 at 0x10de0e578>}

这个装饰器稍微偏离了接收包装函数、截取参数并通过仅返回传递给它的原始函数对象来调用包装函数的正常装饰器模式。这节省了必须实现另一个包装器来拦截参数的空间,并允许在函数绑定(bind)到其对象时立即添加注册表。

另外,请注意 tests 是一个字典,因此在不首先调用 dict.items() 并引发 ValueError 的情况下尝试通过解包对其进行迭代: 太多值无法解压 错误。

编辑:如果函数变成方法,那么解决方案是:

class Tests:
    def __init__(self):
       self.tests = {}
    def task(self, name):
       def wrapper(f):
          self.tests[name] = f
       return wrapper

test = Tests()
@test.task('test 1')
def f1():
   pass

@test.task('test 2')
def f2():
   pass

for a, b in test.tests.items():
   pass

print({a:b.__name__ for a, b in test.tests.items()})

输出:

{'test 2': 'f2', 'test 1': 'f1'}

关于python - 用装饰函数填充字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49020162/

相关文章:

python - 值错误: Location based indexing can only have [labels (MUST BE IN THE INDEX)

python - 2D 到 3D numpy 数组的高效转换

python - 在给定列表中创建重复元素的新列表

python - 从 Viber 机器人向订阅用户发送消息

python - 如何使用 python 更新嵌套 JSON 文件中的值?

python - numpy - 附加到数组而不制作副本

python - Pandas :AttributeError: 'module' 对象没有属性 '__version__'

python - 打印列表值字典

python-3.x - Python 3.x 如何获取 http 版本(使用请求库)

python - 无法更改Python中全局变量的值