Python赋值quirk w / list index assign,dict index assign和dict.get

时间:2017-07-14 08:54:36

标签: python ruby variable-assignment

在ruby 2.4中:

x = ['a']
y = {}
x[0] = y[x[0]] = y.fetch(x[0], y.length)
puts y #=> {"a"=>0}

在python 3.5中:

x = ['a']
y = {}
x[0] = y[x[0]] = y.get(x[0], len(y))
print(y) #=> {0: 0}

为什么会这样?

ETA:

y[x[0]] = x[0] = y.get(x[0], len(y))

产生预期的行为(这让我很懊恼。)

1 个答案:

答案 0 :(得分:5)

Ruby和Python是不同的语言,并做出不同的选择。在Python中,分配是语句,并从从左到右评估多个分配目标。 Ruby做出了其他选择;作业是表达式,因此以相反的顺序进行评估。

所以在Ruby中会发生这种情况:

  • 评估y.fetch(x[0], y.length),生成0(密钥丢失,y为空)。
  • 评估y[x[0]] = 0y['a'] = 0。这是一个导致0
  • 的表达式
  • 评估x[0] = 00作为y[x[0]] = 0作业表达式的结果。)

请注意,在Ruby中,赋值是表达式。它可以嵌套在其他表达式中,赋值表达式的结果是赋值后的目标值。

在Python中,这恰好发生了:

  • 评估y.get(x[0], len(y)),生成0(密钥丢失,y为空)。
  • 评估x[0] = 0
  • 评估y[x[0]] = 0y[0] = 0

来自Python assignment statements documentation

  

赋值语句计算表达式列表(请记住,这可以是单个表达式或以逗号分隔的列表,后者产生元组)并将单个结果对象从左到右分配给每个目标列表。

因此,右侧的表达式首先评估 ,然后从左到右分配给每个目标。

Python故意制作了赋值语句,因为它们之间存在差异:

if a = 42:

if a == 42:

是如此难以发现,即使故意真的伤害了代码的可读性。在Python中,可读性很重要。很多。

一般来说,您确实希望避免对名称进行分配,这些名称随后也会在同一语句的后续分配中使用。不要分配到x[0],然后在同一作业中再次使用x[0],这只是非常混乱。