python学习日记
装饰器:不修改函数的调用方式,但是还在原来的函数基础上添加功能
原则:开放封闭原则
开放:对拓展是开放的
封闭:对修改是封闭的
基础格式
举例:
from functools import wraps #引入别人写好的装饰器
def wrapper(f):
@wraps(f) #这个装饰器不会再改原来函数的名字
def inner(*args,**kwargs): #定义*args和**kwargs可以输入元组字典
print('装饰函数之前做的事')
ret = f(*args,**kwargs)
print('装饰函数之后做的事')
return ret
return inner
@wrapper
def holiday(day):
print('全体放假%s天'%day)
return '开心'
ret = holiday(3)
print(ret)
#打印装饰器的函数
print(holiday.__name__)
装饰器作业题:
1、编写装饰器,位多个函数加上认证的功能(用户的账号密码来源于文件)
#要求登录成功一次,后续的函数都无需再输入用户名和密码
from functools import wraps
flag = False
def login(func):
@wraps(func)
def inner(*args,**kwargs):
global flag
'''登陆程序'''
if flag:
ret = func(*args, **kwargs)
print('登陆成功')
return ret
else:
username = input('username:')
password = input('password:')
if username == 'boss_gold' and password == '123':
flag = True
ret = func(*args,**kwargs)
print('登陆成功')
return ret
else:
print('登陆失败')
return inner
@login
def shoplist_add():
print('增加一件物品')
@login
def shoplist_del():
print('删除一件物品')
shoplist_add()
shoplist_del()
2、编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都被调用的函数名称写入文件
def log(func):
def inner(*args,**kwargs):
with open('log','a',encoding='utf-8') as f:
f.write(func.__name__+'\n')
ret = func(*args,**kwargs)
return ret
return inner
@log
def shoplist_add():
print('增加一件物品')
@log
def shoplist_del():
print('删除一件物品')
shoplist_add()
shoplist_add()
shoplist_add()
shoplist_add()
shoplist_del()
shoplist_del()
带参数的装饰器
三层装饰器
import time
FLAGE = True
def timmer_out(flag):
def timmer(func):
def inner(*args,**kwargs):
if flag:
start = time.time()
ret = func(*args,**kwargs)
end = time.time()
print(end - start)
return set
else:
ret = func(*args, **kwargs)
return set
return inner
return timmer
@timmer_out(FLAGE)
def wahaha(a):
time.sleep(a)
print('aaaa')
@timmer_out(FLAGE)
def erguotou(a):
time.sleep(a)
print('eeeee')
wahaha(0.1)
erguotou(0.2)
语法糖:@装饰器函数名 后紧接被装饰的函数
迭代器
tips :print(dir([])) 可以告诉我列表拥有的所有方法pycharm
只要含有__iter__方法的都是可迭代的
迭代器的好处:
从容器类型中一个一个的取值,会把所有的值都取到。
节省内存空间
迭代器并不会在内存中再占用一大块内存,
而是随着循环 每次生成一个
每次next每次给我一个
Iterable 可迭代的 – > iter #只要含有__iter__方法的都是可迭代的
[].iter() 迭代器 – > next #通过next就可以从迭代器中一个一个的取值
迭代器协议和可迭代协议
可以被for循环的都是可迭代的
可迭代的内部都有__iter__方法
只要是迭代器 一定可迭代
可迭代的.iter()方法就可以得到一个迭代器
迭代器中的__next__()方法可以一个一个的获取值
from collections import Iterable
from collections import Iterator
print(isinstance([],Iterator)) #利用isintance判断列表是不是迭代器
print(isinstance([],Iterable))
for
只有 是可迭代对象的时候 才能用for
当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代
生成器:自己写的迭代器
只要含有yeild关键字的函数都是生成器函数
且yeild不能和return共用
def generater():
print(1)
yield 'a'
print(2)
yield 'b'
#生成器函数:执行之后会得到一个生成器作为返回值
ret = generater()
for i in ret:
print(i)
# print(ret)
# print(ret.__next__())
# print(ret.__next__())
# 从生成器中取值的几个方法
# next
# for
# 数据类型的强制转换 : 占用内存
g = generator() #调用生成器函数得到一个生成器
print(list(g)) #数据类型的强制转换,变成list
ret = g.__next__() #每一次执行g.__next__就是从生成器中取值,预示着生成器函数中的代码继续执行
print(ret)
num = 0
for i in g:
num += 1
if num > 50:
break
print(i)
生成器:send
send 获取下一个值的效果和next基本一致
只是在获取下一个值的时候,给上一个yield的位置传递一个数据
使用send的注意事项:
第一次使用生成器是是用next获取下一个值
最后一个yield不能接受外部的值
例子:求移动平均值
带装饰器的生成器
def init(func): #装饰器
def inner(*args,**kwargs):
f = func(*args,**kwargs)
f.__next__()
return f
return inner
@init
def average(): #生成器
sum = 0
count = 0
avg = 0
while True:
num = yield avg
sum += num
count += 1
avg = sum/count
avg_g = average()
# avg_g.__next__()
avg1 = avg_g.send(10)
print(avg1)
avg1 = avg_g.send(20)
print(avg1)
avg1 = avg_g.send(30)
print(avg1)
avg1 = avg_g.send(40)
print(avg1)
avg1 = avg_g.send(50)
print(avg1)
avg1 = avg_g.send(60)
print(avg1)
python3 中带有一个新的生成器语法form
from:返回a,b中的每一个字符
def gen():
a = 'abfda'
b = '2312rfde3'
yield from a
yield from b
g = gen()
for i in g:
print(i)
鸡蛋列表 列表推导式
公式 + for i in rang(10
egg_list = ['鸡蛋%s' %i for i in range(10)] #列表推导式
print(egg_list)
#用正常的for循环实现鸡蛋列表
egg_list = []
for i in range(10):
egg_list.append('鸡蛋%s' %i)
print(egg_list)
生成器表达式
与列表表达式的区别是:括号不一样,返回的值不一样----->几乎不占内存
g = (i for i in range(10))
print(g)
for i in g:
print(i)