Python编程学习-基础笔记04
六、函数
6.1 函数基础
6.1.1 函数定义
''''
函数:复用
格式:
def 函数名([参数],...)
代码
sample:
def get_name():
pass
def search():
pass
代码:
封装重复内容
函数调用:函数名()
'''
import random
def gernerate_code():
# 定义一个空字符串
ver_code = ''
# 准备一个字符串,包含字母和数字
source = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890'
for i in range(4):
# 可以直接随机取一个字符
r = random.choice(source)
# 将每次获取到的值拼接为4为的字符串
ver_code += r
print(ver_code)
print(gernerate_code) #<function gernerate_code at 0x0000020BCFE3C2F0>
'''
定义一个login函数
用户名:admin,密码:123456
验证用户名和密码是否正确
'''
def login():
while True:
#输入用户名或手机号
login_name = input("请输入用户名/手机号:")
passwd = input("请输入密码:")
if login_name == 'admin' and passwd == '123456':
break
print('登录成功')
else:
print('用户名或密码有误,请重新输入')
#验证函数是否可用?调用函数
gernerate_code()
login()
6.1.2 带参数的函数
'''
参数:
1,无参数
2,有参数
无参数:
def 函数名()
代码
有参数:
def 函数名(参数1,参数2,...)
代码
参数就是在调用函数时,往函数体内传值
默认值参数:在定义函数的时候,有一个或多个参数已经赋值好
def 函数名(参数1,参数2,参数3=值,参数4=值):
pass
调用特点:
函数名(值1,值2,值3)
注意:
定义函数时,普通参数要位于默认值参数前面
调用时,默认参数顺序时定义时的顺序,可以指定关键字参数赋值,改变顺序
'''
#login 带参数,n表示允许输入的错误此次数
def login(n):
m =0
while m < n:
m += 1
#输入用户名或手机号
login_name = input("请输入用户名/手机号:")
passwd = input("请输入密码:")
if login_name == 'admin' and passwd == '123456':
break
print('登录成功')
else:
print('用户名或密码有误,请重新输入')
#数字累加函数1 - n
def accumulation(n):
sum = 0
m = 0
while m <= n:
sum += m
m += 1
print(sum)
#带默认值的函数,number和school带默认值,不传入参数时,使用默认值
def borrow_book(bookname,username,number=1,school='天大'):
print(f'欢迎进入{school}借书系统>>>>>>')
print(f'{username}借阅了{bookname},共{number}本')
#函数调用
# login(3)
accumulation(10)
borrow_book('Forrest','红楼梦') #红楼梦借阅了Forrest,共1本
borrow_book(username='Forrest',bookname='红楼梦') #Forrest借阅了红楼梦,共1本
borrow_book('Forrest','红楼梦',2) #红楼梦借阅了Forrest,共2本
#普通参数也带上关键字后,默认参数不能直接给值
borrow_book(username='Forrest',bookname='红楼梦',number=2,school='北大') #SyntaxError: positional argument follows keyword argument
可变参数:参数类型为列表,元组和集合
'''
参数类型:
1,列表
2,可变参数:
*args
**kwargs
3,装包和拆包 --> 对应可变参数
装包:函数装包的过程,定义函数是,参数加星*
def 函数(*args): --> 此时函数会出现装包
pass
拆包:函数拆包的过程,调用函数时,参数加星*, 拆列表,元组和集合
调用函数时:
函数(*list) | 函数(*tuple) |函数(*set)
'''
#验证示例讲解
#参数和变量个数相等
a,b,c = 1,2,3
print(a)
print(b)
print(c)
#参数和变量个数不等,带星号的表示一个容器,多余的参数都给带星的
a,*b,c = 1,2,3,4,5,
print(a)
print(b) #[2, 3, 4]
print(c)
#参数和变量个数不等,带星号的表示一个容器,多余的参数都给带星的
*a,b,c = (1,2,3,4,5)
print(a) #[1, 2, 3]
print(b)
print(c)
#参数类型为列表
list1 = [1,5,66,34,22,7,77,89,100,25,50]
#从列表中删除小于50的数,list_1-->形参,可以随便定义
def del_from_list(list_1):
n = 0
while n < len(list_1):
if list_1[n] < 50:
list_1.remove(list_1[n])
else:
n += 1
print(list_1)
#可变参数,重写求和函数,*星号是关键,装包,之后的变量名可以任意,但通常用args
def get_sum(*args):
s = 0
for i in args:
s += i
print(s)
#函数调用,list1 实参
del_from_list(list1)
get_sum(1,2) #参与会以元组的形式赋值给变量
get_sum(1,2,3,4,5)
#调用是加*,星号表示拆包
get_sum(*list1) #382
可变参数:带2颗星的情况, 同时有1颗星 和2颗星的情况
'''
可变参数:**kwargs, 关键字参数
在函数调用时必须传递关键字参数,才可以转换为key:value,装载到字典中
'''
#key word
def show_book(**kwargs):
print(kwargs)
#同时带了*args 和 **kwargs
def show_story(*args,**kwargs):
print(args) #()
print(kwargs) #{}
#调用函数
show_book() #{}
# show_book('红楼梦') #TypeError: show_book() takes 0 positional arguments but 1 was given
#可以加多个关键参数
show_book(bookname='红楼梦',author='曹雪芹') #{'bookname': '红楼梦', 'author': '曹雪芹'}
#拆包,必须加2颗星
book = {'bookname': '红楼梦', 'author': '曹雪芹'}
show_book(**book) #{'bookname': '红楼梦', 'author': '曹雪芹'}
#带* ** 的情况
show_story('小红','小花') #('小红', '小花')
show_story('小红','小花', story='星际联邦')
'''
('小红', '小花')
{'story': '星际联邦'}
'''
#字符拼接,'-' 以此为分隔符
result = ''.join(['a','b','c'])
print(result) #abc
result = '-'.join(['a','b','c'])
print(result) #abc
6.2 函数应用
6.2.1 函数注释
'''
在函数体内加上注释,给使用函数的人以提示信息
'''
6.2.2 函数返回值
return 会结束函数调用,并返回值。return不仅会结束循环,还会结束函数
'''
参数:外界向函数内传值
返回值:函数里面的内容值向往传递
def function():
...
return xx
当函数调用时,通过return向往返回值
注意: 只有函数有返回值,外部需要有变量来接收
return 后可跟一个或多个值,逗号分隔
如果时多个值,返回的是一个元组,多个值被封装在元组中
示例: retur a,b,c
结果 (a,b,c)
'''
#将计算结果作为返回值,返回一个值
def get_sum(*args):
s = 0
for i in args:
s += i
#返回计算结果
return s
#返回多个值
def get_max_min(numbers):
#先排序:冒泡排序
for i in range(len(numbers)-1):
for j in range(0,len(numbers)-1-i):
if numbers[j]>numbers[j+1]:
numbers[j],numbers[j+1] = numbers[j+1],numbers[j]
#获取头和尾
min = numbers[0]
max = numbers[-1]
#返回
return min,max
#在外部定义一个变量total来接收函数的返回值
total = get_sum(1,2,3,5)
x = 100
x = x + total
print(x) #111
list1 = [3,8,6,11,25,43,66,89,36,77,99,66]
#return返回2个值(min,max),使用2个变量来接收
min,max = get_max_min(list1)
print(min,max)
6.3 函数高级
6.3.1 全局变量和局部变量
全局变量:声明在函数外部的变量
局部变量:声明在函数内部的变量,使用范围仅限于函数内部
'''
全局和局部变量:
全局变量:声明在函数外部的变量
局部变量:声明在函数内部的变量,使用范围仅限于函数内部
注意:
函数内部可以直接使用全局变量,但是不能直接修改全局变量
如果想修改全局变量,则必须使用关键字 global
global 关键字的添加:
'''
a = 100
def test1():
#局部变量,函数优先使用
a = 0
b = 8
print('a = ',a)
print('b = ',b)
def test2():
#局部变量,函数优先使用,如果函数体内定义的同名的变量
b = 8
#这里取到的a就是全局变量a
print('a = ',a)
print('b = ',b)
def test3():
#声明a为全局变量
global a
#如果部声明a为全局变量,函数内部无权操作a
a -= 10
#这里取到的a就是全局变量a
print('a = ',a)
#函数调用
test3()
test1()
test2()
6.3.2 可变和不可变类型
'''
全局和局部变量:
global 关键字的添加:
只有不可变的类型,才需要添加关键字global
可变类型,不需要添加关键字global
可变和不可变类型:
不可变:当改变变量值时,地址发生了改变
类型:int, str,float,bool, tuple
可变:内容发生改变,但是地址没有发生改变
类型:list, dict, set
'''
#可变变量
library = ['红楼梦','水浒传','西游记','三国演义']
print(id(library)) #2425797567112
library.append('窦娥冤')
print(id(library)) #2425797567112
#不可变变量
a = 100
print(id(a)) #140712806182832
a = 80
print(id(a)) #140712806182192
s = 'abc'
print(id(s)) #1698608322912
s = 'def'
print(id(s)) #1698608946848
t1 = (1,2,3)
print(id(t1)) #1908556126968
t1 = (1,2,3,4)
print(id(t1)) #1908556105112
#添加图书
def add_book(bookname):
if bookname not in library:
library.append(bookname)
print(f'{bookname}添加成功')
else:
print('此书已经存在')
#展示全部图书
def show_books(books):
for book in books:
print(book)
#函数调用
add_book('西厢记')
show_books(library)
6.3.3 引用及参数值传递
'''
引用:
1,不是在函数中使用,可以通过sys.getrefcount(a)查看引用个数
del 变量名 --> 表示删除了一个引用
2,函数的引用:
必须要分清传递的值是可变还是不可变类型
如果可变,里面发生改变,外层可以看到改变后的内容
如果是不可变,里面发生改变,不会影响外部的变量值
'''
import sys
list1 = [1,2,3,4,5]
list2 = list1 #list1 将其引用地址给list2赋值
list3 = list1
#获取变量被引用的次数,这里查的是地址
print(sys.getrefcount(list1)) #4
del list2
print(sys.getrefcount(list1)) #3
def test(n1):
#n1是局部变量
for i in range(n1):
print('--->',i)
n1 += 1 # 这里改变的只是局部变量的值
n = 9
#调用test
test(n)
print(n) #9
def test1(l):
#判断传入的是列表
if isinstance(l,list):
for i in l:
print(i)
#在第0个位置插入新的值
l.insert(0,8) #可变参数,改变的是全局参数值
else:
print('不是列表类型')
#调用test1
test1(list1)
print(list1) #[8, 1, 2, 3, 4, 5]
6.3.4 练习:停车计费系统
'''
停车计费数据结果:
[{'车牌':[进入时间,0]},{'车牌':[进入时间,出场时间]}]
15分钟 1元
1小时 4 元
停车场变量--> 全局变量
'''
import random
#初始化停车场数据
car_park = []
#记录车辆入场停车,车牌和时间
def veh_enter():
print('欢迎进入AAA停车场')
plate = input('请输入车牌号:').strip()
#构建结构{'车牌':[0,5]}
car = {}
car[plate] = [0]
#添加到car_park
car_park.append(car)
print(f'欢迎{plate}入场停车!')
#记录车辆出场,车牌和时间
def veh_exit():
#出场扫描
plate = input('请输入车牌号:').strip()
#判断此车是否有入场记录
for car in car_park:
if plate in car:
#记录出场时间
time = random.randint(0,24)
time_record = car.get(plate)
time_record.append(time)
#计算费用,退出循环
total = time * 4
print(f'{plate}停车{time}小时,应缴费:{total}元')
break
else:
print(f'{plate}没有入场记录!')
#调用
veh_enter()
veh_exit()
6.4 闭包
函数只是一段可执行代码,编译后就固化了,每个函数在内存中只有一份实例,得到函数入口点便可执行。函数还可以嵌套函数,即函数内部可以定义另一个函数,这就会产生闭包的问题。
'''
函数嵌套:
变量查找顺序:内层函数 --> 外层函数 --> 全局 --> 系统 builtins
闭包:
1,是嵌套函数
2,内部函数引用了外部函数变量
3,返回值是内部函数
'''
#嵌套
def outer():
a = 100
def inner():
b = 200
# b += a #内部函数可以使用外部函数的变量,但是不能改变外部变量
#如果想修改外部变量,需要在内部函数中加上: nonlocal
nonlocal a
a += b #内部函数不能改变外部变量
print('这是内部函数',b)
result = locals() #locals()表示查看函数中的局部变量,以字典形式返回
print(result) #{'a': 100, 'inner': <function outer.<locals>.inner at 0x000001E39698E730>}
#调用inner
inner() #这是内部函数 300
#函数调用
outer()
#闭包 = 函数块 + 引用环境
def outer1(n):
a = 10
def inner():
b = a + n
print('内部函数:',b)
return inner
r = outer1(5)
print(r) #<function outer1.<locals>.inner at 0x0000020177D0E7B8>
r() #内部函数: 15
6.5 装饰器
6.5.1 装饰器基础
'''
装饰器:
遵循开放封闭原则,在不改变原函数的情况下,扩展了函数功能
定义:
def xxx(func):
def xxx():
...
func()
...
return xxx
return yyy
装饰:
@装饰器名 #原函数 = 装饰器名(原函数)
def 原函数():
pass
功能:
1,引入日志
2,函数执行时间统计
3,执行函数前的预备处理
4,执行函数后的清理功能
5,权限校验等场景
6,缓存
'''
#定义一个装饰器
def decorator(func):
print('------------->1')
def wraper():
func() # 先执行外部函数 house
print('刷漆')
print('铺地板')
print('软装')
print('精装房')
print('------------->2')
return wraper
@decorator #开始调用decorator,house = decorator(house) 先执行打印 ------------->1 ------------->2
def house(): #将house作为变量传入,类似 func = house
print('毛坯房')
#调用函数
house()
'''
执行结果:
------------->1
------------->2
毛坯房
刷漆
铺地板
软装
精装房
'''
6.5.2 带参数的装饰器
'''
带参数的装饰器:
如果原函数有参数,装饰器内部也要有参数
'''
#定义一个装饰器,*args,**kwargs 可以接任意变量
def decorator(func):
def wraper(*args,**kwargs): #address = ’北京‘,*args是一个元组
func(*args,**kwargs) # func 就是 house
print('刷漆')
print('铺地板')
print('软装')
print('精装房')
return wraper
@decorator #开始调用decorator
def house(address): #将house作为变量传入,类似 func = house
print(f'位于{address}的毛坯房')
@decorator #开始调用decorator
def workplace(address,area):
print(f'位于{address}的毛坯房,面积{area}平米')
@decorator #开始调用decorator
def hotel(name,address,area=40):
print(f'{name}酒店,位于{address}的毛坯房,单间面积{area}平米')
#调用函数
house('北京') # house 就是 wraper
workplace("北京通州",1000)
hotel('全季',address='北京') #如果没有**kwargs 运行会报错
6.5.2 带返回值的装饰器
'''
装饰器修饰有返回值的函数:
原函数有返回值,装饰器内部函数也需要返回值
'''
#定义一个装饰器,*args,**kwargs 可以接任意变量
def decorator(func):
def wraper(*args,**kwargs): #address = ’北京‘,*args是一个元组
r = func(*args,**kwargs) # func 就是 house
print(f'预计费用是:{r}元')
print('刷漆')
print('铺地板')
print('软装')
print('精装房')
return 60000 # 原函数有返回值,wrapper也需要返回值
return wraper
@decorator #开始调用decorator
def house(address): #将house作为变量传入,类似 func = house
print(f'位于{address}的毛坯房')
return 50000
#调用函数
house('北京') # house 就是 wraper
6.6 递归函数
如果一个函数在内部不调用其他任何函数,而是自己本身的话,这个函数就是递归函数。
'''
如果一个函数在内部不调用其他任何函数,而是自己本身的话,这个函数就是递归函数
遵循:
1,必须要有出口
2,每次递归,要向出口靠近
'''
#
def test():
print('----------test-----------')
# 调用a()
a()
def a():
print('----------aaaa-----------')
#调用a()
a()
# 调用a()
# a()
#打印数字1-10,递归函数实现
def num(i):
if i == 10:
print(i)
else:
print(i)
i += 1
num(i)
#调用num(),从1开始
# num(1)
#数字1-10的累加和,递归函数实现
total = 0
def sum(i):
global total
if i == 11:
print('over',total)
else:
total += i
i += 1
sum(i)
#使用返回值求累加
def sum1(i):
if i == 10:
return 10
else:
return i + sum1(i+1) # 逐层向下递归,但是到最后i=10之后才有返回,然后再逐层返回值进行计算
#调用sum(),从1开始
# sum(1)
r = sum1(1)
print(r)
6.7 匿名函数
6.7.1 匿名函数定义
'''
用lamda关键词可以创建小型匿名函数,省略了def声明函数的标准步骤
匿名函数定义格式:
lamda 参数列表:返回值表达式
'''
#定义标准函数
def test(a):
return a+1
#使用变量来接收函数返回值
result = test(5)
print(result)
#定义匿名函数,由于没有函数名,使用r来接收
r = lambda a:a+1
result = r(6)
print(result)
#定义匿名函数,多个参数
r = lambda x,y: x+y
result = r(6,7)
print(result)
6.7.2 匿名函数的使用场合
'''
匿名函数的使用场合:
匿名函数作为参数来使用
'''
#定义标准函数
def test():
print('------test------')
def func(a,f):
print('--------->',a)
f()
#使用变量来接收函数返回值
func(5,test)
def func1(a,f): #lambda x:x**2
print('>>>>>>>>>>',a)
r = f(a)
print('=====>',r)
#调用func1,因为f带返回值,这里用匿名函数来赋值,多数情况,匿名函数放在参数位置
func1(8,lambda x:x**2)
6.8 高阶函数
函数可以作为变量来使用。既然变量可以指向函数, 函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数。同样,可以把一个函数作为另一个函数的返回值。这种函数的使用方式,称之为高阶函数。
'''
高阶函数:
一个函数的参数是另一个函数
系统高阶函数:
max,min,sorted, filter,map,reduce
'''
#普通查找最大值
from functools import reduce
m = max(5,6)
print(m)
#列表内查找最大值
m = max([2,5,8,3,11,56,39,22])
print(m)
#匿名函数,找最大年龄
list1 = [('Lily',25),('Tony',19),('Jessy',21),('Tomas',28),('Lucy',26),('Rose',29)]
m = max(list1,key= lambda x:x[1])
print(m)
#找最小年龄
m = min(list1,key= lambda x:x[1])
print(m)
#按年龄排序
m = sorted(list1,key= lambda x:x[1])
print(m) #[('Tony', 19), ('Jessy', 21), ('Lily', 25), ('Lucy', 26), ('Tomas', 28), ('Rose', 29)]
#按年龄排序,倒序
m = sorted(list1,key= lambda x:x[1],reverse=True)
print(m) #[('Rose', 29), ('Tomas', 28), ('Lucy', 26), ('Lily', 25), ('Jessy', 21), ('Tony', 19)]
#过滤 大于20岁的,lambda 返回值是真或假,返回值必须是bool类型,结果为True才符合过滤条件
m = filter(lambda x:x[1]>20,list1)
print(m) #<filter object at 0x0000020A2EDED748>, 返回的是可迭代对象
#将m强转为list
print(list(m)) #[('Lily', 25), ('Jessy', 21), ('Tomas', 28), ('Lucy', 26), ('Rose', 29)]
#映射map,通过匿名函数指明提取内容,并对内容进行加工
ma = map(lambda x:x[1]+1,list1)
print(ma) #<map object at 0x000001FF6FCEE710>
print(list(ma)) #[26, 20, 22, 29, 27, 30]
ma = map(lambda x:x[0].title(),list1)
print(ma) #<map object at 0x0000013E7233E860>
print(list(ma)) #['Lily', 'Tony', 'Jessy', 'Tomas', 'Lucy', 'Rose']
#reduce,对一个序列进行压缩运算,最后得到一个值
r = reduce(lambda x,y:x+y,[1,2,3,4,5])
print(r) #15
***************用努力照亮现实的梦!***********************
本文来自博客园,作者:逆流的鱼2016,转载请注明原文链接:https://www.cnblogs.com/orange2016/p/16417375.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)