【问题标题】:Why do list operations in python operate outside of the function scope? [duplicate]为什么 python 中的列表操作在函数范围之外运行? [复制]
【发布时间】:2014-05-26 14:53:36
【问题描述】:

在下面的python代码中,变量number被传递给函数addone,并进行了本地复制操作。 number 的值保持不变。

def addone(num):
    num = num + 1
    print "function: added 1, now %d" % num

number = 5
print "Before:", number
addone(number)
print "After:", number

输出:

Before: 5
function: added 1, now 6
After: 5

但是,列表操作(如 pop、append 等)的行为似乎有所不同。这让我有些困惑。所有列表操作都在全球范围内操作吗?如果是这样,这背后有什么特别的原因吗?

def pop_first(stuff):
    popped = stuff.pop(0)
    print "function: '%s' was popped!" % popped

words = ["A", "list", "of", "words"]
print "Before:", words
pop_first(words)
print "After:", words

输出:

Before: ['A', 'list', 'of', 'words']
function: 'A' was popped!
After: ['list', 'of', 'words']

【问题讨论】:

  • 因为列表是可变的,但整数不是; num += 1 将不同的对象分配给 numstuff.pop 更改对象。

标签: python list scope


【解决方案1】:

简短的回答是因为列表是可变的,而整数是不可变的


你不能就地改变一个整数,所以我们称它为“不可变的”。考虑到这一点,像整数加法这样的事情不会修改原始对象,而是返回一个新值——所以你的原始变量将保持不变。因此,如果我们存储对整数的引用,只要我们没有更改其中任何一个,它们将只是同一个对象:

>>> foo = 1
>>> bar = foo
>>> foo is bar
True
>>> foo += 2
3
>>> foo
3
>>> bar
1
>>> foo is bar
False

另一方面,列表是“可变的”(可以修改相同的对象引用),并且像pop() 这样的操作会在原地改变list,从而改变原来的。这也意味着,如果您编辑对可变对象(例如 list)的引用,原始对象也会被更改:

>>> baz = [1, 2, 3, 4, 5]
>>> qux = baz
>>> qux is baz
True
>>> baz.pop()
5
>>> qux
[1, 2, 3, 4]
>>> baz
[1, 2, 3, 4]
>>> qux is baz
True

【讨论】:

    【解决方案2】:

    将对象传递给函数的工作方式与分配对象相同。所以,你看到的是和下面一样的效果:

    >>> words = ["A", "list", "of", "words"]
    >>> stuff = words
    >>> stuff.pop()
    'words'
    >>> words
    ['A', 'list', 'of']
    

    这是因为stuffwords同一个列表,而pop 更改了该列表。 int 是不可变的,这意味着它们不支持任何就地突变:每次更改其值时,它都会为您提供一个具有新值的 不同 int 对象。您可以使用is 运算符测试两个对象是相同还是不同的对象:

    >>> stuff is words
    True
    >>> a = 5
    >>> b = a
    >>> a is b
    True
    >>> b += 1
    >>> a is b
    False
    

    【讨论】:

      【解决方案3】:

      当您执行stuff.pop() 时,您修改了对象stuff。当您执行num = num + 1 时,您不会修改num,您只需创建一个新对象并将其分配给变量num。如果num 是一个列表,结果将完全相同:

      def addone(num):
          num = num + [1]
          print "function: added 1, now", num
      
      number = [5]
      print "Before:", number
      addone(number)
      print "After:", number
      
      
      # Before: [5]
      # function: added 1, now [5, 1]
      # After: [5]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-09
        • 2017-02-07
        • 2019-12-19
        • 1970-01-01
        • 1970-01-01
        • 2021-08-24
        • 1970-01-01
        • 2022-01-16
        相关资源
        最近更新 更多