在不使用第三个变量的情况下交换2个变量的2个值; 蟒蛇

tod*_*dsm 2 python math portability function

所以,我的一个朋友问我的python编程是怎么来的; 我说我学到了很多,而且很顺利.然后我的朋友,一个数学势利者问我:

"你可以在不使用第三个变量作为临时占位符的情况下交换2个变量的值吗?"

Syl*_*oux 25

在Python中交换两个变量的规范方法是

a, b = b, a
Run Code Online (Sandbox Code Playgroud)

请注意,这不是有效的什么"类型" a或者b是(数字,字符串,元组对象,...).当然,如果两个变量都引用不同类型的值,它也会起作用.


与许多命令式语言一样,Python从右到左评估分配.从概念上讲,所有行为都表现如果元组是为表达式的右手部分构建的,然后解构为对左手部分执行操作.这已经比我在这里解释得更清楚了:https://stackoverflow.com/a/14836456/2363712

但实际细节依赖于实现.例如,要构建@undefined的注释不是下面的函数,CPython虚拟机有一个ROT_TWO操作码,可以交换堆栈中的两个顶级项,因此可以优化这种操作.有关详细说明,请参阅此前一个答案:https://stackoverflow.com/a/21047622/2363712

  • 当我们只交换2个变量时,不会创建元组,而是使用[ROT_TWO](https://docs.python.org/2/library/dis.html#opcode-ROT_TWO). (3认同)

小智 5

 x = x + y;  // x now becomes 15
 y = x - y;  // y becomes 10
 x = x - y;  // x becomes 5
Run Code Online (Sandbox Code Playgroud)

这是代码的主要片段 这就是你朋友的意思


tod*_*dsm -5

一个看似简单的问题。回想起来,大概是为了确定你是否进行数学思考而设计的。我想,这不是一个简单的问题,但也并非遥不可及。

研究表明,这是一个相当常见的问题,有很多好的坏的答案。我相信我已经找到了一个说明性的解决方案:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# MODULES


# VARIABLES
x = 20
y = 10


# FUNCTIONS
# Swap 2 vars: longhand method, the portable way:
def swapNosL(val1, val2):
    print("BEFOR: val1: %r,  val2: %r") % (val1, val2)
    val1 = val1 + val2
    val2 = val1 - val2
    val1 = val1 - val2
    print("AFTER: val1: %r,  val2: %r") % (val1, val2)
    return(val1, val2)


# Swap 2 vars: shorthand method, the non/less-portable way:
def swapNosC(val1, val2):
    print("BEFOR: val1: %r and val2: %r") % (val1, val2)
    val1, val2 = val2, val1
    print("AFTER: val1: %r and val2: %r") % (val1, val2)
    return(val1, val2)


# MAIN PROGRAM
print("")
print("The Problem:")
print("We need to swap 2 variables without using a 3rd.")
print("The values: 'x' is %r and 'y' is %r.") % (x, y)
print("")

(retVal1, retVal2) = swapNosC(x, y)
print("")
print("Now values: 'x' is %r and 'y' is %r.") % (retVal1, retVal2)

print"\n"
Run Code Online (Sandbox Code Playgroud)

虽然有一些不必要的重复,但逻辑还是很扎实的。至基线:

1)它适用于所有正数和负数;我还没有测试过浮动。

2) 相同的内存以一种方式或另一种方式使用;无论哪种方式都只使用 2 个变量。

3)可移植性是(或应该)始终是一个目标。研究表明,在编程语言消失而您需要移植到新语言的情况下,以数学方式处理此问题将提供更大的可移植性。

在“坏”示例中,此方法是特定于语言的,并且移植到某种语言(有一天)将需要不同的解决方案。我希望 Python 永远不会重蹈 COBOL 的覆辙,但未来是广阔的。

然而,在“好”示例中,数学在 C 语言中以类似的方式处理。事实上,研究还表明,大多数语言中数学的处理方式通常都是相同的。

因此,保持数学不变,仅协商语法修改是更可移植的方法。

在某些时候,我会向我的朋友承认,这对我来说是一个很好的学习机会。但暂时不行。我找到了答案,但由于研究作弊而失败。

TT

  • 你能解释一下为什么“左,右=右,左”被认为是“坏答案”吗?据我了解,问题是“面向Python”——那么为什么不使用语言习惯来解决问题呢? (6认同)
  • 但这只适用于数字变量,对吗? (3认同)
  • 您自己说过您想交换浮点数,但您的解决方案甚至无法正确执行此操作。例如,参数“0.0000001”和“1000000”会给出不正确的输出。我不太确定你为什么提到字符串;它绝对不适用于它们(它们没有定义减法运算符)。 (3认同)
  • 老实说,您发布的第一个方法是在 Python 中实现交换的一种**糟糕**的方式。它会在许多浮点值上默默地失败,并且对于非数字类型根本不起作用。 (2认同)
  • @todd_dsm 如果它只有一两行代码,并且在两种语言中都是有风险和次优的,那么我就不会那么担心可移植性。当我考虑可移植性时,我会想到“这些信号在 Windows 上能正常工作吗?”之类的问题。不是“如何将这个变量交换更改为 C,同时更改尽可能少的字符?” (2认同)
  • @todd_dsm 问题的背景?你的问题根本没有提到任何类型。它说“变量”。您的解决方案是限制问题的唯一方法。如果将任何类型的两个变量传递到第一个解决方案中,它将按预期工作。如果变量是整数,第二个函数将成功,对浮点数和某些具有自定义运算符的对象给出不正确的结果,并对所有其他对象抛出错误。它甚至在你奇怪的假设中不起作用。从技术上讲,它甚至在 C 中不起作用,因为在 C 中溢出在技术上是未定义的。 (2认同)