该应用程序有一个模块A
,其中包含一个装饰器,它将函数添加到列表中,该列表是A
中的模块级全局。函数列表用于模块中的其他函数。
A.py
import functools
things = []
def register(func):
@functools.wraps(func)
def inner(*args, **kwargs):
things.append(func)
return func
return inner
@register
def foo():pass
@register
def bar():pass
foo()
bar()
print(things)
此模式已复制到应用程序的其他部分,因此许多模块包含寄存器功能和模块级列表。
我希望通过在一个位置实现A.register
来减少重复量,但导入的模块需要拥有自己的本地功能列表。
我尝试导入A
并创建提供列表:
B.py
import A
things = []
@A.register
def baz():pass
@A.register
def quux():pass
baz()
quux()
print(things)
但所有功能都在A.things
注册:
>>> import A
[<function foo at 0x7f3ecdf466e0>, <function bar at 0x7f3ecdf467d0>]
>>> import B
[]
>>> print A.things
[<function foo at 0x7f3ecdf466e0>, <function bar at 0x7f3ecdf467d0>, <function baz at 0x7f3ecdf46410>, <function quux at 0x7f3ecdf469b0>]
有没有办法单独实现A.register
,但要在其导入的模块中填充列表?那是
>>> print A.things
[<function foo at 0x7f3ecdf466e0>, <function bar at 0x7f3ecdf467d0>]
>>> print B.things
[<function baz at 0x7f3ecdf46410>, <function quux at 0x7f3ecdf469b0>]
答案 0 :(得分:1)
您在模块A中只有register()
函数的单一实现。
模块B中没有变量things
,它[变量]仅属于模块A.
即使你在模块B中使用装饰器,它也是模块A中将被追加的变量things
。
要记住的另一个非常重要的一点是每次调用函数时都会附加变量things
。
如果您无法在每个模块中更改算法声明变量 things
并创建这样的装饰器:
(来自ryachza的代码)
def register(things=things):
def _register(func):
@functools.wraps(func)
def inner(*args, **kwargs):
things.append(func)
return func
return inner
return _register
但是,这不是使用装饰器的方法。
您可以在每个模块中创建一个变量things
,然后像这样添加它。您不必为此使用装饰器。
things = []
def foo():
pass
things.append(foo)
def bar():
pass
things.append(bar)
foo()
bar()
print(things)
答案 1 :(得分:1)
不完全相同但可能令人满意,您可以定义register
,如:
def register(things=things):
def _register(func):
@functools.wraps(func)
def inner(*args, **kwargs):
things.append(func)
return func
return inner
return _register
在A
中使用,如:
@register()
def foo():pass
@register()
def bar():pass
在B
之中:
@A.register(things)
def baz():pass
@A.register(things)
def quux():pass
如果需要,甚至可以这样:
@A.register(A.things)
def whatever():pass
答案 2 :(得分:0)
我可能需要对现有代码进行少量修改的其他答案的替代方法是更改模块B
,如:
...
things = []
A.things = things
@A.register
def baz():pass
...
基本上你所引用的任何东西都是可变的(在这种情况下是A.things
)。您当然可以保存对原始A.things
的引用,并在需要时在单个模块之间进行交换。