52

たとえば、Python 組み込みpow()関数を考えてみましょう。

xs = [1,2,3,4,5,6,7,8]

from functools import partial

list(map(partial(pow,2),xs))

>>> [2, 4, 8, 16, 32, 128, 256]

しかし、xs を 2 乗するにはどうすればよいでしょうか。

取得するため[1, 4, 9, 16, 25, 49, 64]

list(map(partial(pow,y=2),xs))

TypeError: pow() takes no keyword arguments

リスト内包表記の方が簡単なのはわかっています。

4

12 に答える 12

51

いいえ

ドキュメントによると、これを行うことはできません(私自身を強調します):partial

部分.args

位置引数の前に付加される左端の位置引数


powあなたはいつでもキーワード引数を持つためにただ「修正」することができます:

_pow = pow
pow = lambda x, y: _pow(x, y)
于 2012-06-23T23:29:29.587 に答える
19

この単純なワンライナーを使用すると思います:

import itertools
print list(itertools.imap(pow, [1, 2, 3], itertools.repeat(2)))

アップデート:

また、便利な解決策よりも面白い解決策を思いつきました。Python3では...リテラルが意味するという事実から利益を得ている、美しい構文糖衣です。Ellipsisこれは の修正版でpartial、左端と右端の間の位置引数を省略できるようになっています。唯一の欠点は、省略記号を引数として渡すことができなくなったことです。

import itertools
def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(newfunc.leftmost_args + fargs + newfunc.rightmost_args), **newkeywords)
    newfunc.func = func
    args = iter(args)
    newfunc.leftmost_args = tuple(itertools.takewhile(lambda v: v != Ellipsis, args))
    newfunc.rightmost_args = tuple(args)
    newfunc.keywords = keywords
    return newfunc

>>> print partial(pow, ..., 2, 3)(5) # (5^2)%3
1
>>> print partial(pow, 2, ..., 3)(5) # (2^5)%3
2
>>> print partial(pow, 2, 3, ...)(5) # (2^3)%5
3
>>> print partial(pow, 2, 3)(5) # (2^3)%5
3

したがって、元の質問の解決策は、このバージョンの部分的なものになりますlist(map(partial(pow, ..., 2),xs))

于 2012-06-23T23:43:03.747 に答える
8

このためのヘルパー関数を作成できます。

from functools import wraps
def foo(a, b, c, d, e):
    print('foo(a={}, b={}, c={}, d={}, e={})'.format(a, b, c, d, e))

def partial_at(func, index, value):
    @wraps(func)
    def result(*rest, **kwargs):
        args = []
        args.extend(rest[:index])
        args.append(value)
        args.extend(rest[index:])
        return func(*args, **kwargs)
    return result

if __name__ == '__main__':
    bar = partial_at(foo, 2, 'C')
    bar('A', 'B', 'D', 'E') 
    # Prints: foo(a=A, b=B, c=C, d=D, e=E)

免責事項: キーワード引数を使用してこれをテストしていないため、それらが原因で爆発する可能性があります。また、これが何@wrapsに使用されるべきかはわかりませんが、正しいように思えました。

于 2012-06-23T23:10:46.610 に答える
4

クロージャーを使用できます

xs = [1,2,3,4,5,6,7,8]

def closure(method, param):
  def t(x):
    return method(x, param)
  return t

f = closure(pow, 2)
f(10)
f = closure(pow, 3)
f(10)
于 2012-06-23T23:16:55.200 に答える
2

それを行う1つの方法は次のとおりです。

def testfunc1(xs):
    from functools import partial
    def mypow(x,y): return x ** y
    return list(map(partial(mypow,y=2),xs))

ただし、これにはpow関数の再定義が含まれます。

パーシャルの使用が「必要ない」場合は、単純なラムダがトリックを実行します

def testfunc2(xs):
    return list(map(lambda x: pow(x,2), xs))

そして、2の捕虜をマッピングする特定の方法は次のようになります

def testfunc5(xs):
    from operator import mul
    return list(map(mul,xs,xs))

しかし、これらのどれも、キーワード引数に関連する部分的なアプリケーションの問題に直接完全に対処していません

于 2012-06-23T22:59:28.917 に答える