【问题标题】:pythonic swap x,y = y,x doesn't work?pythonic 交换 x,y = y,x 不起作用?
【发布时间】:2016-03-30 18:20:14
【问题描述】:

我刚刚意识到 pythonic 交换并不总是有效。

def swap(x,y):
    x,y = y,x

a = 1
b = 2
swap(a,b)

print b

结果:2

为什么在这种情况下交换变量的 Pythonic 方式不起作用?我需要临时变量吗?

【问题讨论】:

  • 您到底期望什么? print b 确实会打印 2 因为 b=2
  • 大多数 python 对象是不可变的......所以你实际上并没有交换......你只是在函数内部创建了一个局部 x,y 变量,这样x=y,y=x 但它只适用于你在方法范围内
  • @JoranBeasley 这与可变性无关。如果您为此函数传入列表,行为将是相同的。
  • x[:] = x[::-1] @timgeb ...但是我知道你在说什么
  • @hongjooy,你的问题得到解答了吗?

标签: python swap


【解决方案1】:

在函数定义的第一行

def swap(x,y):

xy 是所谓的形式参数。 当你打电话时

swap(a, b)

您将ab 作为实际参数传递。

现在发生的是 Python 为您传入的实际参数创建新名称。

在函数体内x 现在是内存中整数对象的新名称,它也具有名称ay 现在是内存中整数对象的新名称,其名称也为 b。这就是为什么 Python 既不是按值调用也不是按引用调用,而是最好将其描述为 call-by-assignment 的原因。

与流行的看法相反,调用函数和赋值对于可变参数和不可变参数的工作方式完全相同。您将看到与可变值相同的行为:

>>> def swap(x,y):
...     x,y = y,x
... 
>>> a = [1]
>>> b = [2]
>>> swap(a,b)
>>> a
[1]
>>> b
[2]

因此,一旦您了解了 Python 中赋值的工作原理,您也将了解函数调用的工作原理。

举个例子:如果你没有写一个函数,你的代码就相当于:

a = 1
b = 2
x = a
y = b
x,y = y,x
del x
del y

在第 3 行中,您正在为整数对象创建一个新名称 x,该名称也称为 a。第 4 行遵循相同的逻辑。

在第 5 行中,您正在创建元组 (y, x),右侧的值为 (2, 1),然后将其解包,即名称 x重新分配到该值2 并将名称 y 重新分配给值 1:

>>> a = 1
>>> b = 2
>>> x = a
>>> y = b
>>> x,y = y,x
>>> x
2
>>> y
1

这里要注意的重要一点是 ab 从未停止分别作为值 1 和 2 的名称:

>>> a
1
>>> b
2

最后两行只是取消绑定名称xy,这大致相当于退出函数作用域后在函数中发生的情况。请注意,在取消绑定 xy 后,名称 ab 仍然绑定。

>>> a
1
>>> b
2

【讨论】:

    【解决方案2】:

    您从未返回并分配结果。否则,正如 Joran 所说,您只是在函数中创建局部变量。例如:

    def swap(a, b):
        print "swap called"
        return (b,a)
    
    a = 1
    b = 2
    
    print a,b
    a,b = swap(a,b)
    print a,b
    

    结果显示如下:

    1 2 交换调用 2 1

    【讨论】:

    • 也就是说python是传值的。
    • @JamesBuck 不,python 是传递赋值。
    • @timgeb 它的传递方式与 C 和 Java 相同。更准确地描述为 pass-by-reference-value。
    • @JamesBuck 请注意this,没有人在python中这样称呼它,这是有充分理由的。
    【解决方案3】:

    你需要返回一些东西;交换的变量

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-20
      相关资源
      最近更新 更多