3

関数を別の関数に割り当てようとしていますが、割り当ての左側は文字列として利用できます。たとえば、私が探しているメソッドの本体は

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. 私はこれを単体テストのコンテキストで行っています。つまり、いくつかの関数をモックし、テストを実行してから、基本的にそれらを「モック解除」します。上記のアプローチに問題はありますか?
4

6 に答える 6

5

Mockのようなモッキング ライブラリを使用する方がよいと思います。You を使用patchすると、コンテキスト マネージャーまたは関数のスコープ内で関数の動作を変更し、後で通常の状態に戻すことができます。例えば:

from mock import patch

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

function1がブロック内で呼び出された場合、withに置き換えられfunction_objectます。

同様に、関数内でのパッチ:

@patch('module1.function1')
def my_test(function1):
    function1.side_effect = function_object
    # Do stuff
于 2013-05-09T10:36:39.143 に答える
1

私のアプローチ:

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
于 2013-05-09T10:19:44.997 に答える
1

Python 関数デコレーター

まず、あなたが話している概念は関数デコレータの概念です。関数デコレーターは、関数定義が始まる前の行 (シンボル@) に配置することで、関数定義に適用されます。関数の動作を変更したり、関数の合成を操作したりするためのツールです。ここに例があります

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 ステートメントが終了すると、パッチは取り消されます。

Patch を使用すると、withステートメント内の関数の動作を変更できます。

withこれは、 patch() がステートメントでコンテキストマネージャーとして使用される例です。

>>> 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)
于 2013-05-09T11:27:56.187 に答える
0

「getattr」を使用して、関数の文字列名を使用して関数を取得できます (関数はオブジェクトです)。次に、名前を変更して、新しい名前付き呼び出しで別のもの (元の名前付き関数) を呼び出す/呼び出すことができます。

于 2013-05-09T10:26:47.520 に答える