装饰器
装饰器:本质是函数
功能:为其他函数添加附加功能。(为房子装饰)
原则:
- 不能修改被装饰函数的源代码
- 被装饰函数的调用方式不能被修改
实现装饰器的知识储备:
1.函数即"变量",函数名即为'门牌号'(类似变量名),函数体即为变量内容。del可删除门牌号,若没有门牌号指向函数体函数体即被清空。
2.高阶函数:满足下列条件之一:
a.把一个函数名当作实参传给另外一个函数(在不修改被装饰函数的源代码情况下为其添加新功能。
b.返回值中包含函数名(不修改函数的调用方式)
3.嵌套函数
高阶函数+嵌套函数=》装饰器
#希望实现的目标:给test1
import time
def timmer(func):
def warpper(*args,**kwargs):
start_time = time.time()
func()
stop_time=time.time()
print('the func run time is %s'%(stop_time-start_time))
return warpper()
@timmer
def test1():
time.sleep(3)#代表函数运行逻辑所花费的时间
print('in the test1')
test1()
pass
装饰器应用实例->登陆系统
user,passwd = 'negu','negu0'
def auth(auth_type):
print('auth func:',auth_type)
def outer_wrapper(func):
def wrapper(*args,**kwargs):
if auth_type == 'local':
username = input('user:\t').strip()
password = input('password:\t').strip()
if user == username and passwd == password:
print('\033[32;1m User has passed authentication \033[0m')
func(*args,**kwargs)
else:
exit('\033[31;1minvalid username or password\033[0m')
#return 'from home'
elif auth_type == 'ldap':
print('ldap')
return wrapper
return outer_wrapper
def index():
print('welcome to index page.')
@auth(auth_type = 'local')#home = wrapper(),加上括号以后会提前执行wrapper
def home():
print('welcome to home page.')
return 'from home'#用装饰器以后没有输出任何值,要在装饰器内部给func赋值才有。
@auth(auth_type = 'ldap')
def bbs():
print('welcome to bbs page.')
index()
print(home())
bbs()
迭代
列表生成式、生成器
p = [i*2 for i in range(10) ]
print(p)
等价于
for i in range(10):
print i*2
通过列表生成式,可以直接创建一个列表。但内存受限制,列表容量有限。,而且创建一个包含100W个元素的列表,不仅占用很大空间,如果仅仅访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以如果列表可以按照某种算法推算出来那我们可以在循环过程中不断推算算出后面的元素,这样不必创建完整的列表,从而节省大量的空间。在py中,这种 一边循环一边计算的机制称为生成器。(generator)
g = (i*2 for i in range(10))#用生成器生成100W个元素一般感觉不到任何延迟而生成式会有延迟,因为执行命令的时候根本没有生成,除非调用才生成。
print(1,g.__next__()) #输出0,一般不能调用g[5]之类的因为还没生成,一般只能用循环去取值。
print(2,g.__next__()) #输出2
print(3,g.__next__()) #输出4
for i in g:#它的调用方式多次的:g.__next__(唯一方法),生成器省内存的方法:只保留当前循环的位置的数据,不知前后数据。只能用for循环调用。
print(i)
生成器应用实例
import time
def consumer(name):
print("%s 准备吃包子啦!" %name)
while True:
baozi = yield#第一句为negu准备吃包子啦!,可见yield为一个断点。
print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
# c = consumer('negu')#如果是consumer是函数这样赋值直接执行函数,而genrator不会执行。
# c.__next__()
# b1 = '韭菜馅'
# c.send(b1)#出现这个send将会默认执行一次c.__next__,并给yield赋值。
# #c.__next__()
def producer(name):
c = consumer('A')
c2 = consumer('B')
c.__next__()#相当于打印print('xx开始准备吃包子啦')
c2.__next__()
print("老子开始准备做包子啦!")
for i in range(2):
time.sleep(1)
print("%s做了2个包子!"%name)
c.send(i)
c2.send(i)
producer("negu")#这个程序同时执行三个任务,顾客1,顾客2吃包子,negu做包子。
输出:
A 准备吃包子啦!
B 准备吃包子啦!
老子开始准备做包子啦!
negu做了2个包子!
包子[0]来了,被[A]吃了!
包子[0]来了,被[B]吃了!
negu做了2个包子!
包子[1]来了,被[A]吃了!
包子[1]来了,被[B]吃了!
可迭代对象、迭代器
可直接用于for循环的数据类型:str,tuple,list,dict,set,文件句柄。
可直接用于for循环还有一个就是生成器generator和带yield的function。
可用于for循环的变量对象称为可迭代对象(iterable)
可以用collection中的iterable类、以及内置isinstance来判断是否是可迭代对象。
from collections import Iterable
print('元组',isinstance((1,2,3),Iterable))#true
print('列表',isinstance([1,2,3],Iterable))#true
print('字典',isinstance({1,2,3},Iterable))#true
print('字符串',isinstance('1,2,3',Iterable))#true
print('集合',isinstance(set([1,2,3]),Iterable))#true
#通过内置函数iter()可以把dict、list、tuple变成迭代器对象。
为什么list、tuple、dict不是个iterator????:因为python的iterator表示的是一个数据流,iterator对象可以被next()函数调用。
可以把这个数据流看成一个有序的序列,但我们不能提前知道序列长度,只能通过不断的next()计算下一个数据,所以iterator是惰性的。只有需要返回下一个数据的时候才会计算而元组、列表等变量是储存在内存中可以随时提取的。
在python3中range()函数就是一个迭代器
for i in range (10):
[代码命令]
等价于
it = iter([1,2,3,4,5,6,7,8,9,10])
while True :
try :
i = it.__next__
[代码命令]
except StopIteration:
break