列表上的Python 3奇函数行为

时间:2013-11-05 04:43:06

标签: python python-3.x scope

所以我正在使用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”中,列表被翻转,但在函数之外,它不会被翻转。为什么变量名不再引用列表?

为什么会这样?运营商做了什么呢?为什么有时变量名称在函数中被修改后仍然引用列表,但它与其他运算符的行为不一样?

2 个答案:

答案 0 :(得分: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

注意内存位置是如何不同的

答案 1 :(得分:1)

lis的分配是一个局部变量,并没有更新列表。这很容易在你的程序python tutor visualization中看到。

另外,请参阅this blog post以获得有关正在发生的事情的明确说明。这是一个简短的回顾:

  • 名称是指值。
  • 许多名称可以引用一个值。
  • 名称将独立于其他名称重新分配。
  • 作业永远不会复制数据。
  • 通过所有名称可以看到值的变化。
  • Python以不同方式分配可变和不可变的值。
  • 参考文献不仅仅是名称。

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

def split(lis):
    global lis

    lis = lis[3:] + lis[:3]