Python学习笔记(九)—— 函数
一、函数调用:
1、python内部函数查询:http://docs.python.org/3/library/functions.html#abs
2、注意调用函数的参数个数和类型。
3、函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”:
>>> a = abs # 变量a指向abs函数 >>> a(-1) # 所以也可以通过a调用abs函数 1
二、定义函数
1、语法(以abs为例子)
def my_abs(x): if x >= 0: return x else: return -x
(1)函数一定有返回值:为NONE
(2)在Python交互环境中定义函数时,注意Python会出现...
的提示。函数定义结束后需要按两次回车重新回到>>>
提示符下:
2、函数封装成文件
(1)第一步将函数写在一个python文件中
(2)使用命令:
from python文件名(不要后缀) import 函数名字
(3)demo
3、空函数
(1)概念:
如果想定义一个什么事也不做的空函数,可以用pass
语句:
def nop():
pass
(2)作用:
比如现在还没想好怎么写函数的代码,就可以先放一个pass
,让代码能运行起来
4、参数检查
(1)个数检查
个数不对,python解释器会自动检查出来,幷报错。
(2)参数类型检查
类型出错,不会报出错误类型,需要自己手动添加。
1 2 3 4 5 6 7 | def my_abs(x): if not isinstance(x, ( int , float )): raise TypeError( 'bad operand type' ) if x >= 0: return x else : return -x |
其中isinstance是自带检测函数。
5、返回多个值
一个demo
1 2 3 4 5 6 | import math def move(x, y, step, angle=0): nx = x + step * math. cos (angle) ny = y - step * math. sin (angle) return nx, ny |
(1)import math
语句表示导入math
包,并允许后续代码引用math
包里的sin
、cos
等函数
(2)然后,我们就可以同时获得返回值:
1 2 3 | >>> x, y = move(100, 100, 60, math.pi / 6) >>> print(x, y) 151.96152422706632 70.0 |
但其实这只是一种假象,Python函数返回的仍然是单一值:
1 2 3 | >>> r = move(100, 100, 60, math.pi / 6) >>> print(r) (151.96152422706632, 70.0) |
原来返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。
三、函数的参数
1、位置参数
1 2 | def power(x): return x * x |
其中的 x 便是位置参数。
2、默认参数
1 2 3 4 5 6 | def power(x, n=2): s = 1 while n > 0: n = n - 1 s = s * x return s |
书写函数的时候可以将位置参数设置默认值,称为默认参数。
(1)好处:简化函数的调用方式,不需要修改参数n 的时候不需要赋值,简化函数的调用。
(2)规则:
A、必选参数在前,默认参数在后,否则Python的解释器会报错(思考一下为什么默认参数不能放在必选参数前面);
B、如何设置默认参数。当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
(3)调用小结
1 2 3 4 5 | def enroll(name, gender, age=6, city= 'Beijing' ): print( 'name:' , name) print( 'gender:' , gender) print( 'age:' , age) print( 'city:' , city) |
有多个默认参数时,调用的时候,既可以按顺序提供默认参数,比如调用enroll('Bob', 'M', 7)
,意思是,除了name
,gender
这两个参数外,最后1个参数应用在参数age
上,city
参数由于没有提供,仍然使用默认值。
也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。比如调用enroll('Adam', 'M', city='Tianjin')
,意思是,city
参数用传进去的值,其他默认参数继续使用默认值。
(4)默认参数必须指向不可变对象
一个Demo
1 2 3 | def add_end(L=[]): L.append( 'END' ) return L |
1 2 3 4 5 | >>> add_end() #当你使用默认参数调用时,一开始结果也是对的: [ 'END' ]>>> add_end() #但是,再次调用add_end()时,结果就不对了: [ 'END' , 'END' ] >>> add_end() [ 'END' , 'END' , 'END' ] |
默认参数L
的值一开始就被计算出来了,即[]
,因为默认参数L
也是一个变量,它指向对象[]
,每次调用该函数,如果改变了L
的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]
了。
修改方法:指向NONE
1 2 3 4 5 | def add_end(L=None): if L is None: L = [] L.append( 'END' ) return L |
3、可变参数
(1)格式
1 2 3 4 5 | def calc(*numbers): sum = 0 for n in numbers: sum = sum + n * n return sum |
即类似C语言指针的格式方法
(2)调用
A、list调用
1 2 3 | >>> nums = [1, 2, 3] >>> calc(*nums) 14 |
B、正常调用
1 2 3 4 | >>> calc(1, 2) 5 >>> calc() 0 |
4、关键字参数
(1)定义:
关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
(2)格式:
1 2 | def person(name, age, **kw): print( 'name:' , name, 'age:' , age, 'other:' , kw) |
(3)调用:
A、正常调用
1 2 3 4 | >>> person( 'Bob' , 35, city= 'Beijing' ) name: Bob age: 35 other: { 'city' : 'Beijing' } >>> person( 'Adam' , 45, gender= 'M' , job= 'Engineer' ) name: Adam age: 45 other: { 'gender' : 'M' , 'job' : 'Engineer' } |
B、dict调用
1 2 3 | >>> extra = { 'city' : 'Beijing' , 'job' : 'Engineer' } >>> person( 'Jack' , 24, **extra) name: Jack age: 24 other: { 'city' : 'Beijing' , 'job' : 'Engineer' } |
(4)命名关键字参数
对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw
检查。仍以person()
函数为例,我们希望检查是否有city
和job
参数:
1 2 3 4 5 6 7 8 | def person(name, age, **kw): if 'city' in kw: # 有city参数 pass if 'job' in kw: # 有job参数 pass print( 'name:' , name, 'age:' , age, 'other:' , kw) |
四、递归函数
1、尾递归
(1)概念
解决递归调用栈溢出的方法是通过尾递归优化,尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
(2)但是:
python解释器没有实现这样的功能
本文作者:Blue Mountain
本文链接:https://www.cnblogs.com/BlueMountain-HaggenDazs/p/6349541.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步