Python,根据调用者改变函数行为,是否可能?

时间:2013-03-12 15:56:16

标签: python design-patterns

在此Python代码段中:

def get_something():
    return something

def do_staff():
    value = get_something()
    doit(value)

def test():
    # ?????
    doStaff()

更改get_something返回的值的最佳方法是什么,具体取决于是否通过test or not调用?唯一的限制是我不想修改do_staff

3 个答案:

答案 0 :(得分:2)

回答您提出的问题

您要么需要一个可选参数来更改函数的行为。这意味着您需要do_staff中的可选参数,因为这里真正的问题是如何告诉get_something调用do_staff的地方test或其他地方):

def get_something(test=False):
    if test:
        return something + test_var
    return something

def do_staff(test=False):
    value = get_something(test=test)
    return doit(value)

def test():
    return do_staff(test=True)

如果你因为某种原因确实非常反对修改do_staff,那么你必须通过堆栈查看测试方法是否在那里,就像评论中提到的那样 - 但是很快变得丑陋。否则,告诉函数如何被调用的唯一方法是通过指示符。

实际上解决您的问题

从上下文来看,我认为你真正想要的是是知道如何测试这个东西而不必在测试/生产环境之间修改太多的代码。在这种情况下,我建议采用一种完全不同的方法:不要试图查看是否从某个地方调用过,只需定义/导入is_debug_on变量并使用它。

is_debug_on = False

def get_something():
    if is_debug_on:
        pass # Do testing stuff, print statements, etc.
    return something # Do normal stuff.

def do_staff():
    value = get_something()

def test():
    is_debug_on = True
    do_staff()
    is_debug_on = False

显然,如果你可以将它全部放在一个类中,或者使用logging包等等,这是更清洁的,但这是基本的想法。您可以通过这种方式测试所有代码,而不必在移动到生产时删除任何内容,因为调试模式将被关闭。 奖金:当生产中出现问题时,您将能够重新启用调试并(希望)立即获得一些有用的信息!

答案 1 :(得分:1)

可选参数?

def get_something(from_test=False):
    if from_test:
        return something_test
    else:
        return something

def test():
    get_something(True)

答案 2 :(得分:0)

我的解决方案基于接受的答案:

from contextlib import contextmanager

VALUE = 'normal'

@contextmanager
def test_context():
    global VALUE
    original = VALUE
    VALUE = 'test'
    yield
    VALUE = original

def get_something():
    return VALUE + ' value'

def do_staff():
    return get_something()

def test():
    with test_context():
        return do_staff()

if __name__ == '__main__':
    print 'do_staff() => ', do_staff()
    print 'test() => ', test()
    print 'do_staff() again  => ', do_staff()