最近学习python定义一个函数遇到了一些坑整理如下:
python定义一个函数函数属于第一类对象,和整数、字符串一样可以赋值给变量也可以当作参数被其他函数直接调用、传递,也可以当作返回值
def的任务是创建函数对象,在全局命名空间函数名会指向该函数对象,也就是在程序中所调用的函数实际上是同一個函数在def可执行语句定义时,就将其属性(名字、默认参数列表)初始化完成了但是不会执行函数逻辑,只有调用时才会
我主要介紹我遇到的一个坑:
函数如果有默认参数,那么就会在def定义阶段开辟好这个全局空间由于函数无论多少次调用都是同一个对象,所以这個全局空间是共享的倘若该默认参数是可变类型(list或dict),在某次执行中被改变了那么下次调用函数,就不再是原来的默认参数了因為默认参数只在定义时被初始化,反复执行时不会见下代码:
所以,一般不采用可变类型作默认参数用下面的方法代替
但是,还没完经过我反复测试,我发现python定义一个函数对传入参数开辟空间的一个规律:为了节省空间python定义一个函数会对默认参数在定义阶段开辟一個空间,但是一旦有实参输入默认参数变量m的引用将发生变化,传参传的是引用所以m就会变为这个指向这个引用,如果是可变类型函数内发生的变化会改变其内容。
所以函数在反复调用时,m会指向的空间只有2种一个是默认值的空间,为可变类型时会因共用可能导致一些错误建议改为不可变类型(如None),在函数内部使用逻辑判断再使用可变类型;如果是实参则m会指向实参的引用,但是函数结束後m又会重新指向默认参数的引用。
PS. 这里func([2])和func([n])对应的id一样和python定义一个函数回收机制有关立即数[2]也会开辟内存,只是函数已返回由于该空間并非常量池,就会立即回收下次继续使用该内存,如:
但是下面这两个的id不一样是因为同时使用前一个开辟的并未回收!
一般我们編码不需要注意python定义一个函数开辟空间的这些底层细节,因为立即数一旦用完就会回收下次再使用内容相同的立即数,是重新开辟的所以我们可以站在顶层角度编码即可。