默认值的作用域
xyz是在函数里的局部作用域
这种和上面一种有何区别
没追加上去说明用的不是同一个东西
因为后面的foo[1]相当于同一种方式,指的是传入了一个
用到了缺省值和没用到缺省值的区别
有追加效果用的是同一个,没有就不是同一个
第一次传参,1.append 1打印 1.1
第二次无参数,使用缺省值1.append 1.1
第三次,根据上一次的,继续append 1.1.1
主要是引用类型的区别
首先理解缺省值是什么,
每个函数定义可以理解为函数对象的创建,因为一切皆对象,找个函数对象在内存中构建出来后,与你指定的标识符建立了关联,调用找个函数名就相当于调用这个函数
python是把缺省值放到这个对象的特殊属性上去
后面的标识符就是双下划线开头,双下划线结尾
这个属性就保存着这些缺省值
bar这个函数缺省值保存的是1
它为了记住顺序,用了sequence序列,既然是缺省值,就没必要修改,所以用了元组,
1.不允许你改缺省值,
2.不允许你改变顺序
这就是使用元组的目的
foo函数跟第一次一样,现在默认来看是定义一个参数,有缺省值,这个缺省值是一个列表,这个列表被放到了缺省值当中,这个元组本身不可改变,但是这个元组的第一个元素列表可以改
分析一下foo函数
xyz拿到了[1]对象,追加了一个1
简单赋值,但是xyz是赋值的列表出来,是引用类型(本来是简单类型和复杂类型,后面可以改成非引用类型,和引用类型)
引用类型赋值传来传去,赋值的是引用地址,别人赋值后的操作,修改的是同一个对象
bar是简单的非引用类型,传过去是值本身,所以修改改的是这个值
函数也是对象,所以函数上也会有个特殊的属性,它会将函数定义的所有缺省值保存下来,默认这个缺省值使用的是__defaultes__特殊属性,以元组的方式保存函数的缺省值
函数的定义只做了一次
函数调用,你想做几次就几次
这样每次返回的xyz就改变了是有意义的
函数大多数是x不同,得出不同的结果,可以复用
一次定义,可以反复调用,应该一套定义,解决很多的问题
可变位置参数后面是keyword-only,关键字参数
但是keyword-only的缺省值就没显示出来
写空元组要小心,光写一个数字是代表优先级,要加逗号
函数定义好这个内存地址跟函数名foo关联起来,这个函数对象从头到尾都没变过
xyz的变化是对列表中的元素进行变化,元组记录的列表地址没变,并不是元组变化,而是元组里的列表变化
缺省值一旦定义好就不动了,因为定义只做一次
引用类型一定要注意
kwdefaultes是字典保存所有keyword-only参数的默认值
默认值相当于给了哪个变量,变量相当于形参,所以默认值的作用域相当于给形参用,在这个形参没有对应的实参进来后,这个时候就找找有没有缺省值,补齐,如果补不齐就报错了
默认值其实当形参用,形参可以当函数的局部变量来看,缺省值往往是函数定义部分,属于函数对象本身,是函数一个特殊属性,defaults,kwdefaults
缺省值是放在defaults,kwdefaults里的,生命周期跟函数有关,但是局部变量是在每一次调用的时候,用一下就没了
所以缺省值有所谓自己的作用域,要看你说的是什么,如果缺省值给形参,形参作用域在函数内部,局部变量
defaults是函数对象本身的特殊属性,是放在函数对象的,函数对象是跟函数定义相关
一定要记住
使用缺省值有好有坏
第一句等价xyz = foo.defaults
第二句等价在内存额外再开辟一个内存空间 x={】,一个新的空列表再给了xyz
用这种方式就可以避免使用同一个缺省值带来的追加效果
查看下半部分调用
重新拷贝,所有变化跟原有无关,原有传的参数爱谁谁,这个副本操作是不会影响原来的对象
潜拷贝只是原来的一个副本
如果传一个none,就做一个列表,再列表里追加1
如果是10就在10的基础上追加1如过没有就造空列表,有就在基础之上添加
如果xyz是none就给一个空列表,然后+1
如果有值,就在原有的添加,10,1
会继续追加
缺省值一般不会写死给一个列表,往往都是加none
在标准库经常这么操作,如果不是none就继续操作,是none就创建空列表
可以嵌套使用
第一次是none,用缺省值,内部创建一个引用类型[],然后return回来拿到知道再当做参数传入,+1
通过传入none来灵活判断 到底是外界传入还是用缺省值,缺省值往往会做一些动作,比如创建一个新列表
第一种使用影子拷贝的方式,一般来讲相当于修改副本,原有的不做任何修改
通过一个缺省值来灵活判断,查看用户是否传入值,如果传入就用传入的,没有传入就用缺省值
这是一种惯例的方法