python基础三_02_函数的作用域
导读:
本文主要记录自己学习python3基础中函数的作用域(全局变量与局部变量等)要点知识和例子;仅供自己梳理。搞清楚函数的作用域很关键,这是理解闭包,装饰器等的前提。
一、引子
def func():
x = 1
print(x)
func()
print(x)
1.分析:如上,为何在函数外部打印x的值没有结果呢?
这是因为x是func函数内部的变量。
随着func的生命周期当函数调用完成,没有变量指向1的内存地址后,python的垃圾回收机制就会回收1的内存
所以就出现了:NameError: name 'x' is not defined,这个很容易理解
x = 6
def func():
x = 1
print(x)
func()
print(x)
2.分析:现在为何可以在func函数外部打印x的值呢?
这是因为我们定义了全局变量,x = 6
二、函数的作用域
1.变量起作用的范围
- L local局部作用域,本地作用域
- E enclosing嵌套作用域
- G global全局作用域
- B built-in内建作用域
for,if,while返些流程控制不会形成自己的作用域
import sys
# 得到所有该模块的方法 内建作用域
print(dir(sys))
# 全局
name = 'while'
def outer():
name = 'for'# 嵌套作用域
def inner():
# 本地作用域
name = 'json'
age = 18
print(name)
print(age)
inner()
outer()
初学者可能看不太懂上面的程序,我们来分析一下:
name = 'while'
def outer():
name = 'for'
def inner():
name = 'json'
age = 18
print(name)
print(age)
outer()
2.分析:执行后为什么啥结果都没有呢?
这是因为我们只调用了outer函数,但真正想调用的inner函数没有调用。
有的人可能一眼就看出来了,但是对初学者来说可能有点勉强。
好比下面的程序,你觉得它会有输出内容吗?
name = 'for'
def inner():
name = 'json'
age = 18
print(name)
print(age)
这个程序当然不会输出任何东西,原因是它只定义了name和inner,但是并没有调用。
仔细看它是不是就是outer函数里面的东西呢?
我们只要调用一下inner函数就可以了。
name = 'for'
def inner():
name = 'json'
age = 18
print(name)
print(age)
inner()
3.变量起作用的范围
现在我们肯定都能看懂这个程序
# 全局作用域,全局变量
name = 'while'
# 定义外层函数
def outer():
# 嵌套作用域,嵌套变量
name = 'for'
# 定义内嵌函数
def inner():
# 本地作用域,局部变量
name = 'json'
age = 18
print(name)
print(age)
inner()
outer()
如果本地作用域没有定义name变量呢?
# 全局作用域,全局变量
name = 'while'
# 定义外层函数
def outer():
# 嵌套作用域,嵌套变量
name = 'for'
# 定义内嵌函数
def inner():
# 本地作用域,局部变量
# name = 'json'
age = 18
print(name)
print(age)
inner()
outer()
分析:因为本地作用域中没有定义name,所以程序执行时会向上一层找,也就是嵌套作用域:name = 'for'
如果嵌套作用域也没有定义name变量呢?
# 全局作用域,全局变量
name = 'while'
def outer():
# 嵌套作用域,嵌套变量
# name = 'for'
def inner():
# 本地作用域,局部变量
# name = 'json'
age = 18
print(name)
print(age)
inner()
outer()
分析:相应的如果嵌套作用域还没有定义name变量,那么就再向上一层,直到全局作用域,name = 'while'
当然,如果全局作用域还没有变量的定义,就会报错
3.同样,那我们现在能访问(即:打印)变量age吗?
name = 'while'
def outer():
# 嵌套作用域,嵌套变量
# name = 'for'
def inner():
# 本地作用域,局部变量
# name = 'json'
age = 18
print(name)
print(age)
inner()
outer()
#
print(age)
分析:
当然不能,因为age是inner函数的变量,是局部变量,它和inner函数一样有生命周期和作用范围,它不在全局。
函数内部定义的数据函数外部无法访问,即函数具有封闭性,函数可以封装代码即具有包裹性,所以函数可以构成闭包。闭包我们下次聊。
三、global
什么叫局部变量,全局变量?
局部变量是指在程序中只在特定过程戒函数中可以访问的变量,函数内部定义的变量。
如果一个变量,既能在一个函数中使用,也能在其他的函数中使用,返样的变量就是全局变量
总结:不同的函数,可以定义相同的名字的局部变量,但是各用各的不会产生影响。
局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储,这就是它的作用。
1.修改全局变量
现在打印出来的肯定是json,我现在想在本地作用域中,越级直接修改你的全局变量,怎么搞?关键字global可以实现
name = 'while'
print(name)
def outer():
# 嵌套作用域,嵌套变量
name = 'for'
def inner():
# 本地作用域,局部变量
# global声明一般在最前面,修改全局变量name
global name
name = 'json'
age = 18
print(name)
print(age)
inner()
outer()
print(name) #这里本应该打印出的是while
2.那如果我只想修改嵌套变量呢?
nonlocal声明修改嵌套变量name
name = 'while'
def outer():
# 嵌套作用域,嵌套变量
name = 'for'
print(name)
def inner():
# 本地作用域,局部变量
# nonlocal声明修改嵌套变量name
nonlocal name
name = 'json'
age = 18
print(name)
print(age)
inner()
print(name)
outer()
3.修改可变数据类型没有必要声明global
在上面的例子中,字符串属于不可修改的所以需要用global声明。但如果是可修改的数据类型,如:list,set,dict在修改时没有必要声明global。
c = [1,2,3]
d = {}
e = set()
def test():
c.append('5')
d.update({'name':'ydxq'})
e.add(1)
test()
print(c,d,e)