简体   繁体   English

Python指针歧义

[英]Python Pointer Ambiguity

Say I have a function foo that takes a list baz, and in foo I wanted to clear baz like so: 假设我有一个带列表baz的函数foo,在foo中,我想像这样清除baz:

baz = []
foo(baz)

foo(baz):
    baz = []

Now, this code does not do what I would want it to do, because it creates a new local list called baz. 现在,此代码无法执行我想要的操作,因为它创建了一个称为baz的新本地列表。 I know that there are other ways of doing this, but I would like to know Python resolves ambiguities like this where the statement 我知道还有其他方法可以执行此操作,但是我想知道Python解决了此类歧义,其中语句

 baz = []

could be interpreted as telling Python to point the outer scope baz variable at a new empty chunk of memory or to create a new pointer pointing to an empty chunk of memory. 可以解释为告诉Python将外部作用域baz变量指向一个新的空内存块,或创建一个指向空内存块的新指针。

EDIT 编辑

Please be aware that I am not asking how to clear a list. 请注意,我不是在问如何清除列表。 I am asking about the behavior of the Python interpreter. 我在问Python解释器的行为。 Please read the question clearly before downvoting. 拒绝投票之前,请先清楚阅读问题。

Python will only treat variable assignment as assigning to a variable from an outer scope if you explicitly tell it to with the global or nonlocal keywords. 如果您使用globalnonlocal关键字明确地将变量赋值给Python,Python只会将其视为从外部作用域分配给变量。 global is for global variables, and nonlocal is a Python 3-exclusive keyword for closure variables: global表示全局变量, nonlocal表示闭包变量的Python 3专有关键字:

x = 1
def change_x():
    global x
    x = 2
def dont_change_x():
    # no global
    x = 3

change_x()
print(x)  # prints 2

dont_change_x()
print(x)  # still prints 2

Otherwise, it will always interpret assignment as assigning to a local variable. 否则,它将始终将分配解释为分配给局部变量。

If you intend to clear the items in your list, you would not need to reassign the current name to a new list, just clear the old one by slicing : 如果您打算清除列表中的项目,则无需将当前名称重新分配给新列表,只需通过切片将旧名称清除:

foo(baz):
    baz[:] = [] # clears out list baz

baz[:] is a way of indexing all the items in your list and assigning them a new value baz[:]是索引列表中所有项目并为其分配新值的一种方法

Update : 更新

If you use the same in an assignment to a new list, the interpreter simply reassigns that name to a new list object: 如果在分配给新列表的操作中使用了相同的名称,则解释器会将该名称重新分配给新的list对象:

>>> baz = []
>>> id(baz)
14832064
>>> baz = []
>>> id(baz)
14834304

Except you use slicing to refactor the old list, the name baz will no longer be a reference to the old list. 除了使用切片来重构列表以外,名称baz将不再是对old列表的引用。

Take a look at this post to understand python way of passing parameters by assignment . 看一下这篇文章,了解python 通过赋值传递参数的方式。

What is happening is that you are redefining the variable baz to another list, so it doesn't have the reference to the outer baz anymore. 发生的事情是您将变量baz重新定义为另一个列表,因此它不再具有对外部baz的引用。 You need to manipulate the elements in the list directly. 您需要直接操作列表中的元素。

For example, if you're adding an element to baz, the outer list will get the changes: 例如,如果您要向baz添加元素,则外部列表将获得更改:

def foo(baz):
    baz.append('baz')

But by doing this: 但是通过这样做:

def foo(baz):
    baz = []

You assign a new list to baz and the reference to your outer baz is now broken. 您为baz分配了一个新列表,对外部baz的引用现在已断开。

In your case, you have 2 options to clear the list: 对于您的情况,您有2个选项可以清除列表:

del baz[:]
baz[:] = []

Use slicing: 使用切片:

>>> def foo(baz):
...     baz[:] = []
...
>>> baz = [1, 2]
>>> foo(baz)
>>> baz
[]

The my_list[:] tells Python to replace all of the elements in my_list with the content on the right side of the assignment statement, referring to the same my_list object. my_list[:]告诉Python来代替所有的元素my_list与赋值语句的右侧的内容,指的是同一my_list对象。

If you want to clear the list, use .clear() instead of creating a new list: 如果要清除列表,请使用.clear()而不是创建新列表:

def foo(baz):
    baz.clear()

Side note: To access the outer baz in your foo() you can to use global keyword. 旁注:要访问foo()的外部baz ,可以使用global关键字。 However in that case there will be no ambiguity, as python will force you to rename the argument by throwing SyntaxError. 但是在那种情况下,不会有任何歧义,因为python会通过抛出SyntaxError迫使您重命名该参数。

def foo(baz2):
    global baz
    baz = []

Plase note that usage of global is discouraged. 请注意,不建议使用global

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM