变量赋值
a = 5 #相当于void *a = &Number(5),创建了一个Number(5)对象
#第一次给a赋值,创建变量a
#不需要声明a的数据类型,python眼中,所有的变量都是void*指针,类型说的是指向的对象。
a = 10 #第二次赋值,就是普通意义的赋值
#相当于a = &Number(10),创建了Number(10)对象
#最终的效果就是a指向了一个全新的对象。
a = [1,2,3] #变量可以指向任意类型的对象,void*嘛。
#对象是[1,2,3]是List类型
del a #删除变量a对对象的引用,a不再指向任何对象,a不可再使用。
a = b = c = 1 #多变量赋值
a, b, c = 1, 2, "john" #多变量赋值,类似lua
变量作用域
全局作用域:在函数体外定义的变量,程序范围内可访问。
局部作用域:在函数体内定义的变量,只在函数体内可访问。
类似C++的全局变量,局部变量。
名字查找规则和C++类似,优先查找当前所在最小范围作用域,比如函数体内,优先查找函数内的局部作用域,如果没找到,再从全局作用域找。
var = 1; #定义了一个全局变量
def fuck():
var = 2; #定义了一个局部变量,
#在局部作用中,覆盖了全局变量var的名字,通过var只会查找到局部变量。
global var #显式声明使用全局变量var,接下来的var指的全部是全局变量。
var = 2; #全局变量var的值改为1。
nonlocal var #显式声明使用外层作用域的变量var,不包括全局作用域
#这里是错误的,因为外层作用域已经是全局作用域。
def shit():
nonlocal var #正确,使用fuck函数作用域的var变量。
pass
globals()、locals()内置函数
globals(),返回当前作用域内可访问的全局名字。
locals(),返回当前作用域内的名字。
gvar = 1
def fuck():
lvar = 1
print(globals()) # {"gvar":1}
print(locals()) # {"lvar":1}
print(globals()) # {"gvar":1}
print(locals()) # {}
对象生命周期
python和lua一样,垃圾自动回收。
使用引用计数来跟踪回收垃圾。
引用计数器记录着每个对象的当前引用数量,数量=0时,它将被垃圾回收,回收不是”立即”的, 由解释器在适当的时机,将垃圾对象占用的内存空间回收。
原理类似于C++的智能指针shared_ptr。
a = 40 # 创建对象<40>,对象<40>引用计数=1
b = a # 对象<40>引用计数+1,因为变量b也引用了对象
c = [b] # 对象<40>引用计数+1
del a # 对象<40>引用计数-1,解除了a对对象<40>的引用
b = 100 # 对象<40>引用计数-1,对象<100>引用计数=1
c[0] = -1 # 对象<40>引用计数-1,对象<40>引用计数=0,下一轮垃圾回收,对象将被回收。