如果函数没有副作用并以确定的方式返回一个单例(给定它的输入),它会产生相同的。
例如:
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)
因为在那种情况下x 和y 是同一个对象,所以执行x.append(42) 之类的操作意味着x 和y 都持有对现在有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 的值可能会有所不同。