链式赋值如何进行?

2025-01-17 09:23:00
admin
原创
96
摘要:问题描述:引用某件事:>>> x = y = somefunction() 等同于>>> y = somefunction() >>> x = y 问题:x = y = somefunction() 和...一样x = somefunction() y =...

问题描述:

引用某件事:

>>> x = y = somefunction()

等同于

>>> y = somefunction()
>>> x = y

问题:

x = y = somefunction()

和...一样

x = somefunction()
y = somefunction()

根据我的理解,它们应该是相同的,因为somefunction只能返回一个值。


解决方案 1:

先左转

x = y = some_function()

相当于

temp = some_function()
x = temp
y = temp

注意顺序。最左边的目标首先被分配。(C 中的类似表达式可能按相反的顺序分配。)来自Python 赋值的文档:

...将单个结果对象从左到右分配给每个目标列表。

拆解后显示:

>>> def chained_assignment():
...     x = y = some_function()
...
>>> import dis
>>> dis.dis(chained_assignment)
  2           0 LOAD_GLOBAL              0 (some_function)
              3 CALL_FUNCTION            0
              6 DUP_TOP
              7 STORE_FAST               0 (x)
             10 STORE_FAST               1 (y)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE

注意:每个目标总是分配同一个对象。因此,正如 @Wilduck 和 @andronikus 指出的那样,您可能永远都不希望出现这种情况:

x = y = []   # Wrong.

在上述情况下,x 和 y 引用同一个列表。由于列表是可变的,因此向 x 追加内容似乎会影响y。

x = []   # Right.
y = []

现在您有两个名称引用两个不同的空列表。

解决方案 2:

somefunction如果返回可变值,它们的工作方式不一定相同。考虑一下:

>>> def somefunction():
...     return []
... 
>>> x = y = somefunction()
>>> x.append(4)
>>> x
[4]
>>> y
[4]
>>> x = somefunction(); y = somefunction()
>>> x.append(3)
>>> x
[3]
>>> y
[]

解决方案 3:

somefunction()如果每次调用时返回不同的值会怎样?

import random

x = random.random()
y = random.random()

解决方案 4:

当函数没有副作用并且以确定性的方式返回单例(给定其输入)时,才会产生相同的结果。

例如:

def is_computer_on():
    return True

x = y = is_computer_on()

或者

def get_that_constant():
    return some_immutable_global_constant

请注意,结果是一样的,但是实现结果的过程却不一样:

def slow_is_computer_on():
    sleep(10)
    return True

x 和 y 变量的内容相同,但该指令x = y = slow_is_computer_on()将持续 10 秒,而其对应指令x = slow_is_computer_on() ; y = slow_is_computer_on()将持续 20 秒。

如果函数没有副作用并且以确定的方式(给定其输入)返回不可变的,那将几乎相同。

例如:

def count_three(i):
    return (i+1, i+2, i+3)

x = y = count_three(42)

请注意,上一节中解释的相同捕获内容适用。

为什么我说“几乎”?因为:

x = y = count_three(42)
x is y  # <- is True

x = count_three(42)
y = count_three(42)
x is y  # <- is False

好吧,使用起来is有些奇怪,但这说明返回值不一样。这对于可变的情况很重要:

如果函数返回一个可变的变量,那么这很危险,并且可能会导致错误

这个问题也已经回答过了。为了完整起见,我重述一下这个论点:

def mutable_count_three(i):
    return [i+1, i+2, i+3]

x = y = mutable_count_three(i)

因为在那种情况下xy是同一个对象,执行类似的操作x.append(42)意味着xy都持有对现在有 4 个元素的列表的引用。

如果函数有副作用,情况就不一样了

考虑打印的副作用(我认为这是有效的,但也可以使用其他示例来代替):

def is_computer_on_with_side_effect():
    print "Hello world, I have been called!"
    return True

x = y = is_computer_on_with_side_effect()  # One print

# The following are *two* prints:
x = is_computer_on_with_side_effect()
y = is_computer_on_with_side_effect()

与打印不同,它可能是一种更复杂或更微妙的副作用,但事实仍然是:该方法被调用一次或两次,这可能会导致不同的行为。

如果函数的输入是非确定性的,情况就不一样了

也许是一种简单的随机方法:

def throw_dice():
    # This is a 2d6 throw:
    return random.randint(1,6) + random.randint(1,6)

x = y = throw_dice()  # x and y will have the same value

# The following may lead to different values:
x = throw_dice()
y = throw_dice()

但是,与时钟、全局计数器、系统内容等相关的事物在给定输入的情况下是不确定的,并且在那些情况下x和的值y可能会有所不同。

解决方案 5:

正如 Bob Stein 所说,分配的顺序很重要;请看下面这个非常有趣的案例:

L = L[1] = [42, None]

现在,包含什么L?您必须了解,最初是单个对象[42, None],它被分配给L;最后,L[1] = L执行类似的事情。因此,您创建了一些循环无限“列表”(这里的“列表”一词更类似于CONSLisp 中的一些列表,其中标量42CAR,列表本身为CDR)。

只需输入:

>>> L
[42, [...]]

然后通过输入来获得一些乐趣L[1],然后L[1][1],然后L[1][1][1]直到到达结尾......

结论

这个例子比其他答案中的例子更难理解,但另一方面,你可以更快地看到

L = L[1] = [42, None]

不同于

L[1] = L = [42, None]

因为如果先前没有定义,第二个将会引发异常,L而第一个始终有效。

解决方案 6:

x = somefunction()
y = somefunction()

somefunction将被调用两次而不是一次。

即使每次都返回相同的结果,如果返回结果需要一分钟,这也会很明显!或者如果它有副作用,例如要求用户输入密码。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3101  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1882  
  产品生命周期管理(PLM)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力至关重要。在实际的PLM项目推进过程中,单一的管理模式往往难以满足复杂多变的需求,混合管理模式应运而生。混合管理模式融合了多种管理理念与方法的优势,能够更好地应对PLM项目中的各种挑战。接下来,我们将深入探讨PLM项目中混合管理模式的...
plm流程是什么   6  
  项目风险的有效管理对于项目的成功至关重要。PLM(产品生命周期管理)系统作为一种强大的工具,在项目风险管理中发挥着关键作用。通过合理运用PLM系统的功能,能够准确识别、评估和应对项目中的各种风险,确保项目按计划推进,达成预期目标。PLM系统在项目风险管理中的角色定位PLM系统贯穿于产品从概念设计到退役的整个生命周期。在...
plm软件有哪些   5  
  虚拟团队协作在当今的项目运作中愈发重要,PLM(产品生命周期管理)系统作为强大的管理工具,能为虚拟团队协作提供多方面支持。通过一系列有效的沟通工具,PLM系统可以打破地理、时间等限制,提升团队协作效率,确保项目顺利推进。以下将详细介绍PLM系统支持虚拟团队协作的6个沟通工具。即时通讯工具即时通讯工具是PLM系统中促进团...
plm系统有什么功能和意义   6  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用