使用python functools partial的参数顺序

时间:2016-01-23 00:17:49

标签: python multiprocessing functools

我正在尝试使用pool.map的多处理来加速函数的执行,但是iterable不是该函数的第一个参数。 Lambdas不会起作用,因为它们不是可选择的。我尝试使用functools.partial创建一个新函数,但它失败了TypeError。下面是一个非常简单的例子,结果相同。如果我将参数顺序切换为f(i, s1, s2),它将按预期工作。

为什么参数顺序在这里很重要?当我阅读doc时,对我来说并不明显。

我有哪些选择(除了改变原始功能之外)?

import multiprocessing
from functools import partial


def f(s1, s2, i):
    return [s1] + [s2]*i

def main():
    # other code... constants for f aren't known until runtime
    pool = multiprocessing.Pool()
    func = partial(f, s1='a', s2='c')
    for strings in pool.map(func, range(10)):
        print(strings)
    pool.close()
    pool.join()

if __name__ == '__main__':
    main()

更新: 我能想到的最好的方法是在模块级别创建一个包装器来切换参数顺序,然后在包装器中创建一个部分包装器。看起来不漂亮或看似pythonic。

import multiprocessing
from functools import partial


def f(s1, s2, i):
    return [s1] + [s2]*i

def wrapper(i, s1, s2):
    return f(s1, s2, i)

def main():
    # other code... constants for f aren't known until runtime
    pool = multiprocessing.Pool()
    func = partial(wrapper, s1='foo', s2='bar')
    for strings in pool.map(func, range(10)):
        print(strings)
    pool.close()
    pool.join()

if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:1)

由于pool.map正在调用f(i, s1='a', s2='c'),因此订单很重要。 你可以像这样编写你的部分:

import multiprocessing

def f(s1, s2, i):
    return [s1] + [s2]*i

def f2(i):
    return f('a','c',i)

if __name__ == '__main__':
    pool = multiprocessing.Pool()
    for strings in pool.map(f2, range(10)):
        print(strings)
    pool.close()
    pool.join()

如果您使用的是python3.3,pool.starmap可供您使用:

import multiprocessing
from itertools import repeat

def f(s1, s2, i):
    return [s1] + [s2]*i

if __name__ == '__main__':
    pool = multiprocessing.Pool()
    for strings in pool.starmap(f, zip(repeat('a'), repeat('c'), range(10))):
        print(strings)
    pool.close()
    pool.join()