为什么有的变量是局部变量,有的变量就是全局变量?这是因为变量的命名背后都有一个命名空间,在局部空间的就是局部变量,在全局空间的就是全局变量
命名空间
什么是命名空间?就是变量名的集合,可以看成一个字典,一个大字典里面可以包含小字典,大字典的空间对小字典来说就是全局的。不同字典之间的键名相同并不影响,这就是命名空间中变量名具有各自的独立性。
内置命名空间__builtins__
所有的内置函数与内置常量都在内置builtins中, 可以通过__builtins__.__dict__字典访问
print(max)
print(__builtins__.__dict__['max'])
全局空间-globals
通过globals()
可以获得全局所有变量
def myfun():
pass
print(myfun)
class A:
pass
print(A)
# 输出
# <class '__main__.A'>
# 全局变量可以使用globals()获得
print(globals()['myfun'])
print(globals()['A'])
模块命名空间
如果A位于一个模块中,命名空间就是模块名, 当前模块的名称是__main__
def func():
pass
print(func)
from sys import getsizeof
print(sys.getsizeof)
类命名空间
类的所有属性都是通过类名.属性名访问
class A:
a = 10
def show_a(self):
print(self.a)
print(A.a)
# 相当于
print(A.__dict__['a'])
A.show_a(A())
# 相当于
A.__dict__['show_a'](A())
函数局部空间-locals
局部变量可以通过locals()
获得
def myfun():
func_name = "my_fun"
var = 100
options = {"db": "mysql"}
print(locals())
def inner_func():
nonlocal options
func_name = "inner_func"
var = 1000
options['db_url'] = "127.0.0.1:3306"
print(locals())
print(locals())
return inner_func
inner_func = myfun()
inner_func()
命名空间的寿命期
寿命期就是对象存活时间
最长的就是内置命名空间__builtins__
,从解释器启动开始生效,直到解释器关闭
然后是模块空间,从加载一直到解释器关闭
然后是类,从创建一直到销毁
最后是函数,调用时创建,调用完毕销毁,因此不能直接用函数名.函数名来访问嵌套函数
# 可以通过del语句删除变量、函数、类
import sys
a = 100
print(globals().get("a"), None)
del a
print(globals().get("a"), None)
class A:
a = 100
b = 10
def showme(self):
print(self.__class__)
# 实例销毁时执行__del__方法
def __del__(self):
print("实例已经销毁了")
a = A()
print(a.__class__)
del A
print(a.__class__)
print(sys.getrefcount(a.__class__))
del a
# 函数定义时内部变量并没有创建
# 函数调用后会销毁其内部所有变量
def myfun():
def inner_func():
pass
# 错误的变量引用方式
print(myfun.inner_func)
变量作用域
变量作用域是什么呢?
变量作用域是指变量、函数、对象等在程序中可被访问的范围.
命名空间解决了不同变量作用域间命名冲突的问题
变量作用域搜索顺序:
- 最先搜索的最内部作用域包含局部名称(L)
- 从最近的封闭作用域开始搜索的任何封闭函数的范围包含非局部名称,也包括非全局名称(E)
- 倒数第二个作用域包含当前模块的全局名称(G)
- 最外面的范围(最后搜索)是包含内置名称的命名空间(B)
a = 10
class A:
a = 10
def show_a(self):
print(a)
a = A()
a.show_a()
def func():
a = 100
A().show_a()
讨论区