函数
函数的概念:函数就是实现某一特定功能的代码的封装
函数的分类:
a. 系统函数:系统定义好的函数,可以直接使用。例如:print、input、type等
b. 自定函数:自己定义函数
函数的定义:
语法:
def 函数名(形参列表):
函数说明文档
函数体
说明:
def --关键字 固定写法
函数名 自己命名
要求:标识符;不能是关键字
规范:所有字母都小写,多个单词之间用下划线;
见名知义;不能使用系统自带的函数名、模块名和类名
形参列表 -以 变量名1,变量名2,变量名3,……的形式存在(可以一个都没有)
作用:将函数外部的数据传递到函数的内部
定义函数的时候需不需要形参, 看函数实现功能 需不需要额外的参数
函数说明文档 --就是用""""""表示的说明性文字
函数体 --和def保持一个缩进的语句;
实现功能的一条或多条语句
定义函数的步骤
第一步:确定函数功能
第二步:根据函数功能确定函数名字
第三步:确定函数的参数(看函数实现功能 需不需要额外的参数)
第四步:实现函数功能
第五步:写说明文档
注意:定义函数的时候不会执行函数体!!调用函数的时候才会执行函数体
调用函数
语法:
函数名(实参列表)
说明:
函数名 —已经定义好的函数的函数名
实参列表 —以数据1,数据2,数据3,……的形式存在(也可以没有)
真正传递到函数中使用的数据
函数的参数
- 位置参数和关键字参数(实参)
根据函数调用的时候实参的传递方式将实参分为位置参数和关键字参数
a. 位置参数 --调用函数的时候直接在括号里面写多个实参,实参和形参是一一对应的
def func1(a,b,c):
print(f'a:{a},b:{b},c:{c}')
func1(20,10,30)
b. 关键字参数 --调用函数的时候以形参=实参 的方式来确定形参(位置不影响结果)
关键字参数不能重复;每个参数都赋值;不缺少
def func1(a,b,c):
print(f'a:{a},b:{b},c:{c}')
func1(a=20,c=10,b=30)
注意:位置参数可以和关键字参数一起使用,但是位置参数必须在关键字参数的前面
不管以什么样的形式传参,最终都要保证每个参数都有值;没有默认值的参数必须在有默认值的前面
def func1(a,b,c):
print(f'a:{a}, b:{b},c:{c}')
func1(20,b=10,c=30)
- 参数默认值(形参)
在定义函数的时候,可以给形参赋默认值;如果这个形参有默认值,那么这个参数在调用的时候可以不用传参。
def fun2(a=10,b=20,c=30):
print('a:{},b:{},c={}'.format(a,b,c))
fun2()
def fun2(c,a=10,b=20,):
print('a:{},b:{},c={}'.format(a,b,c))
fun2(30)
- 不定长参数(参数个数不确定)
a. 在一个参数前加*,那个这个参数就是一个不定长参数,可以同时接受多个参数
注意:带*参数的本质就是一个元组;
这个参数在调用的时候必须使用位置参数传参
# 练习定义一个函数,求多个数的和
def sum1(*nums):
print(type(nums),nums)
print(sum(nums))
# sum1()
sum1(10,20) #<class 'tuple'> (10, 20)
# sum1(12)
#定义一个函数计算一个学生所有学到的总成绩
def total_score(name,*score):
print(name)
print(score)
total_score('李四',29,45,66)
b.定义函数的时候在一个参数加**,那么这个参数就是一个不定长参数,同时可以接收多个实参
注意:带**的参数本质是一个字典;
必须使用关键字参数传参(关键自己随便命名)
def fun5(**num):
print(num)
# fun5(1) #TypeError: fun5() takes 0 positional arguments but 1 was given
fun5(a=1) #{'a': 1}
fun5(name='小明',age=18,sex='男') #{'name': '小明', 'age': 18, 'sex': '男'}
# 面试题:定义函数的时候,经常看到函数的参数:*args,**kwargs 这样写的意义是什么 def fun6(*args,**kwargs): pass fun6() fun6(1,2,3) fun6(a=2,b=3) fun6(1,2,a=2,b=3) # 俩种不定长函数一起用,最终还是实现一个参数个数不定的函数; # 只是这个函数在调用的时候更加灵活,可以只使用位置参数;可以只使用关键字参数; # 也可以位置参数和关键字参数一起使用
- 参数类型说明
def func7(a:int,b=10):
pass
func7()
def func8():
pass
方便别人看代码的时候,知道输入的类型
函数的返回值
-
什么是返回值
返回值就是从函数内部传递到函数外部的数据;
返回值就是return关键字后面的表达式的值;
返回值就是函数调用表达式的值。 -
return关键字
return是只能在函数体中使用的关键字,作用有俩个:
a.确定函数的返回值(return后面是什么,函数的返回值就是什么)
b.提前结束函数(只要遇到return,整个函数直接结束)
注意:如果在执行函数的时候没有遇到return,那么函数的返回值是None
怎么确定函数是否需要返回值:看实现函数的功能会不会产生新的数据,如果有,就将这个数据作为返回值
函数调用表达式:调用函数的表达式;当函数调用结束后,函数调用表达式的值就是函数的返回值
# 定义一个函数获取字符串中所有的数字字符
def get_num(str1):
num_str=''
for x in str1:
if '0'<=x<='9':
num_str+=x
return num_str
#用变量保存函数调用表达式的值,其实就是保存函数的返回值
re=get_num('123sdas23')
print(re)
def sum1(num1,num2):
totle=num1+num2
return totle
print(sum1(1,2))
# 返回值对应的数据能做的事,函数调用表达式都可以做
def sum1(a:int,b:int):
return a+b
print(30)
print(sum1(10,20))
- 函数调用过程
函数调用过程(执行过程)
第一步:回到函数定义的位置
第二步:传参(实参给形参赋值;传参的时候必须保证每个参数都有值)
第三步:执行函数体
第四步:执行完函数体确定返回值
执行完函数体:a.执行到函数体的最后;b.遇到return
怎么确定返回值:看函数执行完成的时候有没有遇到return,如果遇到了,就是return后面的值
;没有遇到return返回值是None
第五步:回到函数调用的位置,接着往后执行(这个时候函数调用表达式的只就是函数的返回值)
如果一个函数要返回多个数据,将多个数据作为一个元组中的元素返回
函数的返回值有且只有一个,如果要返回多个数据,就返回一个容器。常用元组
def fun1(a):
return a**2 ,a*2
print(fun1(10)) #(100, 20)
re=fun1(4)
print(re[0],re[1]) #16 8
x,y=fun1(5)
print(x,y) #25 10
变量的作用域
变量的作用域指的是变量的使用范围,根据变量使用范围,我们将变量分为全局变量和局部变量
- 全局变量和局部变量
1)全局变量
定义在函数和类的外部的变量就是全局变量。
作用域:从定义开始到文件结束的任何位置都能够使用
2)局部变量
定义在函数中的变量
作用域:从定义开始到函数结束的任何位置
#全局变量
a=10
#x,y都是全局变量
for x in range(4):
y=10
pass
#x1,y1,a1都是局部变量
def fun2(x1,y1):
a1=110
print(f'函数内部:',x1,y1,a1)
- globals和nonlocal
global和nonlocal只能在函数体中使用。
用globals可以在函数里面定义一个全局变量
name='小明'
age=18
def show_message():
global name
name='小花'
print(name)
global age
age=20
show_message()
print(age)
nonlocal:在局部的局部中修改局部变量的值的时候使用
def fun3():
num=100
def fun4():
nonlocal num
num=200
print('函数中的函数:',num)
fun4()
print('当前函数:',num)
fun3()
# 练习:有一个银行账号,定义俩个函数对这个函数进行存钱和取钱的操作
# 调用函数进行多次存钱和取钱的操作,在打印余额
account={
'name':'枫',
'id':'1241315465474' ,
'tel':'1111',
'balance': 1000
}
def get_money(money:int):
if account['balance']>=money:
account['balance']-=money
else:
print('钱不够,滚!')
def save(money:int):
account['balance']+=money
get_money(2344)
save(123)
print(account['balance'])
#方法二
number=5000
def get_money(money:int):
global number
if number>=money:
number-=money
else:
print('钱不够,滚!')
def save(money:int):
number+=money
匿名函数
匿名函数的本质还是函数,除了定义的语法以外,其他的和普通函数没有区别
语法:
函数名=lambda 参数列表:返回值
相当于
def 函数名(参数列表):
return 返回值
# 写一个匿名函数求俩个数的和
# sum1=lambda num1,num2:num1+num2
def sum1(num1,num2):
return num1+num2
print (sum1 (1, 2))
# 练习:根据年龄的范围返回成年或未成年
ages=lambda age:'成年' if age>=18 else '未成年'
print(ages(88))
ages=lambda age: age>=18
函数就是变量
定义函数的时候,其实就是在定义一个类型是function的变量,函数名就是变量名
普通变量能做的事情函数都有可以做
- 查看变量类型
def a():
print('函数1')
b=[1,2]
print(type(b)) #<class 'list'>
print(type(a)) #<class 'function'>
- 使用变量中保存的数据
print(b) #[1, 2]
print(a) #<function func1 at 0x02B36150>
b2=b
print(b2[1]) #2
a2=a
a2() #函数1
- 修改变量的值
b=100
print(b) #100
a='asd'
print(a) #asd
- 变量可以作为列表元素
x=100
def y():
return 'abs'
list1=[x,y,y()]
print(list1) #[100, <function y at 0x035A6108>, 'abs']
print(list1[0] * 2,list1[0]%10) #200 0
print (list1[1] ())#abs
高阶函数
如果一个函数的参数就是函数,那么这个函数就是实参高阶函数
高阶函数的参数
- 普通变量可以作为函数的参数
def func1(x):
print(f'x:{x}')
a=100
func1(a) #x:100
2.函数可以作为函数的参数
def func1(x):
print(f'x:{x}')
def b():
return 'abc'
func1(b) #x:<function b at 0x013260C0>
- 函数的返回值作为实参
def func1(x):
print(f'x:{x}')
def b():
return 'abc'
func1(b()) #x:abc
怎么确定调用函数的时候参数传什么值
看这个参数在函数中是怎么使用的
def func2(x):
print(x+10)
func2(20) #30
func2(1.34) #11.34
func2(True) #11
def func3(x):
print(x[1])
func3('abc')
func3([100,200,300])
func3((1,2,3))
# func5就是一个实参高阶函数
def func5(x):
# x = lambda item: 'a'
# x = test
# print(test(100)) -> print(1000)
# print(test(100)) -> print('a')
print(x(100))
def test(a):
# a = 100
return a*10 # return 1000
func5(test)
func5(lambda item: 'a')
实参高阶函数的应用
除了写装饰器以外,一般不会自己去定义实参高阶函数,主要是使用系统以及定义好的实参高阶函数
系统中常用的实参高阶函数;max、min、sorted、reduce、map
- max、min
max(序列)/min(序列) --获取指定序列中元素的最大值/最小值
max(序列,key)/min(序列,key) --参数key的类型是函数;
key的要求:a. 是一个函数
b.函数有且只有一个参数,并且这个参数指向的是序列中的每一个元素
c.需要一个返回值,这个返回值就是比较大小的时候的比较对象
nums=[12,34,566,77]
# print (max (nums))
print (max (nums, key=lambda item: item)) #566;比较 元素本身的大小
def test(item):
sum1=0
for x in str(item):
sum1+=int(x)
return sum1
print(max(nums,key=test)) #566
# max实现原理
def yt_max(seq,key=None):
list1=list(seq)
temp=list1[0]
if not key:
for x in list1:
if x>temp:
temp=x
else:
for x in list1:
if key(x)>key(temp):
temp=x
return temp
print(yt_max([109,240,45,66,67]))
print(yt_max([109,24,45,66,67],key=lambda item:item%10))
# 问题1:求students中分数最高的学生
students=[
{'name':'小明','age':23,'score':90},
{'name':'小红','age':25,'score':80},
{'name':'小丽','age':29,'score':70}
]
print(max(students,key=lambda item:item['score']))
print(min(students,key=lambda item:item['age']) )
# 问题2:求nums中个位数最大的元素
# print (max (nums, key=lambda item: item%10)) #77
# list1=['zbc','sdfddf','dds']
# print(max(list1)) #zbc
# print(max(list1,key=lambda item:len(item))) #sdfddf
- sorted
sorted(序列) --按照序列元素的大小进行排序,返回的是排序后的列表
sorted(序列,key) --key:a.函数 b.有且只有一个参数(参数就是序列中的元素)
c.有一个返回值(比较大小的比较对象)
nums=[73,69,57,28,71,54]
print(sorted(nums)) #[28, 54, 57, 69, 71, 73]
#按照个位数的大小从小到大排序
print(sorted(nums,key=lambda item:item%10)) #[71, 73, 54, 57, 28, 69]
# 将students按照分数从大到小排序
print(sorted(students,key=lambda item:item['score'],reverse=True))
- map
方法一:
map(函数,序列)—将序列按照函数 给的的规则创建成一个新的序列
函数的要求:a.是一个函数 b.有一个参数(指向序列中的每个元素)
c.一个返回值(产生新元素的规则)
方法二:
map(函数,序列1,序列2) --将序列按照函数给定的规则创建成一个新的序列
函数的要求:a.是一个函数 b.有俩个参数(第一个参数指向第一个序列中的元素,第二个参数指向第二个序列中的元素)
c.一个返回值(产生新元素的规则)
注意:俩个序列中元素的个数一致
生成一个新列表,元素是nums所有元素的个位数
nums=[12,34,556,778,88]
new_nums=list(map(lambda item:item%10,nums))
print(new_nums)
# 使用map创建一个新的列表,元素是nums中元素的100倍
nums=[0.23,0.34,0.45,0.68]
# new_nums=list(map(lambda item:item*100,nums))
# print(new_nums)
new_nums=list(map(lambda item:f'{item:.2%}',nums))
print(new_nums) #['23.00%', '34.00%', '45.00%', '68.00%']
strs=['abc','hao','you','love']
nums=[1,20,4,60]
new_list=list(map(lambda x,y:x+str(y),strs,nums))
print(new_list) #['abc1', 'hao20', 'you4', 'love60']
prices=[67,30,456,89]
discount=[1,0.8,0.75,0.95]
new_prices=list(map(lambda x,y:x*y,prices,discount))
print(new_prices) #[67, 24.0, 342.0, 84.55]
- reduce
方法一:
reduce(函数,序列) --将序列中所有的元素按照函数规定的操作进行合并
函数的要求:a.函数 b.有俩个参数(第一个参数第一次指向的是序列的第一个元素,从第二次开始指的是上次的运算结果
第二个参数指向是序列第二个开始的每个元素)
方法二:
reduce(函数,序列,默认值)–将序列中所有的元素按照函数规定的操作进行合并
函数的要求:a.函数 b.有俩个参数(第一个参数第一次是初始值,从第二次开始指的是上次的运算结果
第二个参数指向的是序列的每个元素)
nums=[67,30,456,89]
result=reduce(lambda x,y:x+y,nums)
print(result) #642
# 合并成一个字符串
result=reduce(lambda x,y:str(x)+str(y),nums)
print(result) #673045689
students=[
{'name':'小明','age':23,'score':90},
{'name':'小红','age':25,'score':80},
{'name':'小丽','age':29,'score':70}
]
result=reduce(lambda x,y:x+ y['score'],students,0)
print(result) #240
def test(x,y):
print(f'x:{x},y:{y}')
return x+y['score']