链式赋值如何进行?

2025-01-17 09:23:00
admin
原创
94
摘要:问题描述:引用某件事:>>> 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大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3018  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1880  
  PLM(产品生命周期管理)系统在企业产品研发、生产与管理过程中发挥着至关重要的作用。它能够整合产品全生命周期中的各类数据与流程,提升企业的协同效率、降低成本并加速产品上市。然而,不同企业由于业务模式、产品特性以及管理理念的差异,对PLM系统有着个性化的需求。如何实现这些个性化需求,成为企业在实施PLM系统定制开发时面临...
免费plm软件   0  
  在企业的发展进程中,跨地域协同工作变得愈发普遍和重要。不同地区的团队需要紧密合作,以实现资源共享、提高效率和创新能力。而产品生命周期管理(PLM)系统在这一过程中发挥着关键作用,尤其是其分布式架构,为跨地域协同提供了强大的支持。PLM系统概述PLM系统是一种用于管理产品从概念设计到退役全生命周期过程中所有数据和流程的软...
免费plm管理软件   0  
  在企业项目管理中,资源平衡是确保项目顺利推进、提高效率与效益的关键环节。产品生命周期管理(PLM)系统作为整合产品全生命周期信息与流程的重要工具,为实现资源平衡提供了强大的支持。通过合理运用PLM系统,企业能够优化资源分配、提升协同效率,从而在激烈的市场竞争中占据优势。接下来,我们将深入探讨如何借助PLM系统实现资源平...
plm系统   0  
热门文章
项目管理软件有哪些?
曾咪二维码

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

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

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用