基本概念:
1 程序由一个个代码组成,一个函数就代表一个任务或一个功能
2 函数是代码复用的通用机制
定义语法:
def 函数名([参数列表]):
函数体
结合循环语法使用
注:函数也是对象
形参和实参:
形参:定义函数时使用的,属于函数内部的参数
上图中,a,b为形参.1,2 实参. 形参用于定义,实参用于调用.
文档字符串:
由上图,100行代码处为文档字符串,用于对函数进行说明.
使用 help(one.__doc__) 语句对文档字符串进行调用.
返回值:
用法
return语句决定要返回的值 .没有规定则返回为None.
函数底层的内存分析:
先看代码
由上图,当一个函数被定义时,就创建了这样的一个对象,指向one这个函数,one里面就包含了这个对象的id,代码内容等,定义一次之后,可以反复调用这个函数,都是调用一个相同的对象.当把one赋值给c变量的时候,对象的内容就同时指向c和one两个函数,c和one有同样的对象.
变量的作用域(全局变量和局部变量):
先看代码:
代码中,第一个a为全局变量,从开始创建到代码结束都能使用,但b和第二个a为局部变量,只能在函数中使用,所以打印a时打印的是第一个a对应的对象的值.
底层内存调用过程:
a 对应值为4的对象,one对应定义的函数对象.a,和one都为一个栈,而b被定义的时候,会出现一个值为3的对象,但b被称为一个栈帧(帧只会出现一次,后续被销毁,后续使用时再出现再销毁.第二个a同理)
全局变量要在函数内部使用,必须先声明,看代码:
global声明全局变量 !!!
参数的传递 -- 传递可变对象
由图,列表a为可变对象,当传递对象为a时,m和a指向了同一个对象,所以id相等.所以当创建m这个栈帧时,m指向这个列表对象,并执行函数中语法往列表中增添了一个元素,即被指向的对象增添了一个元素,所以a打印出来是增添了一个元素的.
参数的传递 -- 传递不可变对象
因为传递对象不可变,不会像上面一样指向同一个对象,而会创建一个新的对象.代码如下:
结果如下:
对象的id发生了变化,创建了一个新的对象.
深拷贝和浅拷贝:
为了深入了解参数传递的底层原理,需要了解这个概念.
浅拷贝:
由图,浅拷贝只拷贝子对象的内容,不拷贝子对象的引用,而是一起指向同一个对象.
深拷贝:
由图,深拷贝拷贝的是一个家庭
上代码:
结果:
当b在自身增加元素的时候,a没有增加,是因为浅拷贝时b是自己拷贝出来的对象,与a无关,而在子对象增加元素的时候,浅拷贝是没有拷贝子对象的,是和a指向的同一个子对象,所以a中也会增加元素.
深拷贝:
结果:
深拷贝会把子对象和引用全部拷贝,增加元素时,只增加自身的子对象和引用,a不受影响.
lambda表达式:
lambda表达式用来声明匿名函数,代码实现如下:
结果:
其中,abc为此匿名函数的形参.
eval:
将字符串当成有效表达式并计算结果
字符串被运行了
递归函数:
自己调用自己
结果;
递归阶乘:
结果: 120
nonlocal:
用来声明外层的局部变量,代码:
结果如下:
当nonlocal声明b时,b不受外部函数的局部变量影响