5

ある API から別の API に移行する場合、各 API の同様のキーワード間でマッピングすると役立つ場合があります。これにより、ユーザーが内部でさまざまな API に煩わされることなく、1 つのコントローラー API を他のライブラリに柔軟にディスパッチできるようになります。

あるライブラリ にother_apiというメソッドが"logarithm"あり、ベースのキーワード引数がコードから除外する必要があるものであるとし"log_base_val"ます。それを使用するには、other_api次のように入力する必要があります(たとえば):

other_api.logarithm(log_base_val=math.e)

次のようなおもちゃのクラスを考えてみましょう。

import other_api
import math
import functools

class Foo(object):
    _SUPPORTED_ARGS = {"base":"log_base_val"}

    def arg_binder(self, other_api_function_name, **kwargs):
        other_api_function = getattr(other_api, other_api_function_name)
        other_api_kwargs = {_SUPPORTED_ARGS[k]:v for k,v in kwargs.iteritems()}
        return functools.partial(other_api_function, **other_api_kwargs)

を使用すると、次のようFooに、この引数が常に と呼ばれる他の A​​PI をマップできます。base

f = Foo()
ln = f.arg_binder("logarithm", base=math.e)

andは ( in 、 fromを使用して)lnと論理的に同等です。log_base_val=math.ekwargsfunctools

other_api.logarithm(*args, **kwargs)

ただし、呼び出しによって同じ引数を手動でバインドするfunctoolsと、異なる関数オブジェクトが生成されます。

In [10]: import functools

In [11]: def foo(a, b):
   ....:     return a + b
   ....: 

In [12]: f1 = functools.partial(foo, 2)

In [13]: f2 = functools.partial(foo, 2)

In [14]: id(f1)
Out[14]: 67615304

In [15]: id(f2)
Out[15]: 67615568

したがって、テストはf1 == f2意図したとおりに成功しません。

In [16]: f1 == f2
Out[16]: False

問題は、引数バインディング関数が正しい出力関数オブジェクトになったかどうかをテストする規定の方法は何ですか?

4

1 に答える 1

7

オブジェクトのfunc属性partial()は、元の関数オブジェクトへの参照です。

f1.func is f2.func

関数オブジェクト自体はメソッドを実装していないため、ID をテストするために__eq__使用することもできます。is

同様に、partial().argspartial().keywordsには、呼び出されたときに関数に渡される引数とキーワード引数が含まれています。

デモ:

>>> from functools import partial
>>> def foo(a, b):
...     return a + b
... 
>>> f1 = partial(foo, 2)
>>> f2 = partial(foo, 2)
>>> f1.func is f2.func
True
>>> f1.args
(2,)
>>> f2.args
(2,)
>>> f1.keywords is None
True
>>> f2.keywords is None
True
于 2014-03-27T16:24:43.150 に答える