【问题标题】:Python 3 odd function behavior on list列表中的 Python 3 奇函数行为
【发布时间】:2013-11-05 04:43:05
【问题描述】:

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

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

【问题讨论】:

  • 在函数split中将lis = lis[3:] + lis[:3]更改为lis[:] = lis[3:] + lis[:3]

标签: python python-3.x scope


【解决方案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 函数中,您正在创建一个本地列表,其标识符与提供的列表的标识符相同。但是,这两个不会冲突,因为传递的列表是global

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

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

上述代码的输出

40785920
40785600

注意内存位置的不同

【讨论】:

    【解决方案2】:

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-06
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多