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

Kar*_*sen 0 ruby python variable-assignment

在红宝石2.4中:

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

在python 3.5中:

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

为什么这个?

ETA:

y[x[0]] = x[0] = y.get(x[0], len(y))
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*ers 5

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

所以在Ruby中这会发生:

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

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

在Python中,这恰好发生了:

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

从Python 赋值语句文档:

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

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

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

if a = 42:
Run Code Online (Sandbox Code Playgroud)

if a == 42:
Run Code Online (Sandbox Code Playgroud)

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

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