繁体   English   中英

Python将一个函数分配给另一个函数

[英]Python assign a function to another function

我试图将一个函数分配给另一个函数,该赋值的左侧可以作为String使用。 例如我正在寻找的方法的主体是

def change_function_defintion(name_of_function = 'module1.function1'
       , function_object):
    # Can I do eval(name_of_function) = function_object ? will that work?
    pass

问题:

  1. 我该如何实现? 显然,如果我调用上述方法,然后再调用module.function1,我希望新功能可以使用。
  2. 我是在单元测试的上下文中执行此操作的,即模拟多个功能,运行测试,然后基本上“模拟”它们。 所说的方法有什么问题吗?

我认为最好使用Mock这样的模拟库。 使用patch您可以在上下文管理器或函数的范围内更改函数的行为,然后使其恢复正常状态。 例如:

from mock import patch

with patch('module1.function1') as function1:
    function1.side_effect = function_object
    # Do stuff

如果在with块内调用function1 ,它将被function_object替换。

同样,在函数内打补丁:

@patch('module1.function1')
def my_test(function1):
    function1.side_effect = function_object
    # Do stuff

我的方法:

import importlib

def change_function_defintion(name_of_function = 'module1.function1'
   , function_object):
   my_mod = importlib.import_module('module1')
   setattr(my_mod, function1, function_object)

现在更长的咆哮:

例如, 如果已经在本地名称空间中导入了module1该方法可能会起作用,您可以执行以下操作:

>>> a = eval('str')
>>> a
<type 'str'>
>>> a(123)
'123'

在单元测试的模拟环境中,可能会有更好的方法。

您可以在此处查看: http : //pycheesecake.org/wiki/PythonTestingToolsTaxonomy#MockTestingTools中的某些库,这些库使您可以在单元测试中对模拟对象进行更多控制。

编辑:

您可以执行以下操作来动态导入模块:

>>> import importlib
>>> my_mod = importlib.import_module('mymodule1')

然后,您可以访问模块内部的可用功能,或通过eval / getattr获取它们:

my_function = getattr(my_mod,'somefunction')

当然,如果您想将该函数交换给其他对象:

my_mod.functionName = newFunction

模拟存在一些问题,如果可能,您可以考虑使用其他测试方法:

我认为以下将满足您的要求(但您可能需要更强大的解析):

def set_named_fun(funname, fun) :
    import sys
    modname, funname =  funname.rsplit('.')
    mod = sys.modules[modname]
    setattr(mod, funname, fun)

这里的假设是:

  • 拥有该功能的模块已经导入,并且
  • 您需要将目标函数称为全限定名

这两个假设有点紧张。 在很多情况下,您可以简单地进行以下操作:

import legend
legend.monkey = lambda : "great sage, equal of heaven"

Python函数装饰器

首先,您要谈论的概念是function decorator的概念。 通过将函数修饰符放在该函数定义开始之前的行上(符号@ ),将其应用于该函数定义。 它是用于修改功能行为或执行功能组合的工具。 这是一个例子

class entryExit(object):

    def __init__(self, f):
        self.f = f

    def __call__(self):
        print "Entering", self.f.__name__
        self.f()
        print "Exited", self.f.__name__

@entryExit # decorator
def func1(): # decorated function
    print "inside func1()"

@entryExit
def func2():
    print "inside func2()"

我我跑

func1()
func2()

我得到

Entering func1
inside func1()
Exited func1
Entering func2
inside func2()
Exited func2

Python unittest.mock.patch()

patch充当函数装饰器,类装饰器或上下文管理器。 在函数主体或with语句内部,目标被新对象修补。 当function / with语句退出时,撤消补丁。

修补程序可让您在with语句中修改函数行为。

这是一个示例,其中patch()与with语句一起用作上下文管理器。

>>> with patch.object(ProductionClass, 'method', return_value=None) 
  as mock_method:
...     thing = ProductionClass()
...     thing.method(1, 2, 3)
...
>>> mock_method.assert_called_once_with(1, 2, 3)

可以使用“ getattr”来使用函数的字符串名称(函数是一个对象)来获取函数。 然后,您可以更改名称并在新的命名调用中调用/调用其他名称(原始命名函数)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM