我是一个蟒蛇初学者,并且了解装饰器的基本概念。之前我曾经使用过Python-Behave,框架允许你插入一个装饰器,它的功能就像一个标签。我试图在我目前正在构建的框架中复制它。
CLI中的自定义arg
parser = argparse.ArgumentParser()
parser.add_argument('--type', help='foo help')
args = parser.parse_args() #args.type would receive the value
CLI
python run.py --type=A
功能
@typeA
def foo_func():
print "type A ran"
@typeB
def bar_func():
print "type B ran"
预期输出
"type A ran"
答案 0 :(得分:1)
使用装饰器在字典中存储对函数的引用。使用用户输入从字典中检索函数。之后再打电话。
REGISTER = {}
def register(name):
def wrapper(f):
print f, 'registered'
REGISTER[name] = f
return f
return wrapper
@register('A')
def foo():
print 'foo called'
@register('B')
def bar():
print 'bar called'
name = 'A' # or args.type
func_to_call = REGISTER[name]
func_to_call() # actual call is done here
答案 1 :(得分:1)
将装饰器包装成类样式装饰器,以避免挂起变量并使用memoized工厂函数来创建标签。
import functools
class TagDecorator(object):
def __init__(self, tagName):
self.functions = []
self.tagName = tagName
def __str__(self):
return "<TagDecorator {tagName}>".format(tagName=self.tagName)
def __call__(self, f):
self.functions.append(f)
return f
def invoke(self, *args, **kwargs):
return [f(*args, **kwargs) for f in self.functions]
@functools.lru_cache(maxsize=None) # memoization
def get_func_tag(tagName):
return TagDecorator(tagName)
现在我们创建标签:
tagA = get_func_tag("A")
tagB = get_func_tag("B")
@tagA
def funcA_1(*args, **kwargs):
print("A", args, kwargs)
# another way
@get_func_tag("A")
def funcA_2(*args, **kwargs):
print("A too", args, kwargs)
@tagB
def funcB_1():
print("B")
@tagB
def funcB_2():
print("B too")
# invoke all functions registered with tagA : passing arguments
tagA.invoke("hello", who="dolly")
# invoke all functions registered with tagA, another way.
get_func_tag("A").invoke()
# actually get_func_tag always returns the same instance
# for a given tagName, thanks to lru_cache
assert get_func_tag("A") == tagA
# Of course tagB can be invoked
tagB.invoke()
get_func_tag("B").invoke()
# but passing it args would be an error.
tagB.invoke("B") # TypeError: funcB_1() takes 0 positional arguments but 1 was given
必须注意标记的功能&#39;参数。如果对于同一个标签,您注册了不同的签名,则在调用它们时肯定会遇到问题。您可以使用inspect.signature功能处理此问题。但真正的签名匹配有点棘手。