在 python 中使用字典作为输入调用 map 和 lambda 中的方法

call a method in map and lambda using dictionary as input in python

test_input = {"oneone": 1, "twotwo": 2, "threethree": 3}

def testmethod(no):
    print(f"Number {no}")
    return True, f"Number {no}"

不使用 lambdamap:

d = {}
for k, v in test_input.items():
    ret, out = testmethod(v)
    if ret:
        d[k] = out

我尝试在下面的行中使用 lambdamap 进行迭代:

>>> dict(map(lambda ref: testmethod(ref), list(test_input.values())))
{True: 'Number 3'}

使用 maplambda 的预期输出:

{'oneone': 'Number 1', 'twotwo': 'Number 2', 'threethree': 'Number 3'}

您可以按如下方式重写循环:

d = {}
for k, v in test_input.items():
    tup = testmethod(v)
    if tup[0]:
       d[k] = tup[1]

关键是打包和解包两个 return 值会分散您的注意力,让您忽略它们实际上是一个 return 值这一事实。

将此见解与海象运算符相结合以合并赋值行和条件行:

if (tup := testmethod(v))[0]:

现在你有了一些类似于字典理解的东西:

d = {k: tup[1] for k, v in test_input.items() if (tup := testmethod(v))[0]}

如果您使用的是旧版本 python(3.8 之前的版本),或者出于其他原因想要避免使用海象,则需要过滤结果。您的 lambda 放错了地方:lambda ref: testmethod(ref) 只是 testmethod 多了一些步骤。诀窍是在完成映射后拆分流。然后,您可以使用 itertools.compress:

之类的内容进行过滤
from itertools import compress

rets, outs = zip(*map(testmethod, test_input.values()))
d = dict(compress(zip(test_input.keys(), outs), rets))

这是一个相当丑陋且效率低下的双线。作为一个班轮,你可以让它变得更糟。为此,您将 rets, outs 变成一个列表,反转它,并在 test_input.keys() 之后将其展开为一个 zip 以生成一个迭代器,该迭代器产生 key, value, filter:

d = {k: v for k, v, tf in zip(test_input. keys(), *list(zip(*map(testmethod, test_input.values())))[::-1]) if tf}