函数中的Python作用域



考虑以下代码:

>>> b = 3
>>> def change (b):
...     b = 2
... 
>>> change(b)
>>> print(b)
3

打印语句返回3这一事实并不让我感到困惑。问题是:这是因为作用域,还是因为函数采用的参数与外部b无关?

change内的bchange外的b的作用域不同。在函数的范围内,在传入变量之前调用什么并不重要——目前,它将被称为b。只要你不从change返回b并将其分配给你的"原始"b,第一个就不会改变。

def change(b):
    b = 2
    return b
change(b)
print(b) # 3
b = change(b)
print(b) # 2

您正在重新分配b。它不会更改参数。您可以在分配之前和之后使用id()函数对此进行测试。

范围答案对于您传递的对象类型是部分正确的。

查看此链接以获取有关python如何"通过值引用"的信息

http://stupidpythonideas.blogspot.com/2013/11/does-python-pass-by-value-or-by.html

下面是另一个链接,它解释了蟒蛇的本地->封闭->全局->内置范围解析,并提供了一些示例:

http://nbviewer.ipython.org/github/rasbt/python_reference/blob/master/not_so_obvious_python_stuff.ipynb#python_legb

FWIW,如果我们考虑可变对象,行为会略有不同:

>>> b = [3]
>>> def change(b):
...    b[0] = 2
...
>>> change(b)
>>> print(b)
[2]
>>>  

你问了一个相当棘手的问题,因为你在构建问题时使用的术语会让人们给你不同而奇怪的答案。

你有两个选择:

  1. 我们有范围问题
  2. 函数内的b与函数外的b无关

好吧,它们都是真的,它们真的只是说同一件事的两种方式。

暂时忘记术语,意识到之间没有任何区别

b = 3
def f(a):
    print(a)
f(b)

b = 3
def f(b):
    print(b)
f(b)

函数签名中的参数名称(函数的def行)是函数的本地名称,无论函数外部有什么名称。

现在,你可能注意到我回避了函数中的赋值问题。这是因为它很难快速解释,但对于仍处于学习Python早期阶段的人来说,它仍然是可以理解和难忘的(无意冒犯,你似乎是这样)。

以下是一些阅读资料,可以帮助您理解Python中的基本概念:

  • http://nedbatchelder.com/text/names.html
  • http://www.jeffknupp.com/blog/2013/02/14/drastically-improve-your-python-understanding-pythons-execution-model/

您需要查看全局变量。只需在代码和函数的开头添加global b,它就会起作用:

>>> global b
>>> b = 3
>>> def change():
...     global b
...     b = 2
... 
>>> b
3
>>> change()
>>> b
2
>>> 

您还需要从def change(b)中删除b参数,因为这会使b同时成为localglobal。您也可以return b:

>>> b = 3
>>> def change(b):
...    b = 2
...    return b
...
>>> b
3
>>> b = change(b)
>>> b
2

这是一个作用域问题。函数中的b是一个局部变量。globals()是一个包含所有全局变量的字典。

b=3
def change (a):
    globals()[a] = 2
print b
# 3
change("b")
print b
# 2

最新更新