0
0

More than 3 years have passed since last update.

partial関数で部分適用した関数を実行した際に、"TypeError: add() got multiple values for argument 'xxx'"が発生した

Last updated at Posted at 2020-12-12

環境

  • python 3.8

問題

functools.partialを使って、関数を部分適用したいです。

以下のようなコードを書いたら、"TypeError: add() got multiple values for argument 'a'"というエラーが発生しました。

from functools import partial

def add(a:int, b:int) -> int:
    return a + b

# 引数`a`をキーワード引数として指定する
add_a1 = partial(add, a=1)

# a=1,b=2,result=3 を期待していた
result = add_a1(2)

# TypeError: add() got multiple values for argument 'a'

いろんなパターンを試す

以下のようなコードの場合、エラーは発生しませんでした。

# 引数`a`を位置引数として指定する
foo = partial(add, 1)
result = foo(2)
print(result)
# => 3

add_a1 = partial(add, a=1)
# 引数`b`をキーワード引数として指定する
result = add_a1(b=2)
print(result)
# => 3

partial関数の中身を見る

functools.partial関数のドキュメントによると、partial関数の中身は以下のコードと等価です。

def partial(func, /, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = {**keywords, **fkeywords}
        return func(*args, *fargs, **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

エラーが起きたときのコードは add(2, a=1)を実行していたので、"TypeError: add() got multiple values for argument 'a'" というエラーが発生していたようです。

まとめ

部分適用した後の関数が、位置引数で指定できないのは少し不便です。

# NG -> 不便
add_a1(2)

# OK
add_a1(b=2)

部分適用した後に残る引数(上記だと引数b)より前の引数は、partial関数で部分適用した関数を作る際、位置引数として指定するのがよいと思います。

def add(a,b,c):
    return a+b+c

# 引数aを残す
foo1 = partial(add, b=2, c=3)
foo1(1)
# => 6

# 引数bを残す
foo2 = partial(add, 1, c=3)
foo2(2)
# => 6

# 引数cを残す
foo3 = partial(add, 1, 2)
foo3(3)
# => 6

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0