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

时间:2022-05-17 00:43:45

Why in the first case the dictionary keys have been overwritten, but in the second case the values have been overwritten?

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

>>> 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}

4 个解决方案

#1


2  

If we rewrite as a standard loop, the situation may become clearer (note that I've used isinstance as a better class check):

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

Option 1:

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

Option 2:

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

Clearly the former is modifying the keys, the latter is modifying the values.

显然,前者正在修改密钥,后者正在修改值。


You don't say what you actually wanted to happen, but if you were trying to skip over k: v pairs where the value is a dictionary, i.e.:

你没有说你真正想要发生什么,但如果你试图跳过k:v对,其中值是字典,即:

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

then the "dictionary comprehension" equivalent would look like:

然后“字典理解”等效看起来像:

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

Note that the if condition appearing after the for acts as a filter.

请注意,在for之后出现的if条件充当过滤器。

#2


0  

You are only selecting key on basis of condition, the value remains same whether if is executed or else. Parenthesis would make it more readable.

您只是根据条件选择键,无论是否执行,值都保持不变。括号将使其更具可读性。

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

#3


0  

Because if...else binds more tightly than :. And it's good it does, since otherwise you'd have {('a': 1), None}, and that's not a dict. :-)

因为如果......别紧紧地绑定:。这样做很好,因为否则你会有{('a':1),无},而这不是一个字典。 :-)

You probably wanted

你可能想要

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

But be careful: are you really singling out just dicts here? Or any mapping? Or anything that's not an int? Or...

但要小心:你真的在这里单挑出来吗?还是任何映射?或者任何不是int的东西?要么...

#4


0  

See the language spec on dict comprehensions:

请参阅dict理解的语言规范:

If you analyze the dict-comprehension None if v.__class__ == dict else k: v for k, v in a.items() it will have to match the form expression : expression comp_for. So let's look at what comp_for could be. It states that comp_for would have to start with for and there's only one for in it so for k, v in a.items() is the for_comp and the rest would need to be on the form expression : expression, but there's only one colon so the first expression (ie the key) would be None if v.__class__ == dict else k and the second (ie the value) v. The if and else are part of a conditional expression.

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

The comprehension means that for each k, v in a.items form a key-value pair with the key None if v.__class__ == dict and k otherwise and the value being v.

理解意味着对于每个k,a.items中的v形成一个键值对,如果v .__ class__ == dict,则键为无,而值为v。

#1


2  

If we rewrite as a standard loop, the situation may become clearer (note that I've used isinstance as a better class check):

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

Option 1:

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

Option 2:

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

Clearly the former is modifying the keys, the latter is modifying the values.

显然,前者正在修改密钥,后者正在修改值。


You don't say what you actually wanted to happen, but if you were trying to skip over k: v pairs where the value is a dictionary, i.e.:

你没有说你真正想要发生什么,但如果你试图跳过k:v对,其中值是字典,即:

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

then the "dictionary comprehension" equivalent would look like:

然后“字典理解”等效看起来像:

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

Note that the if condition appearing after the for acts as a filter.

请注意,在for之后出现的if条件充当过滤器。

#2


0  

You are only selecting key on basis of condition, the value remains same whether if is executed or else. Parenthesis would make it more readable.

您只是根据条件选择键,无论是否执行,值都保持不变。括号将使其更具可读性。

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

#3


0  

Because if...else binds more tightly than :. And it's good it does, since otherwise you'd have {('a': 1), None}, and that's not a dict. :-)

因为如果......别紧紧地绑定:。这样做很好,因为否则你会有{('a':1),无},而这不是一个字典。 :-)

You probably wanted

你可能想要

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

But be careful: are you really singling out just dicts here? Or any mapping? Or anything that's not an int? Or...

但要小心:你真的在这里单挑出来吗?还是任何映射?或者任何不是int的东西?要么...

#4


0  

See the language spec on dict comprehensions:

请参阅dict理解的语言规范:

If you analyze the dict-comprehension None if v.__class__ == dict else k: v for k, v in a.items() it will have to match the form expression : expression comp_for. So let's look at what comp_for could be. It states that comp_for would have to start with for and there's only one for in it so for k, v in a.items() is the for_comp and the rest would need to be on the form expression : expression, but there's only one colon so the first expression (ie the key) would be None if v.__class__ == dict else k and the second (ie the value) v. The if and else are part of a conditional expression.

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

The comprehension means that for each k, v in a.items form a key-value pair with the key None if v.__class__ == dict and k otherwise and the value being v.

理解意味着对于每个k,a.items中的v形成一个键值对,如果v .__ class__ == dict,则键为无,而值为v。