python高阶(五)——函数学习
函数 function
什么是函数:函数是可以重复执行的语句块,可以重复使用
作用:
1. 用于封装语句块,提高代码的重用性
2. 定义用户级别的函数
函数定义(创建)语句 def 语句的语法:
def 函数名(形参列表): 语句块
说明:
1. 函数的名字就是语句块的名称
2. 函数名的命名规则与变量名相同(函数名必须为标识符)
3. 函数有自己的名字空间,在函数外部不可以访问函数内部的变量,在函数内部可以访问函数外部的变量,通常让函数处理外部数据需要用参数给函数传入一些数据
4. 函数的参数列表可以为空
5. 语句部分不能为空。如果为空需要填充pass语句
函数的调用
函数名(实际调用传递参数列表) 注: 实际调用传递参数以后称为实参
说明:
- 函数调用是一个表达式
- 如果没有return语句,此函数执行完毕后返回None 对象
- 如果函数需要返回其它的对象需要用到return语句
return 语句
语法:return [表达式] [] 代表可以省略
作用:用于函数中,结束当前函数的执行,返回到调用该函数的地方,同时返回一个对象的引用关系
说明:
1. return语句后跟的表达式可以省略,省略后相当于 return None
2. 如果函数没有return语句,则函数执行完最后一条语句后返回None(相当于在最后加了一条return None语句)
3. 函数调用一定会返回一个对象的引用
python 函数的参数传递
传递方式:位置传递 序列传参 关键字传参 字典关键字传参
位置传参:实际参数(实参)的对应关系与形式参数(形参)的对应关系是按位置来依次对应的
def myfun(a, b, c): pass myfun(1, 2, 3)
- 实际参数和形式参数通过位置进行传递的匹配
- 实参个数必须与形参个数相同
序列传参:序列传参是指在函数调用过程中,用 * 将序列拆解后按位置传参的方式进行参数传递
def myfun(a, b, c): pass s = [1, 2, 3] myfun(*s) # * 表示把s拆开 s2 = "ABC" myfun(*s2)
关键字传参:关键字传参是指传参时,按着形参的名称给形参赋值
实参和形参按名称进行匹配
def myfun(a, b, c): pass myfun(b=22, c=33, a=11) # 等同于myfun(11,22,33) myfun(c=3, b=2, a=1)
- 实参和形参可以不按位置匹配
字典关键字传参:是指实参为字典,将字典用 ** 拆解后进行关键字传参
def myfun(a, b, c): pass d = {'c': 33, 'b': 22, 'a': 11} myfun(**d) # 拆解字典后再传参
- 字典的键名和形参名必须一致
- 字典键名必须为字符串
- 字典的键名要在形参中存在
函数的综合传参:函数传参方式,在能确定形参能唯一匹配到相应实参的情况下可以任意组合
def myfun(a, b, c): pass myfun(100, *[200, 300]) # 正确 myfun(*'AB', 300) # 正确 myfun(100, c=300, b=200) # 正确 myfun(1, **{'c': 3, 'b': 2}) # 正确 myfun(**{'c': 3, 'b': 2}, a=1) # 正确 myfun(b=2, c=3, 1) # 错误,不能确定1给谁?
- 传参时先位置传参,后关键字传参
# 练习: # 1. 写一个函数sum3(a, b, c): # 用于返回三个数的和 # 写一个函数pow3(x) 用于返回x的三次方(立方) # 1) 用以上函数计算 # 1**3 + 2 ** 3 + 3**3的和 # 2) 计算 1 + 2 + 3 的和的立方 # 即(1+2+3)**3 # 写一个函数sum3(a, b, c) 用于返回三个数的和 def sum3(a, b, c): return a + b + c # 写一个函数pow3(x) 用于返回x的三次方(立方) def pow3(x): return x ** 3 # 1) 用以上函数计算 # 1**3 + 2 ** 3 + 3**3的和 print(sum3(pow3(1), pow3(2), pow3(3))) # 36 # 2) 计算 1 + 2 + 3 的和的立方 # 即(1+2+3)**3 print(pow3(sum3(1,2,3))) # 216
-------- 以下学习的是函数的形参(如何接收实参)-----
函数的缺省参数
语法:def 函数名(形参名1=默认实参1, 形参名2=默认实参2, ...): ...
def info(name, age=1, address="未填写"): print(name, "今年",age, '岁, 家庭地址是:', address) info('LeoLRH', 20) info('小魏', 20, '北京市朝阳区') info('小李')
1. 缺省参数必须自右至左依次存在,如果一个参数有缺省参数,则其右侧的所有参数都必须有缺省参数
def test(a, b=10, c): # <---是错的 pass
2. 缺省参数可以有0个或多个,甚至全部都有缺省参数
# 练习 : # 1. 写一个函数 mysum(), 可以传入两个实参或三个实参. # 1) 如果传入两个实参,则返回两个实参的和 # 2) 如果传入三个实参,则返回前两个实参的和对第三个实参求余的结果 # print(mysum(1, 100)) # 101 # print(mysum(2, 10, 7)) # 5 返回:(2+10) % 5 # 方法1 # def mysum(x, y, z=0): # if z == 0: # return x + y # return (x + y) % z # 方法2 def mysum(x, y, z=None): if z is None: return x + y return (x + y) % z print(mysum(1, 100)) # 101 print(mysum(2, 10, 7)) # 5 返回:(2+10) % 5
函数的形参定义方式
位置形参 星号元组形参 命名关键字形参 双星号字典形参
位置形参
语法:def 函数名(形参名1, 形参名2, ...): 语句块
星号元组形参
语法:def 函数名(*元组形参名): 语句
作用:收集多合的位置传参 元组形参名通常用: 'args'
# 此示例示意星号元组形参 def func(*args): print("参数个数是:", len(args)) print('args =', args) func(1,2,3,4) func("hello", "world", 1, 2, 3)
# 练习: # 写一个函数,mysum , 可以传入任意个实参的数字,返回所有实参的和 # def mysum(.....): # ...... # print(mysum(1, 2, 3, 4)) # 10 # print(mysum(2,4,6)) # 12 # 方法1, 用系统内建的sum函数函数求和: # def mysum(*args): # return sum(args) # 方法2, 用自己的算法来求和 def mysum(*args): s = 0 for x in args: s += x return s print(mysum(1, 2, 3, 4)) # 10 print(mysum(2,4,6)) # 12
命名关键字形参
语法:def 函数名(*, 命名关键字形参): 语句 或 def 函数名(*args, 命名关键字形参): 语句
作用:所有的参数都必须用关键字传参或字典关键字传参传递
# 此示例示意命名关键字形参 def fn(*, d, e): print("d=", d) print("e=", e) fn(d=100, e=200) # 合法调用 # fn(1, 2) # 不合法,不能用位置传参 # fn(1, 2, d=100, e=200) def fm(*args, d, e): print(args) print('d=', d) print('e=', e) fm(1, 2, d=100, e=200) fm(*"AB", **{'e': 20, 'd':10})
双星号字典形参
语法:def 函数名(**字典形参名): 语句
作用:收集多合的关键字传参 通常字典形参名定为: "kwargs"
# 此示例示意双星号字典形参kwargs收集多余的关键字传参 def func(**kwargs): print("关键字参数个数是:", len(kwargs)) print("kwargs =", kwargs) func(name='tarena', age=15) func()
- 缺省参数,位置形参,星号元组形参,命名关键字形参和双号星字典形参可以混合使用
- 函数参数自左至右的顺序为:位置形参 星号元组形参 命名关键字形参 双星号字典形参
def f1(a, b, *args, c, **kwargs): pass f1(1, 2, 3, 4, d=6, c=5, e=7)
函数的不定长参数
def fn(*args, **kwargs): pass # 可以接收任意的位置传参和关键字传参
很重要注意一下
# 练习: # 写一个myrange函数,此函数返回一个符合range规则的整数列表 # 如: # L = myrange(3) # print(L) # [0,1,2] # L = myrange(3, 6) # print(L) # [3, 4, 5] # L = myrange(1, 10, 3) # print(L) # [1, 4, 7] def myrange(start, stop=None, step=1): # 如果传入一个参数,start绑定0,stop绑定第一个参数 if stop is None: stop = start start = 0 L = [] i = start # 用i绑定一个开始值 while i < stop: # 把i放到L列表中 L.append(i) # 按step来递增i i += step return L L = myrange(3) print(L) # [0,1,2] L = myrange(3, 6) print(L) # [3, 4, 5] L = myrange(1, 10, 3) print(L) # [1, 4, 7]