2017-03-29 33 views
0

装饰函数的最佳方式是什么,但只能在本地范围内。例如,我们有以下几点:Python:只在本地装饰函数的最佳方法

def a(): 
    do stuff 
    b() 
    do stuff 

我想打一个功能c(),做同样的stuff但装饰B上它增加了一些额外的东西。我发现了一个办法做到这一点,但它改变B()全球:

def c(): 
    global b 
    b = decorator(b) 
    a() 

有没有办法做到这一点,但没有改变全局函数B?

+0

'b = decorator(b)' - 我认为这覆盖了你的全局函数'b'。也许把它分配给另一个变量就是你要找的东西:'x = decorator(b)'。 – ikkuh

+0

不能是x,因为我想在c()内部有不同的b函数,所以当我在c()内调用()时,a()是不同的,但只有当我在c()中调用它时() – edgarstack

回答

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()会因为你重新绑定b()使调用装饰版本

1

拨打a()将尊重更新的b(),您可以保存原始的b(),然后恢复。这可能不是最有效的方式,但它对我有用。

import copy 
def c(): 
    global b 
    orig_b = copy.deepcopy(b) 
    b = decorator(b) 
    a() 
    b = orig_b 
2

您可以修补函数b,并用另一个函数替换它。使用在Python 3 unittest.mock,或mock在Python 2本:

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实例。

+0

它可以工作,但你必须安装模拟。而且它似乎有一个模拟问题,当它试图安装六个(这个问题似乎很常见) – edgarstack

+0

是的,虽然'mock'是Python 3标准库的一部分。我不知道安装'六'和'mock'虽然在Py 2.7中。 –