7 函数
7.1 分类
-
系统函数:
-
自定义函数:
- 定义函数使用关键字
def
,后跟函数名与括号内的形参列表; - 函数语句从下一行开始,并且必须缩进。
- 定义函数使用关键字
7.2 基本语法
-
语法:
def max(a, b): if a > b: return a else: return b
- 函数代码块以
def
关键词开头,后接函数标识符名称和圆括号()
; - 函数内容以冒号
:
起始,并且缩进; - 函数参数
(a, b)
,可以有多个,也可以没有,即直接是()
,(a, b)
也称为形参列表; - 函数可以有返回值,也可以没有。如果没有,
return
相当于返回None
;None
是内置常量,通常用来代表空值的对象;
- 函数代码块以
-
函数的调用:
- 函数定义好了,并不会自动执行,需要程序员调用,才会执行;
- 调用方式:
函数名(实参列表)
,比如:max(10,20)
。
7.3 注意
-
函数的参数列表可以是多个,也可以没有;
-
函数中的变量是局部的,函数外不生效;
-
如果同一个文件,出现两个同名函数,则以就近原则进行调用,所以实参要根据最近的那个函数的形参来配置传递;
-
调用函数时,根据函数定义的参数位置来传递参数,这种传参方式就是位置参数;
- 传递的实参和定义的的形参顺序和个数必须一致;
- 同时定义的形参,不用指定数据类型,会根据传入的实参决定;
-
函数可以有多个返回值,返回数据类型不受限制;
# 下面函数接收两个数,返回这两个数的和、差 def f2(n1, n2) return n1 + n2, n1 - n2
-
函数支持关键字参数:
- 函数调用时,可以通过
形参名 = 实参值
形式传递参数; - 这样可以不受参数传递顺序的限制;
def book_info(name, price, author, amount): print(f"name->{name} price->{price} author->{author} amount->{amount}") # 一般调用方式 book_info("红楼梦", 60, "曹雪芹", 30000) # 关键字参数 book_info(name = "红楼梦", price = 60, amount = 30000, author = "曹雪芹")
- 函数调用时,可以通过
-
函数支持默认参数/缺省参数:
- 定义函数时,可以给参数提供默认值;
- 调用函数时,如果指定了实参,则以指定的实参为准,如果没有指定,则以默认值为准;
def book_info(name = '<<thinking in python>>', price = 66.8, author = '龟叔', amount = 1000): print(f"name->{name} price->{price} author->{author} amount->{amount}") # 调用 book_info() # name-><<thinking in python>> price->66.8 author->龟叔 amount->1000 book_info('<<study python>>') # name-><<study python>> price->66.8 author->龟叔 amount->1000
- 默认参数,需要放在参数列表后;
def book_info(name, price, author = '龟叔', amount = 1000): print(f"name->{name} price->{price} author->{author} amount->{amount}") # 调用 book_info('<<python 揭秘>>', 999)
-
函数支持可变参数/不定长参数:
- 应用场景:当调用函数时,不确定传入多少个实参的情况;
- 传入的多个实参,会被组成一个元组(tuple);
- 简单说明:元组可以储存多个数据项;
# 要计算多个数的和,但是不确定是几个数 def sum(*args): print(f"args->{args} 类型是->{type(args)}") total = 0 # 对args进行遍历,即遍历args这个元组 for ele in args: total += ele return total result = sum(1, 2, 3) # result = sum(1, 2, 3, 4) print(f"result->{result}")
-
函数的可变参数/不定长参数,还支持多个关键字参数,也就是多个
形参名 = 实参值
- 应用场景:当调用函数时,不确定传入多少个关键字参数的情况;
- 传入的多个关键字参数,会被组成一个字典(dict);
- 简单说明:字典可以储存多个
键 = 值
的数据项;
# 需要接收一个人的信息,但是有哪些信息是不确定的,就可以使用关键字可变参数 def person_info(**args): print(f"kwargs->{args} 类型->{type(args)}") # 对args进行遍历,即遍历args这个字典 # {args[arg_name]}就是根据 arg_name 这个键取出的值 for arg_name in args: print(f"参数名->{arg_name} 参数值->{args[arg_name]}") person_info(name = "shisan", age = "18") # kwargs->{'name': 'shisan', 'age': '18'} 类型-><class 'dict'> # 参数名->name 参数值->shisan # 参数名->age 参数值->18 person_info(name = "shisan", age = "18", gender = "male") # kwargs->{'name': 'shisan', 'age': '18', 'gender': 'male'} 类型-><class 'dict'> # 参数名->name 参数值->shisan # 参数名->age 参数值->18 # 参数名->gender 参数值->male
-
Python调用另外一个
.py
文件中的函数:# f1.py文件中的内容如下: def add(x, y) print(x + y) # 在f2.py文件中调用f1.py的add函数如下: import f1 f1.add(1, 2) # 还有其它的引入方式
7.4 传参机制
-
数值和字符串类型的传参机制:
# 数值类型的传参机制 def function_num(a): print(f"a的值:{a} 地址是:{id(a)}") a += 1 print(f"a的值:{a} 地址是:{id(a)}") # 定义变量a a = 10 print(f"调用前 a的值:{a} 地址是:{id(a)}") # 调用函数 function_num(a) print(f"调用前 a的值:{a} 地址是:{id(a)}") # 调用前 a的值:10 地址是:140716675689176 # a的值:10 地址是:140716675689176 # a的值:11 地址是:140716675689208 # 调用前 a的值:10 地址是:140716675689176 # 字符串类型的传参机制 def function_string(str): print(f"str的值:{str} 地址是:{id(str)}") str += " , hi!" print(f"str的值:{str} 地址是:{id(str)}") # 定义变量str str = "shian" print(f"调用前 str的值:{str} 地址是:{id(str)}") # 调用函数 function_string(str) print(f"调用前 str的值:{str} 地址是:{id(str)}") # 调用前 str的值:shian 地址是:2473444466656 # str的值:shian 地址是:2473444466656 # str的值:shian , hi! 地址是:2473444620656 # 调用前 str的值:shian 地址是:2473444466656
- 字符串和数值类型是不可变数据类型,当对应的变量的值发生了变化时,它对应的内存地址会发生改变。
7.5 函数作为参数传递
-
例:
# 定义一个函数,返回两个数中的最大值 def get_max_val(num1, num2): max_val = num1 if num1 > num2 else num2 return max_val # f1返回两数中的最大值 def f1(fun, num1, num2): return fun(num1, num2) # f2返回两数之和,还有两数中的最大值 def f2(fun, num1, num2): return num1 + num2, fun(num1, num2) # 测试 print(f1(get_max_val, 1, 2)) x, y = f2(get_max_val, 1, 2) print(f"x = {x}, y = {y}") # 2 # x = 3, y = 2
-
函数作为参数传递,传递的不是数据,而是业务处理逻辑。
7.6 lambda匿名函数
-
当需要将函数作为参数进行传递,但是这个函数只使用一次时,可以考虑使用lambda匿名函数;
-
语法:
lambda 形参列表: 函数体 # 函数体只能有一行代码
-
例:
def f1(fun, num1, num2): return fun(num1, num2) # lambda a, b: a if a > b else b就是一个匿名函数 max_val = f1(lambda a, b: a if a > b else b, 1, 2) pintf(max_val) # 2
7.7 变量的作用范围
-
全局变量:在整个程序范围内都可以访问,定义在函数外,拥有全局作用域的变量;
-
局部变量:只能在其被声明的函数范围内访问,定义在函数内部,拥有局部作用域的变量;
-
重名变量的使用遵循就近原则;
-
当函数体外和函数体内都有一个重名的变量,想要在函数体内使用函数体外的全局变量,可以加一个
global
关键字;n = 1 def f1(): global n n = 2 print(n) return print(n) f1() # 1 # 2
7.8 range
函数
-
语法:
range(start, stop, step)
-
虽然
range
被称为函数,但range
实际上是一个不可变的序列类型; -
start
默认值是0,可以省略; -
step
是步长,默认是1,可以省略; -
通过
list()
可以查看range()
生成的序列包含的数据; -
range()
生成的数列是前闭后开;
-
-
例1:生成
[1, 2, 3, 4, 5]
r1 = range(1, 6, 1) print(list(r1))
-
例2:生成
[0, 1, 2, 3, 4, 5]
r2 = range(0, 6, 1) print(list(r2))
-
例3:生成
[1, 3, 5, 7, 9]
r3 = range(1, 10, 2) print(list(r3))
-
例4:使用
for + range
的方式输出10句Hello, World!for i in range(10): print("Hello, World!")
7.9 round
函数
round(number, ndigits=None)
- 返回
number
舍入到小数点后ndigits
位精度的值; - 如果
ndigits
被省略或为None
,则返回最接近输入值的整数(四舍五入
- 返回