为什么我们在 Python 字典生成器中有这种行为?

Why do we have this behavior in a Python dictionary generator?

为什么在第一种情况下字典键被覆盖,而在第二种情况下值被覆盖?

>>> a = {'a': 1, 'b': {'c': 3}}
>>> {None if v.__class__ == dict else k: v for k, v in a.items()}
{'a': 1, None: {'c': 3}}
>>> {k: v if v.__class__ != dict else None for k, v in a.items()}
{'a': 1, 'b': None}

你只是根据条件选择键,无论执行if还是执行else,值都是一样的。括号会使它更具可读性。

{(None if v.__class__ == dict else k): v for k, v in a.items()}

如果我们重写为标准循环,情况可能会变得更清楚(请注意,我使用 isinstance 作为更好的 class 检查):

选项 1:

d = {}
for k, v in a.items():
    d[None if isinstance(v, dict) else k] = v

选项 2:

d = {}
for k, v in a.items():
    d[k] = None if isinstance(v, dict) else v

很明显前者是修改key,后者是修改value。


你没有说出你实际上想要发生的事情,但如果你试图跳过 k: v值是字典的对,即:

d = {}
for k, v in a.items():
    if not isinstance(v, dict):
        d[k] = v

那么 "dictionary comprehension" 等价物看起来像:

{k: v for k, v in a.items() if not isinstance(v, dict)}

请注意 if 条件出现在 之后 for 作为过滤器。

因为 if...else 比 : 绑定得更紧密。它确实很好,否则你会得到 {('a': 1), None},这不是命令。 :-)

你可能想要

{k: v for k, v in a.items() if not isinstance(v, dict)}

但要小心:您真的在这里只挑出听写吗?或者任何映射?或者任何不是 int 的东西?或者...

请参阅 dict comprehensions 上的语言规范:

如果你分析 dict-comprehension None if v.__class__ == dict else k: v for k, v in a.items(),它必须匹配 expression : expression comp_for 的形式。那么让我们看看 comp_for 可能是什么。它指出 comp_for 必须以 for 开头并且其中只有一个 for 所以 for k, v in a.items()for_comp 其余的需要以 expression : expression,但只有一个冒号,所以第一个表达式(即键)将是 None if v.__class__ == dict else k,第二个(即值)将是 vifelse 是条件表达式的一部分。

理解的意思是对于a.items中的每个k, v与键None组成一个键值对if v.__class__ == dict and k 否则值为 v.