默认参数的陷阱

默认参数的陷阱 : 默认参数实际上只有一个值
如果是可变数据类型,无论这个函数被调用多少次,
共用这个默认参数
a = []
b = []
a.append(1)
print(a,b)

a = []
b = a
a.append(1)
print(a,b)

变量是变量,值是值
变量的名字和有多少个值 没有对应关系
我们在看修改的时候 : 要看修改的是哪一个具体的值而不是变量

l = [] # 在定义函数之前定义了一个[]
def func():
l.append(1)
func()
func()
func()
func()

def func(l = []): # 在函数定义的时候 创建了一个[]
# 对于默认参数来说,[]只定义一次
l.append(1)

func()
func([]) # 又创建了一个新的空列表,传给func,代替l=[]这个默认参数
func()
func()

def func2(a = 0): # 在函数定义的时候,创建了一个值 0,只有一个0,a永远不消失
a += 1 # a = 0 + 1 = 1 局部变量 会随着这个函数的调用而消失
print(a)

func2()
func2()
func2()
func2()

l = []
l.append(1)
算法 : 超过4个值 把这个列表扩大一倍

函数 是 第一类对象的概念
函数名 可以赋值可以做参数做返回值容器类型中的一项(可以作为字典的key)
函数的内存地址() ==> 调用这个函数
函数的函数名会改变么 ??? 不会改变

闭包 : 缓存和装饰器
内部函数引用了外部函数的变量,内部函数就是一个闭包
def outer():
a = 1
# 先来计算/执行代码 获得要缓存的值
def inner():
'''引用一个外部函数的变量a'''
'''引用外部缓存的值'''
return inner # inner 函数的内存地址

inn = outer()
inn()
inn()


缓存 把一个值存储在内存里
如果一个值 在网络上存,那么你想拿到这个值需要联网 下载 (消耗时间)
如果一个值 要通过复杂的计算才能得出结果,那么每一次你想拿到这个值都要重新计算一次(消耗时间)

装饰器 本质就是一个闭包
一个函数写完之后就不能修改了,这个时候想在这个函数之前或者之后添加一些功能 就用装饰器
原文地址:https://www.cnblogs.com/F18866/p/9958020.html