Python局部变量被另一个方法更改

时间:2014-10-16 16:05:39

标签: python ruby arrays list

我想知道是否有任何python人员可以告诉我如何/为什么会发生以下情况:

# define a list and send it as an arg to another function
def foo():
    nums=[1,2,3]
    bar(nums)
    print(nums)

# Take the list as an arg and pop the last element off
def bar(numbrs):
    numbrs.pop()

# Call the first function
foo()

# The nums local variable has been modified
[1, 2]

作为一个rubyist,我发现foo函数中的本地定义的变量(nums)可以通过bar函数中执行的动作来改变,这真的很奇怪!这种纠缠是否正常?它有名字吗?

这两个函数甚至不使用相同的名称来引用列表。这非常奇特。我有点喜欢它。

3 个答案:

答案 0 :(得分:1)

行为与Ruby完全相同:

def foo()
  nums = [1,2,3]
  bar(nums)
  p(nums)
end

def bar(numbers)
  numbers.pop
end

foo()
# prints [1, 2]

DEMO

您无法更改局部变量的引用以引用其他变量。但是您可以调用原位更改状态的方法。 list.pop就是这种方法之一。 (与Ruby中的Array#pop相同)

答案 1 :(得分:1)

列表是一个对象,调用对象上的方法(如pop())会影响其状态。

更准确地说,让我们一起浏览您的代码,看看发生了什么:

def foo():
    nums=[1,2,3]  # create a list and give it a name. nums contains a reference to the list
    bar(nums)     # call the method bar, passing it the reference to that list
    print(nums)   # print the list.

好的,这很清楚。在酒吧里发生的事情是对你有用的:

# Take the list as an arg and pop the last element off
def bar(numbrs):  # method gets a value. In this case the value is a reference to a list
    numbrs.pop()  # call a method on that object

那么当你调用numbrs.pop()时会发生什么?据推测,在列表的定义中,您将找到方法定义:

def pop(self):

通过删除其中一个成员来修改自身对象的状态,并返回已删除的成员。

那种情况下的自我是什么?它是对列表的引用。具体来说,当你执行pop()操作时,它就是被称为numbrs的引用,这与你在创建它时存储为nums的引用相同。

我希望这会有所帮助 - 它有很多间接性,但是如果你按照参考文献进行操作,你会看到它的全部内容。

答案 2 :(得分:0)

这有点奇怪,我不确定这是否是问题的答案,但如果你运行这个:

def foo():
    nums=[1,2,3]
    print "foo"
    print locals()
    print globals()
    bar(nums)
    print "foo-after"
    print locals()
    print globals()
    print(nums)


def bar(numbrs):
    print "bar"
    print locals()
    print globals()
    numbrs.pop()
    print "bar-after"
    print locals()
    print globals()

foo()

输出:

>>> foo()
foo
{'nums': [1, 2, 3]}
{'bar': <function bar at 0x024759B0>, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, '__name__': '__main__', 'foo': <function foo at 0x024593B0>, '__doc__': None}
bar
{'numbrs': [1, 2, 3]}
{'bar': <function bar at 0x024759B0>, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, '__name__': '__main__', 'foo': <function foo at 0x024593B0>, '__doc__': None}
bar-after
{'numbrs': [1, 2]}
{'bar': <function bar at 0x024759B0>, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, '__name__': '__main__', 'foo': <function foo at 0x024593B0>, '__doc__': None}
foo-after
{'nums': [1, 2]}
{'bar': <function bar at 0x024759B0>, '__builtins__': <module '__builtin__' (built-in)>, '__package__': None, '__name__': '__main__', 'foo': <function foo at 0x024593B0>, '__doc__': None}
[1, 2]