函数
1. 使用步骤
-
定义函数
def 函数名(参数): 代码1 代码2 ......
-
调用函数
# 函数名(参数);不同的需求,参数可有可⽆无。 # 函数必须先定义后使⽤。 # 调用函数语句 务必 顶格写!
2. 函数 参数的作用
不必声明参数的数据类型
# 定义函数时同时定义了了接收⽤用户数据的参数a和b,a和b是形参
def add_num2(a, b):
result = a + b
print(result)
# 调⽤用函数时传⼊入了了真实的数据10 和 20,真实数据为实参
add_num2(10, 20)
3. 函数 返回值的作用
def buy():
return '烟'
# 使⽤用变量量保存函数返回值
goods = buy()
print(goods)
return 返回结果,并结束程序
4. 函数 说明文档
定义函数的说明⽂文档
def 函数名(参数):
""" 说明⽂文档的位置 """
代码
......
查看函数的说明⽂文档
help(函数名)
注意此处调用的是函数名,不包含括号!!
5. 函数 作用域
如何在函数体内部 修改全局变量?
a = 100
def testA():
print(a)
def testB():
# global 关键字声明a是全局变量量
global a
a = 200
print(a)
testA() # 100
testB() # 200
print(f'全局变量量a = {a}') # 全局变量量a = 200
此处一定要使用 global
修饰 a,否则,不过是在 testB() 中 有定义可一个同名的局部变量,修改的仅是局部变量 a;并非全局变量;
6. 多参数返回值
def return_num():
return 1, 2
result = return_num()
print(result) # (1, 2)
注意:
- return a, b 写法,返回多个数据的时候,默认是元组类型。
- return后面可以连接列表、元组或字典,以返回多个值。
7. 函数 参数的格式
-
位置参数
调⽤用函数时根据函数定义的参数位置来传递参数。
注意:传递和定义参数的顺序及个数必须⼀一致。def user_info(name, age, gender): print(f'您的名字是{name}, 年年龄是{age}, 性别是{gender}') user_info('TOM', 20, '男')
-
关键字参数
函数调⽤用,通过“键=值”形式加以指定。可以让函数更更加清晰、容易易使⽤用,同时也清除了了参数的顺序需求。
注意:函数调⽤用时,如果有位置参数时,位置参数必须在关键字参数的前⾯面,但关键字参数之间不不存在先后顺序。def user_info(name, age, gender): print(f'您的名字是{name}, 年年龄是{age}, 性别是{gender}') user_info('Rose', age=20, gender='⼥女女') user_info('⼩小明', gender='男', age=16)
-
缺省参数
缺省参数也叫默认参数,⽤用于定义函数,为参数提供默认值,调⽤用函数时可不不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调⽤用)。
注意:函数调⽤用时,如果为缺省参数传值则修改默认参数值;否则使⽤用这个默认值。def user_info(name, age, gender='男'): print(f'您的名字是{name}, 年年龄是{age}, 性别是{gender}') user_info('TOM', 20) user_info('Rose', 18, '⼥女女')
-
不定长参数
不定⻓长参数也叫可变参数。⽤用于不不确定调⽤用的时候会传递多少个参数(不不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常⽅便。
包裹位置传递def user_info(*args): print(args) # ('TOM',) user_info('TOM') # ('TOM', 18) user_info('TOM', 18)
注意:传进的所有参数都会被args变量量收集,它会根据传进参数的位置合并为⼀一个元组(tuple),
args是元组类型,这就是包裹位置传递。包裹关键字传递
def user_info(**kwargs): print(kwargs) # {'name': 'TOM', 'age': 18, 'id': 110} user_info(name='TOM', age=18, id=110)
综上:⽆无论是包裹位置传递还是包裹关键字传递,都是⼀一个组包的过程。
8. 拆包和交换变量量值
-
拆包
拆包:元组def return_num(): return 100, 200 # 返回的 res = (100,200) res = return_num() num1, num2 = return_num() print(num1) # 100 print(num2) # 200
拆包:字典
dict1 = {'name': 'TOM', 'age': 18} a, b = dict1 # 对字典进⾏行行拆包,取出来的是字典的key print(a) # name 键 print(b) # age 键 print(dict1[a]) # TOM 值 print(dict1[b]) # 18 值
-
交换变量
# 方法一:借助中间变量 # 方法二: a, b = 1, 2 a, b = b, a print(a) # 2 print(b) # 1
9. 引用
在python中,值是 靠引用来传递来的。
我们可以⽤用 id() 来判断两个变量量是否为同⼀一个值的引⽤。我们可以将id值理理解为那块内存的地址标识。
# 1. int类型
a = 1
b = a
print(b) # 1
print(id(a)) # 140708464157520
print(id(b)) # 140708464157520
a = 2
print(b) # 1,说明int类型为不不可变类型
print(id(a)) # 140708464157552,此时得到是的数据2的内存地址
print(id(b)) # 140708464157520
# 2. 列表
aa = [10, 20]
bb = aa
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
aa.append(30)
print(bb) # [10, 20, 30], 列列表为可变类型
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
- 引⽤当做实参
def test1(a):
print(a)
print(id(a))
a += a
print(a)
print(id(a))
# int:计算前后id值不不同
b = 100
test1(b)
# 列列表:计算前后id值相同
c = [11, 22]
test1(c)
10. 可变和不不可变类型
所谓可变类型与不不可变类型是指:数据能够直接进⾏行行修改,如果能直接修改那么就是可变,否则是不不可变.
- 可变类型
列列表
字典
集合 - 不可变类型
整型
浮点型
字符串串
元组
11. 函数 加强
11.1 综合应用 - 学员管理系统
注意使用:
- global 关键字以修改全局变量;
- 注意使用 for…else…
11.2 递归
-
递归的特点
函数内部⾃自⼰己调⽤用⾃自⼰己
必须有出⼝口 -
试求 3 以内 正整数之和
# 3 + 2 + 1 def sum_numbers(num): # 1.如果是1,直接返回1 -- 出⼝口 if num == 1: return 1 # 2.如果不不是1,重复执⾏行行累加: result = num + sum_numbers(num-1) # 3.返回累加结果 return result sum_result = sum_numbers(3) # 输出结果为6 print(sum_result)
11.3 lambda 表达式
-
如果一个函数 只有一个返回值,并且只有一句句代码,可以使⽤用 lambda简化。
lambda 参数列列表 : 表达式
# 注意:lambda表达式的参数可有可⽆无,函数的参数在lambda表达式中完全适⽤用。 # 注意:lambda函数能接收任何数量量的参数但只能返回⼀一个表达式的值 # 直接打印lambda表达式,输出的是此lambda的内存地址 # 函数 def fn1(): return 200 print(fn1) print(fn1()) # lambda表达式 fn2 = lambda: 100 print(fn2) # 内存地址 print(fn2()) # 正确调用方式
# 计算 a + b print((lambda a, b: a + b)(1, 2))
-
lambda的参数形式
- 无参数
print((lambda: 100)())
- 一个参数
print((lambda a: a)('hello world'))
- 默认参数
print((lambda a, b, c=100: a + b + c)(10, 20))
- 可变参数 *args
print((lambda *args: args)(10, 20, 30))
注意:这⾥里里的可变参数传⼊入到lambda之后,返回值为元组。 - 可变参数 **kwargs
print((lambda **kwargs: kwargs)(name='python', age=20))
- 无参数
-
lambda 应用
-
带判断的lambda
print((lambda a, b: a if a > b else b)(1000, 500))
-
列列表数据按字典key的值排序
students = [ {'name': 'TOM', 'age': 20}, {'name': 'ROSE', 'age': 19}, {'name': 'Jack', 'age': 22} ] # 按name值升序排列列 students.sort(key=lambda x: x['name']) print(students) # 按name值降序排列列 students.sort(key=lambda x: x['name'], reverse=True) print(students) # 按age值升序排列列 students.sort(key=lambda x: x['age']) print(students)
-
11.4 高阶函数
把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。
-
绝对值计算
abs(-10) # 10
-
⼀个函数完成计算任意两个数字的 绝对值之和。
# 方法一: def add_num(a, b): return abs(a) + abs(b) result = add_num(-1, 2) print(result) # 3
# 方法二: # 函数式编程大量使⽤函数,减少了代码的重复,因此程序⽐较短,开发速度较快。 def sum_num(a, b, f): return f(a) + f(b) result = sum_num(-1, 2, abs) print(result) # 3
11.1 内置高阶函数
-
map();map(func, lst),
将传⼊的函数变量量func作⽤用到lst变量的每个元素中,
并将结果组成新的列列表(Python2)/迭器器(Python3)返回# 计算list1 序列列中各个数字的2次⽅方。 list1 = [1, 2, 3, 4, 5] def func(x): return x ** 2 result = map(func, list1) print(result) # <map object at 0x0000013769653198> print(list(result)) # [1, 4, 9, 16, 25]
-
reduce();reduce(func(x,y),lst),
每次func计算的结果继续和序列的下⼀个元素做累积计算。
注意:reduce()传⼊入的参数func必须接受2个参数。#:计算list1 序列列中各个数字的累加和。 import functools list1 = [1, 2, 3, 4, 5] def func(a, b): return a + b result = functools.reduce(func, list1) print(result) # 15
-
filter();择取
# filter(func, lst)函数⽤用于过滤序列列, 过滤掉不不符合条件的元素, # 返回⼀一个 filter 对象,。如果要转换为列列表,可以使⽤list() 来转换。 list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def func(x): return x % 2 == 0 result = filter(func, list1) print(result) # <filter object at 0x0000017AF9DC3198> print(list(result)) # [2, 4, 6, 8, 10]