装饰函数的最佳方法是什么,但仅限于本地范围。例如,我们有以下内容:
def a():
do stuff
b()
do stuff
我想创建一个函数c()
来执行相同的stuff
但是装饰b所以它会添加一些额外的东西。我找到了一种方法,但它在全局范围内改变了b():
def c():
global b
b = decorator(b)
a()
有没有办法做到这一点,但没有全局更改功能?
答案 0 :(得分:2)
您可以修补函数b
,并将其替换为其他函数。在Python 3中使用unittest.mock
,或在Python 2中使用mock
:
from unittest.mock import patch
def c():
with patch('b', decorator(b)):
a()
# Or, as a decorator
@patch('b', decorator(b))
def c():
a()
通过修补,您基本上用自己的实例替换b
实例。
答案 1 :(得分:1)
Python允许任何对象成为可调用的,而不仅仅是函数。
您可以使用以下内容:
class A(object):
def __init__(self, func=b):
self.func = func
def __call__(self):
# do stuff
self.func()
# do other stuff
然后使用a = A()
,a()
只会调用f
,但如果您编写c = A(decorator(b))
,c()
将调用已修饰的版本
答案 2 :(得分:1)
由于您正在重新绑定b()
,因此调用a()
会尊重更新后的b()
,您可以保存原始b()
,然后将其恢复。这可能不是最有效的方式,但它对我有用。
import copy
def c():
global b
orig_b = copy.deepcopy(b)
b = decorator(b)
a()
b = orig_b