1 普通函数(def)
1.1 函数的定义
1.1.1 格式
函数定义格式 |
|
python # 定义 def 函数名([形参名1], [形参名2], [形参名3], [形参名4=数据]): '''说明文档''' 执行语句 return 形参名b # 调用 函数名([实参名1], [实参名2], [实参名3], [实参名4=数据]) |
1.1.2 定义空函数
定义空函数 |
|
python def 空函数(): pass |
python # 占位符,实际上不做执行任何任务 |
1.2 函数的参数
1.2.1 形参/实参
无形参 |
|
python # 无形参 无返回值 def say_hello(): print('Hello, how do you do.') # 调用函数 say_hello() |
python Hello, how do you do. |
含形参 |
|
python # 有 形参 无返回值 def say_hello(name): print(f'Hello, {name}. How do you do.') # 通过 实参 调用函数 say_hello('Joey') say_hello() |
python # name 为形参,为仅函数内部传递的参数 # 'Joey' 为实参,为实际带入的参数 Hello,Joey. How do you do. 报错:TypeError: 缺少实参 |
1.2.2 必选参数/可选参数
必选参数/可选参数(默认形参) |
|
python # 必选函数--[形参名];可选函数--[形参名=默认值]。 def introduce_myself(name, age, sex='boy', region='Shenyang'): print(f"Hello, my name is {name}. I'm {age}-year-old. I'm a {sex} and I leave in {region}.") # 调用 函数 introduce_myself('Peter', 26) introduce_myself('Joey', 24, 'girl') # 使用参数覆盖默认值 python # [形参名] 字样为 必选参数,如 name,age;他们是调用函数时必须输入的参数。 # [形参名=数据] 字样为 可选参数,如 sex,rdgion;他们在调用函数时可不输入,输入可覆盖默认值 Hello, my name is Peter. I'm 26-year-old. I'm a boy and I leave in Shenyang. Hello, my name is Joey. I'm 24-year-old. I'm a girl and I leave in Shenyang. |
|
必选参数要在可选参数之前 |
|
python def aa(a=1, b): pass |
python 报错:SyntaxError: SyntaxError: non-default argument follows default argument |
1.2.3 位置参数/关键字参数
位置参数/关键字参数 |
|
python def 排排坐(a1, a2, a3, a4): print(f'a1={a1}; a2={a2}; a3={a3}; a4={a4}') # 位置参数调用 排排坐(1, 2, 3, 4) # 关键字参数调用 排排坐(a1=1, a3=2, a2=3, a4=4) # 混合调用 排排坐(1, 2, a3=4, a4=3) |
python a1=1; a2=2; a3=3; a4=4 a1=1; a2=3; a3=2; a4=4 a1=1; a2=2; a3=4; a4=3 |
1.2.4 可变参数
可变参数(参数数量可变) |
|
python def ddeeff(*args, **kw): print(args) print(kw) # 可变元组调用 ddeeff(1, 2, 3, 4) # 可变字典调用 ddeeff(a1=1, a3=2, a2=3, a4=4) # 混合调用 ddeeff(1, 2, a3=4, a4=3) |
python # *args 为可变元组,[形参]调用 # **kw 为可变字典,[实参1]=[实参2]调用 (1, 2, 3, 4) {} # 没用到可变字典 () # 没用到可变元组 {'a1': 1, 'a3': 2, 'a2': 3, 'a4': 4} (1, 2) {'a3': 4, 'a4': 3} |
定义时,可变元组必须在可变字典之前 |
|
python def ddeeff(**kw, *args): pass |
python SyntaxError: invalid syntax |
1.2.5 参数顺序
参数顺序 |
|
python # 定义函数时,参数顺序为:必选参数、可选参数、可变元组、可变字典。 def staff(name, job='TE', year=1, *others, **salary): print(f"{name} work as {job} in DRA for {year} years. ") print(f"He/She only earns {salary}. His friends earn {others}. ") # 调用函数时,格式[实参名] 必须在 格式[实参名=默认值] 前。 staff('Peter', 'BOM', 4, 7000, 8000, 9000, 12000, 刚来=3700, 第一年=3810, 第二年=3810, 第三年=4700, 第四年=4700) |
1.2.6 global/nonlocal对参数影响
global |
|
|
|
python # 全局变量 b = 150 def 嘿嘿嘿(): # 局部变量 a = 250 print(a + b) 嘿嘿嘿() # 400 print(b) # 150 print(a) # 报错 |
python # 全局变量 b = 150 def 嘿嘿嘿(): # 局部变量 a = 250 b = 250 print(a + b) 嘿嘿嘿() # 500 print(b) # 150 print(a) # 报错 |
|
python # 全局变量 b = 150 def 嘿嘿嘿(): # 局部变量 a = 250 global b b = 250 print(a + b) 嘿嘿嘿() # 500 print(b) # 250 print(a) # 报错 |
+ 全局变量可在任何地方使用; + 局部变量仅在函数内使用,在函数外使用报错; |
+ 全局变量可在函数中再次赋值作为局部变量使用; + 函数结束后,变量依然以全局变量声明的数值为准。除非… |
|
+ 除非在函数中使用全局变量前,用global 关键字声明一下。在函数结束后,全局变量变为global 后紧跟着赋的值 |
global 与 nonlocal |
|
|
|
python def 内函数对外函数变量影响(): 参数 = '外函数初始值' # 直接 改变外函数变量 失败 def 内函数局部变量(): 参数 = '内函数局部变量' 内函数局部变量() print(参数) # nonlocal 改变外函数变量 成功 def 外函数局部变量(): nonlocal 参数 参数 = '外函数局部变量' 外函数局部变量() print(参数) # global 改变外函数变量 失败 def 全局变量(): global 参数 参数 = '全局变量' 全局变量() print(参数) 内函数对外函数变量影响() print(参数) |
|
python 外函数初始值 # nonlocal 内函数中使用,改变外函数变量 外函数局部变量 # global 仅改变全局变量 外函数局部变量 全局变量 |
1.3 函数的返回值(return)
1.3.1 返回值使用
无返回值 |
|
python # 有形参 无返回值 def say_hello(name): print(f'Hello, {name}. How do you do.') # 调用 函数 say_hello('Joey') |
python Hello, Joey. How do you do. |
单返回值 |
|
python # 有形参 有返回值 def say_hello(name): return 'Hello,' + name + '. How do you do.' # 调用函数 print(say_hello('Joey')) |
python Hello,Joey. How do you do. |
多返回值 |
|
python def 某一函数(): return 520, 666 # 调用函数 print(某一函数()) |
python # 返回集合 (520, 666) |
1.3.2 返回值处理
多返回值处理(元组拆包) |
|
python def 某一函数(): return 520, 666 print(某一函数()) # 元组拆包 a,b = 某一函数() print(a) print(b) |
python # return 多返回值以元组形式返回 (520, 666) # 把函数 赋值给 对应数量的变量 520 666 |
特定返回值处理(字典拆包) |
|
python def 年龄查询函数(**年龄): return 年龄 年龄查询 = 年龄查询函数(Joey=24,Peter=26,Bill=28,Janet=29) print(年龄查询) # 字典拆包 a,b,c,d = 年龄查询 print(a) print(年龄查询[a]) |
python {'Joey': 24, 'Peter': 26, 'Bill': 28, 'Janet': 29} # 把函数 赋值给 对应数量的变量 Joey 24 |
1.3.3 使用限制/技巧
第一次执行到 return 直接退出 def |
|
python # 无形参 多返回值 def 找3的倍数(tup): for i in tup: if int(i) % 3 == 0: return '有3的倍数' return '没有3的倍数' # 调用函数 print(找3的倍数((2,7,5,3))) print(找3的倍数((2,7,5,4))) |
python # 如果满足第 4 行条件,则执行完 5 退出 有3的倍数 没有3的倍数 |
1.3.4 利用返回值实现函数递归
递归原则 |
|
+ 必须有停止条件(递归出口); + 必须能够反复自我调用; |
|
数字递归 |
|
python def 数字递归术(a): if a == 1: return 1 sum = a + 数字递归术(a-1) return sum # 函数调用测试 print(数字递归术(99)) |
python 4650 |
序列递归 |
|
python def 序列递归(形参): if type(形参) == dict: 形参 = list(形参.values()) else: 形参 = list(形参) if len(形参) == 1: return 形参[0] else: return 形参[0] + 序列递归(形参[1:]) # 函数调用测试 print(序列递归({'a': 1, 'b': 2})) print(序列递归([1,2,3,4,5,6,7,])) |
python # 等效 形参 = [i for i in 形参.values()] 3 28 |
1.4 函数的说明文档(’’’ help)
说明文档 |
|
python def find_3(a): ''' 参数: a 为一个 列表/元组/集合/字典。 功能: 查找所输入 列表/元组/集合/字典 中任一位含有3的数字 返回: 一个与输入数据相同的数据类型,包含所有满足情况的元素的。 ''' if type(a) == dict: dic = {} for i,j in a.items(): for k in range(len(str(i) + str(j))): if (str(i) + str(j))[k] == '3': dic[i] = j break return dic else: list1 = [] for i in a: for k in range(len(str(i))): if str(i)[k] == '3': list1.append(i) break if type(a) == list: return list1 elif type(a) == tuple: return tuple(list1) elif type(a) == set: return set(list1) # 调用函数 print(find_3((1, '2', 3, '13'))) print(find_3([1, 3, 2.3333])) print(find_3({5, 82, 354.0})) print(find_3({'a': 2, 'c': 3})) print('-' * 70) # 返回说明文档 help(find_3) python (3, '13') [3, 2.3333] {354.0} {'c': 3} ---------------------------------------------------------------------- # 返回的内容为函数中第一段备注 Help on function find_3 in module __main__: find_3(a) 参数: a 为一个 列表/元组/集合/字典。 功能: 查找所输入 列表/元组/集合/字典 中任一位含有3的数字 返回: 一个与输入数据相同的数据类型,包含所有满足情况的元素的。 |
1.5 函数的闭包
1.5.1 闭包规则
函数闭包 四点要求 |
|
python # 一元一次方程 def outer(a, b): def iner(x): print(a*x + b) return iner a = outer(2, 3) a(2) a(3) |
python # 1. 外函数中定义内函数 # 2. 内函数中使用外函数的参数 # 3. 外函数的返回值为内函数(无括号) # 4. 使用前先使用变量赋值外函数 7 9 # 注意参数数量的对应 |
特点:外函数变量 会在所有内函数执行完毕 才会释放 |
|
python # 计数器 def outer(a): b = 0 def iner(): nonlocal b b += 1 print(a + b) return iner a = outer(0) a() a() |
python # 没有nonlocal,a()会报错UnboundLocalError 1 2 |
1.5.2 装饰器
装饰器 隐式/显式闭包(区别高光) |
|
python def 前缀(fn): def tmp(): return 'Hello, ' + fn() return tmp def 后缀(fn): def tmp(): return fn() + ' Byebye.' return tmp @前缀 @后缀 def 正文1(): return "I'm Peter." print(正文1()) # 返回:Hello, I'm Peter. Byebye. |
python def 前缀(fn): def tmp(): return 'Hello, ' + fn() return tmp def 后缀(fn): def tmp(): return fn() + ' Byebye.' return tmp def 正文1(): return "I'm Peter" 正文1 = 前缀(正文1) 正文1 = 后缀(正文1) print(正文1()) # 返回:Hello, I'm Peter. Byebye. |
装饰器 有无参数(区别高光) |
|
python def 前缀(fn): def tmp(): return 'Hello, ' + fn() return tmp def 后缀(fn): def tmp(): return fn() + ' Byebye.' return tmp @前缀 @后缀 def 正文1(): return "I'm Peter." print(正文1()) # 返回:Hello, I'm Peter. Byebye. |
python def 前缀(fn): def tmp(name): return 'Hello, ' + fn(name) return tmp def 后缀(fn): def tmp(name): return fn(name) + '. Byebye.' return tmp @前缀 @后缀 def 正文1(name): return "I'm " + name print(正文1('Peter')) # 返回:Hello, I'm Peter. Byebye. |
装饰器 万能参数(区别高光) |
|
python def 前缀(fn): def tmp(name): return 'Hello, ' + fn(name) return tmp def 后缀(fn): def tmp(name): return fn(name) + '. Byebye.' return tmp @前缀 @后缀 def 正文1(name): return "I'm " + name print(正文1('Peter')) # 返回:Hello, I'm Peter. Byebye. |
python def 前缀(fn): def tmp(*a, **b): return 'Hello, ' + fn(*a, **b) return tmp def 后缀(fn): def tmp(*a, **b): return fn(*a, **b) + '. Byebye.' return tmp @前缀 @后缀 def 正文1(name): return "I'm " + name print(正文1('Peter')) # 返回:Hello, I'm Peter. Byebye. |
多重计数器 |
|
python def 计数器(fn): def inner(*a, **b): inner.count += 1 return fn(*a, **b) inner.count = 0 return inner @计数器 def 物料1(): pass @计数器 def 物料2(): pass 物料1() 物料1() 物料1() 物料2() print(物料1.count) # 返回:3 print(物料2.count) # 返回:1 |
python def 计数器(fn): mat_dic = {} def inner(物料号): if mat_dic.get(物料号): mat_dic.update({物料号: mat_dic[物料号] + 1}) else: mat_dic.update({物料号: 1}) return mat_dic return inner @计数器 def 物料(物料号): pass print(物料('物料号1')) print(物料('物料号1')) print(物料('物料号2')) # 返回:{'物料号1': 2, '物料号2': 1} |
2 匿名函数(lambda)
当函数有一个返回值,且只有一句代码,最好使用 匿名函数;
2.1 基本用法
2.1.1 前期赋值/后期赋值
前期赋值(一次性) |
|
python # (lambda 形参1: 表达式)(实参1) 平方 = (lambda x: x**2)(2) print(平方) # (lambda 形参1, 形参2: 表达式)(实参1, 实参2) 做和 = (lambda x, y: x+y)(2, 4) print(做和) |
python # 等同于:表达式中 形参1 替换成 实参1 # 等同于:2 ** 2 4 # 等同于:2 + 4 6 |
后期赋值(可多次使用) |
|
python # 变量名 = lambda 形参1: 表达式 平方 = lambda x: x**2 print(平方(2)) print(平方(3)) # 变量名 = lambda 形参1, 形参2: 表达式 做和 = lambda x, y: x+y print(做和(2, 4)) |
python # 返回:变量名(实参1) 4 9 # 可多次使用 # 返回:变量名(实参1, 实参2) 6 |
2.1.2 条件格式
条件格式 |
|
python # (lambda 形参1, 形参2: 表达式1 if 条件 else 表达式2)(实参1, 实参2) 最小值 = (lambda x, y: x if x < y else y)(1, 2) print(最小值) # 返回:1 |
2.1.3 嵌套格式
嵌套格式 |
|
python # (lambda 形参1: 表达式)(实参1) = 表达式中所有 形参1 替换成 实参1 lam1 = (lambda x: (lambda y: (lambda z: x + y + z)(3))(2))(1) lam2 = (lambda x: (lambda y: x + y + 3)(2))(1) lam3 = (lambda x: x + 2 + 3)(1) lam4 = 1 + 2 + 3 print(lam1) print(lam1 == lam2 == lam3 == lam4) |
|
笔者觉得 嵌套格式 只用于 前期赋值 |
|
python # 这么写会报错,也可能是有其他写法俺不会 lam1 = lambda x: (lambda y: (lambda z: x + y + z)) print(lam1(3, 2, 1)) # TypeError |
2.1.4 函数递归
函数递归 |
|
python # 单参数写法 func = lambda n: 1 if n == 1 else n ** 2 + func(n-1) print(func(4)) # 双参数写法 感觉完全没有使用双参数的必要,直接单参数就好 func = lambda func, n: 1 if n == 1 else n ** 2 + func(func, n-1) print(func(func, 4)) |
2.1.5 与普通函数等效
与普通函数等效 |
|
python # 无参 def 返回值(): return 666 print(返回值()) # 返回:666 # 含参 def 加法(a,b): return a + b print(加法(2, 3)) # 返回:5 # 可变元组 def 可变元组(*元组): return 元组 print(可变元组(1,2,3)) # 返回:(1, 2, 3) # 可变列表 def 可变列表(**列表): return 列表 print(可变列表(a=1,b=2,c=3)) # 返回:{'a': 1, 'b': 2, 'c': 3} |
python print((lambda: 666)()) # 返回:666 print((lambda a, b : a+b)(2, 3)) # 返回:5 print((lambda *元组: 元组)(1,2,3)) # 返回:(1, 2, 3) print((lambda **列表: 列表)(a=1,b=2,c=3)) # 返回:{'a': 1, 'b': 2, 'c': 3} |
2.2 高阶用法
单行写文件 |
|
python # 单行写文件 (lambda f, d: (f.write(d), f.close()))(open(r'd:/txt.txt', 'wb'), data) python # 用法一:可以通过前期赋值,将任何对象带入;(示例使用的是 file 对象) # 用法二:可以用 (表达式1,表达式2) 的方式写入多个表达式,在一行代码中进行多个操作; # 用法三:表达式的位置也可以使用各种对象的方法,而不仅仅是表达式; |
3 高阶函数
3.1 基本用法
|
|
python # 把函数本身作为参数 def 高阶函数(a, b, fun): return fun(a) + fun(b) print(高阶函数(-4, 5, abs)) |
python 9 |
3.2 内置高阶函数
2.2.1 序列计算(map)
序列计算 |
|
python 平方 = map(lambda x: x**2, range(1,5+1)) print(平方) # 返回:<map object at 0x7fa6f56d8340> ------- 迭代器对象 print(list(平方)) # 返回:[1, 4, 9, 16, 25] ---------------- 进一步处理 |
2.2.2 序列筛选(filter)
序列筛选 |
|
python 负数 = filter(lambda x: x<0, range(-3, 3+1)) print(负数) # 返回:<filter object at 0x7fa6f571fe80> --------------- 迭代器对象 print(list(负数)) # 返回:[-3, -2, -1] ------------------------------ 进一步处理 |
2.2.3 序列整合(reduce)
序列整合 |
|
python from functools import reduce # ---------------------- 需要提前导入functools包 平方和 = reduce(lambda x, y: (-2)**2 + y**2 if x==(-2) else x + y**2, range(-2, 2)) print(平方和) # 6 --------------------------------------------- 不需要进一步处理 |