1 函数基础
函数的定义和调用
定义函数
格式:def 函数名():
函数体
函数体:封装重复内容
def test():
pass
def test(参数):
pass
函数调用
验证函数是否可用
格式:函数名()
'''
函数定义练习--->生成验证码
'''
import random
def generate_code():
s = 'hjfdhajkgUHFSG89GUYGfhtyGYUGFSHGFDS5981334'
code = ' '
for i in range(4):
r = random.choice(s)
code += r
print(code)
generate_code()#函数调用
函数的参数(默认无参数)
参数是外界向函数中传值的过程
一个参数
格式:def 函数名(参数):
函数体
调用:函数名(参数)
#练习1:随机生成n位验证码
import random
def generate_code(n):
s = 'hjfdhajkgUHFSG89GUYGfhtyGYUGFSHGFDS5981334'
code = ' '
for i in range(n):
r = random.choice(s)
code += r
print(code)
generate_code(5)#函数调用
#定义一个登录函数,验证是否正确,用户名:admin 密码:1234。最多输入三次
def login(n):
for i in range(n):
username = input('用户名:')
password = input('密码:')
if username == 'admin' and password == '1234':
print('用户登录成功!')
break
else:
print('用户登录失败!')
print('超出输入次数!账号被锁定!')
login(3)
#求1-n的累加和
def cumulative_sum(n): # cumulative_sum:累加和
sum = 0
for i in range(n):
sum += i
print(sum)
cumulative_sum(10)
多个参数
格式:def 函数名(参数1,参数2,参数3)
函数体
调用:函数名(参数1,参数2,参数3)
def get_sum(a, b):
s = a + b
print(s)
get_sum(2, 3)
get_sum('hello', 'world')
#get_sum('2', 3) # 报错,,类型不一致
'''
1.判断用户是否登录成功
判断用户是否登录成功,是否记住密码
'''
# 练习1
def islogin(username, password):
if username == 'admin' and password == '1234':
print('登录成功')
else:
print('登录失败')
islogin('admin', '1234')
# 练习2
def islogin(username, password,isrember=False):#可以给某个值赋默认值
if username == 'admin' and password == '1234':
print('登录成功')
else:
print('登录失败')
islogin('admin', '1234')
默认值参数
格式:def 函数名(参数1,参数2,参数3=值)
函数体
'''
默认值参数练习
1.借书系统
2.打车程序:
'''
def borrow_book(bookname, number=1, school='北京大学'):
print('要借阅的书名是:{},借阅数量是:{},学校是:{}'.format(bookname, number, school))
borrow_book('狂人日记')
borrow_book('狂人日记', 3)
borrow_book('狂人日记', school='清华大学')
普通参数要放在默认值参数的前面
默认参数的顺序是固定的,可以通过关键字来赋值
调用:函数名(值1,值2) ---->值3为定义中默认值
函数名(值1,值2,值3)---->值3会替换定义中的值
可变参数:
可变参数 *args
def get_sum(*a):
print(a)
get_sum(1, 3) # 结果为元组(1, 3)
# 对应小练习--- 结论 : 谁加*谁接受剩余部分
a, *b, c = 1, 2, 3, 4, 5
print(a) # 1
print(b) # [2, 3, 4]
print(c) # 5
a, b, *c = 1, 2, 3, 4, 5
print(a) # 1
print(b) # 2
print(c) # [3, 4, 5]
# 可变参数求和:
def get_sum(*args):
s = 0
for i in args:
s += i
print('和:{}'.format(s))
get_sum(1, 2, 6) # 和:9
get_sum(3, 5) # 和:8
关键字参数:**kwargs
def show_book(**kwargs):
print(kwargs)
show_book() # {}
# 2.key word --->关键字,,结果是键值对
def show_book(**kwargs):
print(kwargs)
show_book(bookname='洗衣机', author='fds', number=5)
在函数调用时必须传递关键字参数,才可以将其转换为key:value
装到字典中
# *args **kwargs两个混用
def show_book(*args, **kwargs):
print(args) # ()
print(kwargs) # {}
show_book()
show_book('小反射光', 'df')
print('*' * 20)
book = {'bookname': '红楼梦', 'author': '曹雪芹', 'number': 5}
show_book('小反射光', 'df', **book)
函数的返回值(return)
参数:外界往里传值
返回值:里面的内容往外界送值
格式: def 函数名(*args)
.....
.....
return xxx
r=函数名(参数1,参数1,..)
print(r)
def get_sum(*args):
total = 0
for i in args:
total += i
# 将total返回
print('内测T:', total)
return total
t = get_sum(1, 2, 3) # 变量接收return出来的值
print('外侧T:', t)
x = 100
x = x + t
print(x)
# 多个返回值
def get_maxandmin(numbers):
# 先排序,,冒泡排序
for i in range(0, 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 # 将两个值装在一个元组里
list1 = [32, 56, 84, 36, 42, 16, 82, 17, 16]
result = get_maxandmin(list1)
print(result)
注意:1.只要函数有返回值,需要有变量来接收
2.return后面的值可以为多个,若是多个值,类似:return z,b,c
函数的嵌套
可变与不可变变量
判断依据:值变地址是否发生改变
不可变(加global):当该变变量的值时,地址发生了改变
类型:int str float bool tuple
可变(不加):里面内容发生改变,但是地址没有发生改变
类型:list dict set
# 1.不可变,, 两者地址不一样
a=2.1
print(id(a))
a=2.2
print(id(a))
# 1.1元组
t1=(1,2,3)
print(id(t1))
t2=(3,1,2)
print(id(t2))
# #2.可变。。。列表---->内容发生改变,而内容没有发生改变
list1 = [1, 2, 3]
print(id(list1))
list1.append(4)
print(id(list1))
全局变量和局部变量
global 关键字的添加:
只有不可变的类型才需要添加global
全局变量:声明在函数外面的称为全局变量
局部变量:声明在函数内部的变量,称为局部变量
函数内部可以直接使用全局变量,但是不能直接修改全局变量,如果想要修改全局变量,则需要使用关键字:global 变量名
a = 100
def test1():
# 局部变量--->会被收走
a = 0
b = 8
print('a=', a)
print('b=', b)
print('*'*30)
def test2():
b = 6
print('a=', a) # 引用全局变量
print('b=', b) # --->局部变量的作用只限于函数内部
print('*'*20)
def test3():
# 改变全局变量a的值---》通过关键字global
# a-=10 #没有权限,报错
global a#---->表示要用全局a
a -= 2
print('a=', a)
test3()#先调用3会改变全局变量的值,故后面的1.2为改变后面的值
test1()
test2()
# test3()
总结
def func():
a=90
a+=x
print('***',a)
x=100
func()
print(globals())#查看全局变量
嵌套搜索规则:
内层函数----》外层函数----》全局——————》系统builtins
#1.1
def outer():
a=100 #---->变量
def inner():#---->变量
b=200
# b+=a#内部函数可以使用外部变量,不能修改
nonlocal a #表示引用内部函数外部的函数,可以修改
a+=b#不能修改,只能修改自己的
print('我是内部函数',b)
# result=locals()#locals()---->表示查看函数中的局部变量,以字典的形式返回
# print(result)
print(a)
# print(inner)
#调用Inner
inner()
outer()
# 1.2
a=100
def outer():
a=200
def inner():
a=300
print('内部函数:',a)
a-=50
print(a) #当调用outer()时,1.会先执行,==200
inner()# 当调用inner()时,2再执行 内部函数: 300
outer()
print(a)#函数全部执行完,,打印全局变量 100
函数的文档注释
格式:def 函数名(参数1,。。。)
基本注释 :”注释内容“
高级注释:''' '''
def login(username,password):
'''
:param username:
:param password:
:return:
'''
if username=='admin'and password=='1234':
print('登录成功')
return True
else:
print('输入有误!')
return False
login('admin','1234')
函数的引用
定义:检测某个变量有多少个指针指向(获取引用个数)
格式:sys.getrefcount(变量)
参数的值传递:可变 不可变类型
def 变量 ---->表示删除了一个引用
# #1.1
import sys
#reference
a=10
print(sys.getrefcount(a))
list1=[1,2,3,4,5]
list2=list1#将一的地址给二,,,将引用地址赋值
list3=list1
print(sys.getrefcount(list1))# 4 ,list1所指向的空间有多少个引用他
del list3
print(sys.getrefcount(list1))#3
# 1.2参数的值传递
def test(n1):#n是一个数值 n1=n
#n1是函数的一个局部变量
for i in range(n):
print('---->', i)
n1+= 1
n = 9#全局变量
test(n)
print(n)
注意:
如果可变类型---->里面发生改变,外层就能看到改变后的内容
如果不可变----->里面发生改变,不会影响外面的变量值
2 递归函数
定义:如果一个函数在内部不调用其他函数,而是自己本身的话,这个函数就是递归函数
# 用递归实现1-10循环,,,1-10 打印数字
def test(i):
if i == 10:
print('10')
else:
print(i)
i += 1
test(i)
test(1)
#1-10的累加和
def test1(i):
if i==10:
return 10
else:
return i+test1(i+1)
r=test1(1)
print(r)
# # 练习
def test(a,b):
print('打印输出')
return a + b
def func():
c = 10
return c + test(5, 8)#先调用再运算,有结果才往外扔
t=func()
print(t)
#求阶乘
def test1(i):
if i==4:
return 4
else:
return i*test1(i+1)
r=test1(1)
print(r)
# 循环写阶乘
def cal(num):
result, i = 1, 1
while i <= num:
result *= i
i += 1
return result
print(cal(3))
遵循原则:
必须要有出口;每次递归要向出口靠近
3 匿名函数
格式:lambda 参数:返回值
#普通函数
def test(a):
return a + 1
# print(test)
result=test(5)
print(result)
print('------')
#匿名函数
r = lambda a: a + 1
result=r(5)
print(result)
#匿名带两个参数
print('-----')
r=lambda x,y:x+y# 格式 参数:返回值
result=r(1,2)
print(result)
用lambda关键词能创建小型匿名函数
lambda 参数列表:运算表达式
lambda函数能接收任何数量的参数但只能返回一个表达式的值
使用场景:匿名函数在函数中作为一个参数使用
匿名参数作为参数使用
def test():
print('----test----')
def func(a,f):
print('---->',a)
f()
func(5,test)
print('--------')
def func1(a,f):#f=lambda x:x**2
print('++++++>',a)
r=f(a)#调用f函数,a相当于x
print('*********>r')
也称为高阶函数
func1(8,lambda x:x**2)#调用func1函数,8给a,匿名函数给赋值
4 高阶函数
定义:一个函数的参数是另一个函数
系统的高阶函数:max min sorted
# 1.
m = max(5, 9)
print(m)
m = max[2, 4, 67, 8, 9]
print(m)
list1 = [('tom', 19), ('tony', 20)('rose', 52)]
m = max(list1, key=lambda x: x[1])
print(m)
mi=min(list1,key=lambda x:x[1])
print(mi)
sorted(list1,key=lambda x:x[1],reverse=True)
print(m)
filter返回值为布尔类型,只有bool类型条件为真才是符合过滤条件
list1 = [('tom', 19), ('tony', 20), ('rose', 52)]
#filter返回值为布尔类型,只有bool类型条件为真才是符合过滤条件
rr=filter(lambda x:x[1]>20,list1)#取出一堆数,放在x中,看:后面值是否为真,就放在后面。。。Filter通过lambda返回值的真假过滤想要的条件
print(list(rr))
#上面等价
list1=[]
for i in list1:
if i[1]>20:
list1.append(i)
map()映射---->通过匿名函数指明提取的内容,并对内容进行加工
# 3.map()映射---->通过匿名函数指明提取的内容,并对内容进行加工
ma = map(lambda x: x[0].title(), list1)
print(list(ma))#提取某值 [20, 21, 53] ['Tom', 'Tony', 'Rose']
reduce()----->格式 reduce(lambda x,y:x+y,[1,2,3,4,5])
4.reduce()----->格式 reduce(lambda x,y:x+y,[1,2,3,4,5]) 提取出1和二 进行计算,如何将得到值赋给x,在继续
r = reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
print(r)
5 闭包
闭包(主要用在装饰器上)与嵌套类似
满足要求:
嵌套函数
内部函数引用了外部函数的变量
返回值是内部函数
# 1.1.2
a = 100
def outer():
a = 200
def inner():
# a = 300
# global a#出错ame 'a' is assigned to before global declaration
nonlocal a#用的是局部变量
a -= 50
print('内部函数:', a)
print(a) # 当调用outer()时,1.会先执行,==200
inner() # 当调用inner()时,2再执行 内部函数: 300
outer()
print(a) # 函数全部执行完,,打印全局变量 100
# 1.2闭包
def outer(n):
a=10
def inner():
b=a+n
print('内部函数:',b)
return inner
r=outer(5)
print(r)
r()
6 装饰器
定义:遵循开放封闭原则,在不改变原函数内容情况下,开展了函数的功能
格式:def xxx(func):
def xxx():
....
func()
...
return yyy
return xxx
@装饰器名 ----->原函数=装饰(原函数)
def 原函数()
# 定义一个装饰器,,与闭包类似
def decorater(func):
print('----->1')
def wrapper():
func()#在执行func()时优先执行下面house内容
print('刷漆')
print('地板')
print('买家具')
print('精装修房子')
print('----->2')
return wrapper
# # decorater() #等价于 house=decorater(house)
@decorater #在函数中用装饰器,,,也表示调用
# house=wrapper
def house():
print('毛坯房。。。')
house()
@decorater
def xxx():
print('hjdh')
house()
使用场景:日志功能、函数执行时间、执行函数前预备处理、执行函数后清理功能、权限校验等场景、缓存
参数类型:
带参数的装饰器:
如果原函数有参数,装饰器内部函数也需有参数
# 2.装修确定地址的房子
def decorater(func):
# def wrapper(*args):#address='北京四合院'
# #args是一个元组
# func(*args)#func就是house #1.2使用
#关键字参数装饰----》万能装饰器
def wrapper(*args,**kwargs): # address='北京四合院'
# args是一个元组
func(*args,**kwargs) # func就是house
print('刷漆')
print('铺地板')
print('买家具')
print('精装修房子')
return wrapper
#1.---1个参数
@decorater
def house(address):
print('房子的地址在:{}是一个毛坯房...'.format(address))
house('北京四合院')#house就是wrapper
print('---------')
#2.--两个参数---->
@decorater
def changfang(address,area):
print('房子的地址在:{},房子的买哪家是:{}平方米'.format(address,area))
changfang('北京大方','5')
#3.万能装饰器-->有无参数混合
print('---------')
@decorater
def hotel(name,address,area=40):
print('酒店的名字是:{},酒店的地址在:{},是一个毛坯房,单间建筑面积是:{}平米'.format(name,address,area))
hotel('四季酒店','岐山')
装饰器修饰有返回值的函数
原函数有返回值,装饰器的内部函数也要有返回值
def decorater(func):
def wrapper(*args,**kwargs):
r=func(*args,**kwargs)
print('预计装修费用:{}元'.format(r))
print('刷漆')
print('铺地板')
print('买家具')
print('精装修房子')
return r #根据需求
return wrapper
@decorater
def house():
print('我是一个毛坯房...')
return 50000 #要装修的费用
r=house()#r接收return内容....#house==wrapper
print(r)
装饰器带参数
def outer_check(time):
print('------->1')
def check_time(action):
print('-------->2')
def do_action():
if time < 22:
return action()
else:
return '对不起,您不具有该权限'
print('------->3')
return do_action
print('-------->4')
return check_time
@outer_check(23)
def play_game():
return '玩游戏'
6 函数综合练习
'''
小练习---
定义一个出租车打车程序,参数:手机号码,起步价:10元
函数体中输入乘车时间和里程数,2公里内起步价就ok
超出2公里每公里5元,乘车时间每分钟0.5元
下车打印总账单
'''
def dache(phone_number, basic_price=10):
time = int(input('乘车时间(min):'))
distance = float(input('输入乘车距离(km):'))
if distance <= 2:
price = 10
else:
price = 10 + (distance - 2) * 5
price1 = 0.5 * time
total = price1 + price
print('乘客{}:乘车{}分钟,距离{}公里,总费用{}元'.format(phone_number, time, distance, total))
dache('1254632578')
'''
小练习---
获取列表中中大于50的数并打印
'''
# 方式一
list1 = [12, 45, 464, 46, 84, 32, 46, ]
def get_list(list1):
new_list = []
for i in list1:
if i >= 50:
new_list.append(i)
print(new_list)
get_list(list1)
# 方式2--列表推导式
list1 = [12, 45, 464, 46, 84, 32, 46, ]
def get_list(list1):
new_list = [i for i in list1 if i >= 50]
print(new_list)
get_list(list1)
# #删除列表中小于50的数
def remove_from_list(list1):
for i in list1:
if i <= 50:
list1.remove(i)
print(list1)
remove_from_list(list1)
# 正确----》删除小于50
def remove_from_list(list1):
n = 0
while n < len(list1):
if list1[n] < 50:
list1.remove(list1[n])
else:
n += 1
print(list1)
remove_from_list(list1) # [464, 84]
'''练习----
借书:borrow_book
参数:书名
函数体:
判断是否登录,如果登录则可以借书
如果没有登录则提示:还没有登录不能借书'''
islogin=False
def login(username,password):
if username=='admin'and password=='1234':
print('登录成功!')
global islogin
islogin=True
else:
print('登录失败!')
islogin=False
def borrow_books(book_name):
if islogin:
print('成功借阅{}'.format(book_name))
else:
print('用户还没有登录,不能借书!')
username=input('用户名:')
password=input('密码:')
login(username,password)
borrow_books('草房子')
borrow_books('草房子')
'''
停车计费系统
进入停车场记录进入时间,如果出去则记录出去时间,停车时间是:出去时间-进入时间
停车场的数据结构是:
[{'车牌':[进入时间,0]},{’车牌‘:[进入时间,出去时间]}...]
15分钟 1快
1小时4快
停车场变量---->全局变量
def enter():
#键盘输入车牌
pass
def go_out():
#键盘输入车牌
pass
'''
import random
car_park = []
def enter():
print('欢迎进入xxx停车场!')
number = input('输入进场车牌号码:')
# 构建结构{'车牌':[进入时间,0]}
car = {}
car[number] = [0]
# 添加到car_park
car_park.append(car)
print('{}已进场'.format(number))
def go_out():
number = input('输入出场车牌号码:')
# 判断汽车是否进场
for car in car_park:
if number in car:
# 记录结束时间
time=random.randint(0,24)
#保留停车记录
time_record=car.get(number)
time_record.append(time)
#计算花费
total=time*4
print('{}停车{}小时,应缴费:{}元'.format(number,time,total))
break
else:
print('此车未进场')
print('')
enter()
enter()
enter()
go_out()