3

所以我正在使用 python 3.3 中的列表,这是我的示例代码:

def change_to_z(lis):
    lis[3] = 'z'

def change_to_k(lis):
    lis[4] = 'k'


def split(lis):
    lis = lis[3:] + lis[:3]

totest = ['a', 'b', 'c', 'd', 'e', 'f']

change_to_z(totest)
print(totest)
change_to_k(totest)
print(totest)
split(totest)
print(totest)

和输出:

['a', 'b', 'c', 'z', 'e', 'f']
['a', 'b', 'c', 'z', 'k', 'f']
['a', 'b', 'c', 'z', 'k', 'f']

请注意,当我调用前两个函数时,我能够修改列表,而 totest 始终引用列表,即使它已更改。

但是,对于第三个函数,变量 totest 不再引用列表的最新修改版本。我的调试器告诉我,在“split”函数中,列表被翻转,但在函数之外,它没有被翻转。为什么变量名不再引用列表?

为什么会这样?什么运营商会发生这种情况?为什么有时变量名在函数中修改后仍然引用列表,但它与其他运算符的行为不同?

4

2 回答 2

1

您对功能有误scope

如果您真的想更改提供的列表,您可以尝试以下两种方法之一。

def split(lis):
    global lis
    lis = lis[3:] + lis[:3]

或更好

def split(lis):
    lis[:] = lis[3:] + lis[:3] # Credits go to drewk for pointing this out

当你在做

def split(lis):
    lis = lis[3:] + lis[:3]

在该split函数中,您正在创建一个与提供的列表具有相同标识符的本地列表。但是,这两个不会冲突,因为传递的列表是全局的。

如果您想四处玩耍并知道它们是否真的不同,请使用id()

lis = [1, 2, 3]
def split(lis):
    lis = lis[3:] + lis[:3]
    print id(lis)
split(lis)
print id(lis)

上述代码的输出

40785920
40785600

注意内存位置的不同

于 2013-11-05T04:47:12.033 回答
1

赋值lis是一个局部变量,不会更新列表。这在您的程序的python 导师可视化中很容易看到。

另外,请参阅此博客文章以清楚地解释正在发生的事情。这是一个简短的回顾:

  • 名称指的是值。
  • 许多名称可以引用一个值。
  • 名称的重新分配独立于其他名称。
  • 赋值从不复制数据。
  • 值的更改通过其所有名称可见。
  • Python 以不同的方式分配可变值和不可变值。
  • 引用可以不仅仅是名称。

在您的代码中,使用全局声明来查看它与默认本地分配的不同之处:

def split(lis):
    global lis

    lis = lis[3:] + lis[:3]
于 2013-11-05T04:48:41.560 回答