通过迭代一个函数来创建两个字典,该函数在Python中返回两个元素的元组

通过迭代一个函数来创建两个字典,该函数在Python中返回两个元素的元组,python,dictionary-comprehension,Python,Dictionary Comprehension,我想通过字典理解同时在python中创建两个字典。这两个字典共享同一个键集,但每个键的值不同。因此,我使用一个函数返回两个值的元组,并希望字典理解可以同时创建这两个字典 我有一个函数 def my_func(foo): 呜呜呜呜。。。 返回a,b 我将创建两个字典 dict_of_a,dict_of_b=({key:my_func(key)[0]},{key:my_func(key)[1]}用于键列表中的键) 有没有更好的代码来改进它?在我看来,每次迭代都会调用两次my_func(key),

我想通过字典理解同时在python中创建两个字典。这两个字典共享同一个键集,但每个键的值不同。因此,我使用一个函数返回两个值的元组,并希望字典理解可以同时创建这两个字典

我有一个函数

def my_func(foo):
呜呜呜呜。。。
返回a,b
我将创建两个字典

dict_of_a,dict_of_b=({key:my_func(key)[0]},{key:my_func(key)[1]}用于键列表中的键)
有没有更好的代码来改进它?在我看来,每次迭代都会调用两次my_func(key),这会减慢代码的速度。正确的方法是什么

my_func(key)将在每次迭代中调用两次,从而降低代码的速度

别担心。除非您需要进行数千次/数百万次迭代,并且脚本需要花费不合理的长时间才能完成,否则您不应该担心可以忽略不计的优化收益

也就是说,我会用这样的方式:

如果uuuu name_uuuu=='\uuuuuuu main\uuuuuu':
定义我的函数(k):
返回f'a{k}',f'b{k}'
键=['x','y','z']
结果=(键中k的my_func(k))
分组的_值=zip(*结果)
da,db=[dict(zip(键,v))表示分组的_值中的v]
打印(da)
打印(db)
#输出:
#{'x':'ax','y':'ay','z':'az'}
#{'x':'bx','y':'by','z':'bz'}

不能在一个dict理解中创建两个dict。 如果您的主要目标是只调用
my_func
一次来创建两个dict,请使用以下函数:

def mkdicts(keys):

    dict_of_a = {}
    dict_of_b = {}

    for key in keys:
        dict_of_a[key], dict_of_b[key] = my_func(key)

    return dict_of_a, dict_of_b
使用有序切片:


常规循环可能是最好的方法。如果要使用
functools
,可以编写:

>>> def func(foo): return foo[0], foo[1:]
... 
>>> L = ['a', 'ab', 'abc']
>>> functools.reduce(lambda acc, x: tuple({**d, x: v} for d, v in zip(acc, func(x))), L, ({}, {}))
({'a': 'a', 'ab': 'a', 'abc': 'a'}, {'a': '', 'ab': 'b', 'abc': 'bc'})
函数
reduce
是一个折叠式函数:它从
L
中获取当前累加器(这里是正在构建的DICT)和下一个值:

  • zip中的
    d,v(acc,func(x))
    一次提取一个dict和
    func的返回值的匹配元素
    
  • {**d,x:v}
    用当前值更新dict

我不建议使用这种代码,因为它很难维护。

如果有多行代码,可以使用三倍回号开始代码块,然后再次使用三倍回号结束代码块。事实上,我很快意识到我的代码不起作用——这在python中是不可接受的语法。
def myfunc(k):
    return k + '0', k + '1'

list_of_keys = ['a', 'b', 'c']

groups = [(k,v) for k in list_of_keys for v in myfunc(k)]
dict_of_a, dict_of_b = dict(groups[::2]), dict(groups[1::2])

print(dict_of_a)   # {'a': 'a0', 'b': 'b0', 'c': 'c0'}
print(dict_of_b)   # {'a': 'a1', 'b': 'b1', 'c': 'c1'}
>>> def func(foo): return foo[0], foo[1:]
... 
>>> L = ['a', 'ab', 'abc']
>>> functools.reduce(lambda acc, x: tuple({**d, x: v} for d, v in zip(acc, func(x))), L, ({}, {}))
({'a': 'a', 'ab': 'a', 'abc': 'a'}, {'a': '', 'ab': 'b', 'abc': 'bc'})