Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 避免在列表中多次调用同一函数_Python_Python 3.x - Fatal编程技术网

Python 避免在列表中多次调用同一函数

Python 避免在列表中多次调用同一函数,python,python-3.x,Python,Python 3.x,我有一个返回元组的函数,如下所示: def foo(i,j): # does stuff return (m,n) 我想对两个输入进行双列表理解,并获得返回元组中两个元素的和的值。我认为最简单的方法是: [foo(i,j)[0]+foo(i,j)[1]代表x中的i代表y中的j] 这种方法的问题是,每对i,j调用两次foo,使得列表理解速度比需要的慢。如何更改列表理解,使每对I,j只调用一次foo?尝试以下操作: [sum(foo(i,j)) for i in x for j i

我有一个返回元组的函数,如下所示:

def foo(i,j):
    # does stuff
    return (m,n)
我想对两个输入进行双列表理解,并获得返回元组中两个元素的和的值。我认为最简单的方法是:

[foo(i,j)[0]+foo(i,j)[1]代表x中的i代表y中的j]

这种方法的问题是,每对
i,j
调用两次
foo
,使得列表理解速度比需要的慢。如何更改列表理解,使每对
I,j
只调用一次
foo

尝试以下操作:

[sum(foo(i,j)) for i in x for j in y]
尝试Python的内置函数:

[sum(foo(i,j)) for i in x for j in y]
样本运行:

def foo(m,n):
    print(f'called: foo({m},{n})')
    return m,n

x = [1,2]
y = [3,4]

print('Run without sum() - expect 8 calls')
[foo(i,j)[0] + foo(i,j)[1] for i in x for j in y]

print('\nRun with sum() - expect 4 calls')
[sum(foo(i,j)) for i in x for j in y]

> Run without sum() - expect 8 calls
> called: foo(1,3)
> called: foo(1,3) 
> called: foo(1,4) 
> called: foo(1,4)
> called: foo(2,3) 
> called: foo(2,3) 
> called: foo(2,4) 
> called: foo(2,4)
> [4, 5, 5, 6]
>
> Run with sum() - expect 4 calls
> called: foo(1,3)
> called: foo(1,4)
> called: foo(2,3)
> called: foo(2,4)
> [4, 5, 5, 6]
您可以使用Python 3.8+

[p[0] + p[1] for i in x for j in y if (p := foo(i,j))]
需要if条件使其成为双for循环的有效用法(单for循环不需要)。但是,如果总是真的,因为foo返回一个元组

更好的版本(由@MisterMiyagi提供)


这是由于需要if条件。

操作符模块将所有操作符作为一级函数提供
operator.add(a,b)
相当于
a+b
,而
operator.add(*ab)
相当于
operator.add(ab[0],ab[1])

使用
add
sum
稍快一些:

In [1]: %timeit [add(*foo(i, j)) for i in range(50) for j in range(50)]
409 µs ± 8.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [2]: %timeit [sum(foo(i, j)) for i in range(50) for j in range(50)]
554 µs ± 5.97 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [3]: %timeit [add(*foo(i, j)) for i in range(500) for j in range(500)]
47.2 ms ± 215 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [4]: %timeit [sum(foo(i, j)) for i in range(500) for j in range(500)]
61.5 ms ± 215 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

尼斯:-)我不熟悉这个,接受这个答案是因为它是最简单的general@bleutooth65--是的,海象是3.8+的一个很好的特性。不需要有害的
if
条款!改为使用
[(p:=foo(i,j)[0]+p[1]表示x中的i表示y中的j]
。@MisterMiyagi--表达式中有错误吗?我使用as is:
p:=foo(i,j)]^SyntaxError:无效语法
from operator import add
[add(*foo(i,j)) for i in x for j in y]
In [1]: %timeit [add(*foo(i, j)) for i in range(50) for j in range(50)]
409 µs ± 8.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [2]: %timeit [sum(foo(i, j)) for i in range(50) for j in range(50)]
554 µs ± 5.97 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [3]: %timeit [add(*foo(i, j)) for i in range(500) for j in range(500)]
47.2 ms ± 215 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [4]: %timeit [sum(foo(i, j)) for i in range(500) for j in range(500)]
61.5 ms ± 215 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)