函数的参数
-
实参(实际参数),实参可以传递任意类型的对象,如图
-
调用函数时,解析器是不会检查实参的类型
-
常见问题:TypeError: can only concatenate str (not “int”) to str
-
重新给形参赋值不会影响其他变量, 如图
-
形参,形式参数
-
如图所示,当a是列表时,尝试修改列表中的元素,如果现在的形参执行的是一个对象,当我们通过形参去修改对象时,会影响到所有指向该对象的变量
-
如图,a和c同时指向的是同一个对象,id值一样
-
当用copy( ) 或者 切片 时,a和c指向的时不同对象,如图
不定长参数
-
处理位置参数,在定义函数时,可以在形参前面加上一个*,由此这个形参就可以获取到所有的实参,它将获取到实参放到一个元组当中,*a会接受所有位置实参,并且会统一保存在一个元组内,如图实例
- *args为固定写法,流程为:定义一个变量,保存结果,遍历元组,将元组中的数进行相加, 如图一一解释
- 定义一个函数,求任意个数的和,如图
- 常见问题:TypeError: s() takes 2 positional arguments but 3 were given, 当s(13,56,78) 多输入一个实参时,就会报以上????♂️
- 带*号的形参只能有一个,否则会出现错误如 SyntaxError: invalid syntax, 如图用正规args写法写一个函数为求和,加入遍历列表,如下
- 举一反三,多个元素,如图
- 常见错误:TypeError: fn2() missing 1 required keyword-only argument: ‘c’ , 类型错误,函数2少一个关键字c,如图
- 更改为:fn2(4,2,5,6,1,c=7), 得出正确结果为
- 常见错误:TypeError: fn2() missing 2 required keyword-only arguments: ‘b’ and ‘c’ ,函数2,3,少关键字b,c,如图
- 更改为:fn2(4,2,5,6,1,c=7), 得出正确结果为
- 其他情况如图
-
处理关键字参数, 形参可以接收其他关键字参数,它将这些参数统一保存在一个字典中,key 就是参数的名字,字典的value就是参数的值,**形参只有一个,并且只能写在所有参数的后面,**a是处理关键字参数
文档字符串
函数的返回值
- 返回值就是函数执行以后的返回结果,可以通过return来指定函数的返回值,可以直接使用返回值,也可通过一个变量来接收函数返回值
-
函数中,return后面的代码都不会执行,return一旦执行函数自动结束
函数的作用域
- 定义:作用域就是变量生效的区域
- 全局作用域:是函数外部,在程序执行时创建,在程序执行结束时销毁,所有函数以外的区域都是全剧作用域,在全局作用域中定义的变量,都是全局变量,可在程序任何位置进行访问
- 函数作用域:函数作用域在函数调用时创建,在调用结束时销毁,没调用一次就会产生一个新的函数作用域,在函数作用域中定义的变量,都是局部变量,它只能在函数内部被访问
-
NameError: name ‘a’ is not defined print(‘函数外部:a=’,a)
-
从内往外看可以外层作用域,从外往里看不行
- 如果希望函数内部修改全局变量的时候,则需要用global关键字,来声明变量,
global a ,此时a就是全局变量
递归函数
- 递归是一种解决问题的思想,它跟循环很像
- 整体思想是将一个大问题分解为一个一个的小问题,直到问题无法分解时再去解决问题
- 递归函数就是在函数中自己调用自己
- 举例说明,求10 的阶乘
- 创建一个函数 通过函数求任意数的阶乘,比较之前的遍历函数,设定两个参数,r和i,参数r 要求阶乘的数字,定义一个变量来保存一个结果, 变量为i, 返回一个结果
- 思路:10的阶乘为10!=12345…*10=3628800,将这个值r赋值给结果result,将i作为大于等于1 的数字,表达式为result *=i
- 基线条件:问题可以被分解为最小的问题,当满足基线条件时,递归就不在执行了
- 递归条件:将问题可以继续分解的条件
- 创建一个函数,用递归方式来解决,求任意数的阶乘
- 解题思路为,其中有两个变量,n,i,表达式可以写成ni=n*n(i-1)=fn(n,i-1)中n和i-1成为了这个元素,
作业
- 定义一个函数,用来检查一个任意字符串是否是回文字符串,如果是返回True,不是返回False,回文字符串从前往后念和从后往前念是一样的,例如TNT