什么是作用域?
可以指程序设计概念,通常相对于一个完整的程序来说,从中所用到的变量或名称并不全程有效、可用的。为什么需要作用域?因为作用域限定这个变量或名称的可用性范围
# 首先将10赋值给num
num = 10
def ganyu(): # 定义一个函数,输出num
print(num)
ganyu() # 调用ganyu,打印num的值
# 那么如果这个时候,在函数内部将外部的num进行更改,则会报错,需要赋值前引用局部变量“num”
def ganyu1():
num += 20 #UnboundLocalError: local variable 'num' referenced before assignment
print(num)
ganyu1()
所以,在函数内可以读取函数外部的变量而在函数内部不能直接更改函数外的变量
# 如果在函数内部定义一个变量
def ganyu2():
a=100
print(num)
# print(a)# 可见在外部调用也会报错,因为a属于函数的局部变量,无法读取
局部变量&全局变量
-
函数内定义的变量就是局部变量,指的是只在函数内生效,出了函数无法正常使用
-
而在函数外定义的变量则称为全局变量,定义的函数可以获取,但是无法更改值大小,如果在函数内也可以使用global关键字定义全局变量
-
同样的,也可以使用global引用全局变量
# 如果在函数内部使用global关键字定义的变量就是全局变量
def ganyu4():
global numb
numb = 100
ganyu4()
print(numb)
# 使用global引用全局变量
def ganyu4():
global num
num += 20
return num
print(ganyu4())
但是并不是所有的变量都不能更改,变量分为两种
-
可变数据类型
-
不可变数据类型
可变数据类型:在函数外定义的变量,在函数内可以使用,修改,更新
不可变数据类型:在函数外定义的变量,在函数内只能访问,不能使用其他操作
'''
可变数据类型
布尔类型 bool
浮点数 float
列表 list
字典 dict
'''
varlist={'a':'a','b':'b'}# 定义一个字典或者列表,注意:元组不可变
def ganyu3():
varlist['a']='aa'
print(varlist)
ganyu3()
'''
不可变数据类型
字符串 str
整形 int
元组 tuple
'''
globals和locals
# globals()获取全局数据
# locals()获取当前作用域的数据
# 一、
'''
在函数外使用函数
globals()
locals()
'''
print(globals())
# {'__name__': '__main__', '__doc__':
# __name__代表的是当前的魔术方法,是我们当前脚本的一个名字
print(locals())
# 为什么两个函数打印的结果完全一样?
# 由于当前区域就是全局本区域
# 如果在函数内部使用globals()和locals()
# 首先定义一个全局变量
num=100
# 定义一个局部变量
def ganyu():
number=100
print(globals())#依旧返回全局变量:{'__name__': '__main__', '__doc__': '\n在函数外使用函数\nglobals()\nlocals()\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000018E2B7618B0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '------------', '__cached__': None, 'num': 100, 'ganyu': <function ganyu at 0x0000018E2B8A79D0>}
print(locals())#返回局部变量:{'number': 100}
ganyu()
print(__doc__)
# 不光变量有作用域,函数也有作用域
def ganyu():
print("my name is ganyu")
ganyu()
# 如果在函数内再定义一个函数
def ganyu0():
print("my name is ganyu0")
# 在函数内定义的函数也称局部函数
def ganyu1():
print("my name is ganyu1")
ganyu0()# 同样可以调用ganyu0
# ganyu1() 但是无法在全局里调用ganyu1
# 而且在函数作用域内定义的变量,在另一个作用域内也无法使用
def ganyu2():
name=100
print("my name is ganyu2")
# 在函数内定义的函数也称局部函数
def ganyu1():
# name+=100 无法更改上一个作用域定义的变量,但是可以获取
print("my name is ganyu1")
ganyu0()# 同样可以调用ganyu0
# nonlocal
# 变量和函数都有作用域
# 在内函数中如何使用上一层函数中的局部变量?
# 首先定义一个函数
def ganyu():
num=100# 将100赋值给num,为外函数的局部变量
# 内函数,局部函数,在函数的内部定义的函数
def ganyu0():
# num += 1 可以调用,但是无法修改
print(num)
ganyu0()
ganyu()
# nonlocal函数的使用
def ganyu1():
num=100
def ganyu2():
# nonlocal 关键字在局部函数中使用,就可以把外函数的局部变量使内函数也可进行修改、更新
nonlocal num
num += 1
print(num)
ganyu2()
ganyu1()
'''
在内函数中如果想使用外函数的变量,那么需要使用nonlocal关键字引用
'''
# 关于函数的文档
print(globals())
# {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001E8BE6508B0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '-----------', '__cached__': None, 'ganyu': <function ganyu at 0x000001E8BE6361F0>, 'ganyu1': <function ganyu1 at 0x000001E8BE7979D0>}
'''
'__name__':'__main__'==>当前脚本如果作为主程序,那么对应的值是__main__,什么是主程序,如果写完一个程序,直接使用py运行,如果是当做一个模块,在另外一个脚本中,引用去使用,那么值就是当前文件的名字
'__doc__': None==>当前脚本的文档说明,在当前脚本中的第一个三引号注释就是当前脚本的文档说明
'__package__': None
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001E8BE6508B0>
'__spec__': None
'__annotations__': {}
'__builtins__': <module 'builtins' (built-in)>
'__file__': '-----------'==>当前脚本的完整路径
'__cached__': None
'ganyu': <function ganyu at 0x000001E8BE6361F0>
'ganyu1': <function ganyu1 at 0x000001E8BE7979D0>
'''