Python初识 - day5
一、装饰器(decorator)
1.定义:本质是函数(装饰其它函数),就是为了其它函数添加附加功能。
2.原则:一是不能修改被装饰函数的源代码;二是不能修改被装饰函数的调用方式。
3.装饰器包含的知识点:
<1>函数(可作为变量)
<2>高阶函数
a.把一个函数名当作实参传给另一个函数(在不修改被装饰函数的情况下,为其添加新功能)
b.返回值中包含函数名(不修改函数的调用方式)
<3>嵌套函数
高阶函数 + 嵌套函数 ==》 装饰器
4.下面举例分析:
<1>把一个函数名当作实参传给另一个函数
1 import time 2 #把一个函数名当作实参传给另一个函数 3 def hyt(): 4 time.sleep(3) #延迟三秒 5 print('This is hyt') 6 7 def congcong(func): #函数作为变量 8 str_time = time.time() #记录开始时间 9 func() #运行hyt函数 10 stop_time = time.time() #记录结束时间 11 print('The func runs time is %s '%(stop_time-str_time)) #输出:The func runs time is 3.000171661376953 12 13 congcong(hyt)
<2>返回值中包含函数名
import time #返回值中包含函数名(不修改函数的调用方式) def hyt(): time.sleep(3) #延迟三秒 print('This is hyt') def cc(func): print(func)#打印hyt函数的内存地址,结果:<function hyt at 0x00206780> return func #返回hyt函数的内存地址 hyt=cc(hyt) #cc(hyt)表示传递hyt函数的内存地址,而cc(hyt())表示传递hyt函数的返回值,不符合高阶函数的定义 hyt() #运行hyt函数
<3>嵌套函数
1 def foo(): 2 # '嵌套函数:在一个函数的函数体内部用def声明并调用另一个函数。' 3 print('This is foo') 4 def func(): #局部起作用,故只能在函数体内部调用 5 print('This is func') 6 7 func() 8 foo()
<4>#局部作用域与全局作用域的访问顺序
5.装饰器实际运用
<1>简单点的:
1 def timer(func): #timer(cc1) func = cc1 2 'decorator(装饰器高潮版)' 3 def hyt(*args,**kwargs): #非固定传参,前者接受位置参数,后者接受关键字参数 4 star_time = time.time() #time.time()调用时间的计时功能 5 func(*args,**kwargs) #run cc1() 6 stop_time = time.time() 7 print('The func running time is %s'%(stop_time-star_time)) 8 return hyt 9 @timer #等同于cc1 = timer(cc1) 10 def cc1(): 11 time.sleep(1) 12 print('This is cc1..') 13 cc1() 14 15 @timer #等同于cc2 = timer(cc2) = hyt cc2()=>hyt() ==> cc2(name,age)==>hyt(name.age) 16 def cc2(name,age): 17 time.sleep(3) 18 print('Name is \033[32;1m{s1}\033[0m,Age is \033[31;1m{s2}\033[0m'.format(s1=name,s2=age)) 19 cc2('SC',20)
<2>复杂点的:
1 #装饰器经典款 2 import time 3 user = 'cc' 4 passwd = '123456' 5 def auth(func): 6 def wrapper(*args,**kwargs): 7 usename = input('Usename:').strip() 8 password = input('Password:').strip() 9 if user == usename and passwd == password: 10 print('Welcome \033[32;1m%s hased passed authentication\033[0m'%(usename)) 11 func(*args,**kwargs) 12 else: 13 exit('\033[31;1m Your usename or password is invalid\033[0m') 14 return wrapper 15 16 def index(): 17 print('Welcome index page') 18 @auth 19 def home(): 20 print('Welcome home page') 21 @auth 22 def bbs(): 23 print('Welcome bbs page') 24 index() 25 home() 26 bbs() 27 ''' 28 29 #装饰器限量版 30 import time 31 user,passwd = 'cc','123456' 32 def auth(auth_type): 33 print('Auth type:',auth_type) 34 #按照登录方式的不同而选择不同的认证方式 35 def out_wrapper(func): 36 def wrapper(*args,**kwargs): 37 usename = input('Usename:').strip() 38 password = input('Password:').strip() 39 if auth_type == 'local': 40 if user == usename and passwd == password: 41 print('\033[32;1mWelcome %s hased passed authentication\033[0m'%(usename)) 42 res_home = func(*args,**kwargs)# from home 43 print('---after authentication---') 44 else: 45 exit('\033[31;1m Your usename or password is invalid\033[0m') 46 else: 47 print('There is no ladp.....') 48 return wrapper 49 return out_wrapper 50 51 def index(): 52 print('Welcome index page') 53 54 @auth(auth_type='local') #home = home(out_wrapper) => wrapper => home()=>wrapper() 55 def home(): 56 print('Welcome home page') 57 return 'from home' 58 59 @auth(auth_type='ldap') 60 def bbs(): 61 print('Welcome bbs page') 62 index() 63 home() 64 bbs()
二、生成器(generator)
1.定义:
通过列表生成式。可以直接创建一个列表。但是受到内存限制,列表容量有限。而且,创建一个包含上百万 个元素的列表,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表可以按照某种算法推算出来,那 我们可以在循环的过程中不断推算后续的元素,这样就不必创建完整的list,从而节省大量的空间。在python中, 这种一边循环一边计算的机制,称为生成器:generator。
2.生成器创建方法及实例
<1>最简单的生成方法:把列表生成式的[]改成(),就创建了一个生成器(generator)。
<2>列表生成式和生成器实例:
1 #列表生成式(简洁) 2 3 a = [i*2 for i in range(8)] 4 print(a) #输出结果:[0, 2, 4, 6, 8, 10, 12, 14] 5 6 7 #传统的列表生成方式 8 9 a = [] 10 for i in range(8): 11 a.append(i*2) 12 print(a) #输出结果:[0, 2, 4, 6, 8, 10, 12, 14]
1 L = [x * x for x in range(8)] #列表(list) 2 print(L) #输出:[0, 1, 4, 9, 16, 25, 36, 49] 3 M = (x * x for x in range(8)) #生成器(generator) 4 print(M) #输出:<generator object <genexpr> at 0x00537F00> 5 print(M.__next__()) #输出:0 生成器的_next_()方法 6 print(M.__next__()) #输出:1 7 print(M.__next__()) #输出:4
<3>生成器的调用和迭代
注意:生成器(generator)保存的是算法,每次调用_next_(),就计算出M的下一个元素的值,直到计算到最 后一个元素,没有更多元素时,抛出StopIteration(异常)的错误。但这种方法太过繁琐,创建generator后, 基本不会使用_next_(),正确方法是使用for循环来迭代它,并且不需要关心StopIteration的错误
1 N = (y*2 for y in range(6)) 2 for i in N: 3 print(i) #输出:0 2 4 6 8 10
<4>斐波拉契数列和异常处理
generator很强大,但如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以使用 函数来实现。比如著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数可有前两个数相加得 到:1,1,2,3,5,8,13,...斐波拉契数列用列表生成式写不出来,但可用函数轻松表示出来
1 def fib(max): #max = 10 2 n ,a,b = 0,0,1 3 while n < max: 4 #print(b) 5 yield b #yield 表示出产,产生,保存了函数的中断状态 6 a,b = b,a+b # t = (b,a+b) 是一个元组,a=t[0],b=t[1] 7 n = n + 1 8 return 'worked down' #异常的时候打印return的内容 9 #fib(10) #输出:1,1,2,3,5,8,13,21,34,55 10 print(fib(max)) #输出:<generator object fib at 0x00507E70> 11 12 ''' 13 f = fib(10) 14 print(f.__next__())#输出:1 15 print(f.__next__())#输出:1 16 print(f.__next__())#输出:2 17 print('Hello everyone,now looping') #可以插在生成器其中不影响其连续过程 18 for i in f: 19 print(i)#输出:3,5,8,13,21,34,55 20 ''' 21 #异常处理 22 g = fib(6) 23 while True: 24 try: #未出错的时候执行 25 x = next(g) #next为内置方法,等同于_next_()方法 26 print('g:',x) #输出:g: 1 1 2 3 5 8 27 except StopIteration as e: #出错时捕获错误定义为e 28 print('Generator return value:',e.value) #输出Generator return value: worked down 29 break
3.关于生成器并行运算
1 import time 2 def consumer(name): 3 print('\033[32;1m%s\033[0m 准备吃饭了'%name) 4 while True: 5 shuijiao = yield #yield 接受来自N的send 方法传来的参数 6 print('\033[31;1m[%s]\033[0m 饺子煮好了,被\033[32;1m%s\033[0m吃完了'%(shuijiao,name)) 7 8 N = consumer('hyt') 9 N.__next__() #此方法只调用,不传值,输出:hyt 准备吃饭了 10 N.__next__() #输出:[None] 饺子煮好了,被hyt吃完了 11 b1,b2 = '猪肉馅','牛肉馅' 12 N.send(b1) #send方法调用并传值,输出:[猪肉馅] 饺子煮好了,被hyt吃完了 13 N.send(b2) #输出:[牛肉馅] 饺子煮好了,被hyt吃完了 14 15 def prodouct(name): 16 c1 = consumer('sc') 17 c2 = consumer('cc') 18 c1.__next__() 19 c2.__next__() 20 print('\033[32;1m%s 开始做饺子了!\033[0m'%name) 21 for i in range(3): 22 time.sleep(2) 23 print('两人平分一碗饺子') 24 c1.send('粉丝') 25 c2.send('韭菜') 26 prodouct('congcong')
三、迭代器
1.可迭代对象(Iterable)
<1>定义:
可以直接作用于for循环的数据类型有以下几种:
一类 是集合数据类型,如list、tuple、dict、set、str等
二类 是generator,包括生成器和带yield的generator function.
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
<2>判断方法:可以使用isinstance()判断一个对象是否有Iterable对象。
<3>实例:
1 from collections import Iterable 2 print(isinstance([],Iterable)) #判断列表是否有可迭代对象 True 3 print(isinstance((),Iterable)) #判断字典是否有可迭代对象 True 4 print(isinstance({},Iterable)) #判断集合是否有可迭代对象 True 5 print(isinstance('huangyuting',Iterable)) #判断字符串是否有可迭代对象 True 6 print(isinstance(666,Iterable)) #判断数字是否有可迭代对象 False 7 print(isinstance((x for x in range(4)),Iterable)) #判断generator是否有可迭代对象 True
注意:而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,
直到最后抛出StopIteration错误表示无法继续返回下一个值了。
2.迭代器(Iterator)
<1>定义:可以被next函数调用并不断返回下一个值的对象称为迭代器:Iterator。
<2>判断方法:可以使用isinstance()判断一个对象是否是迭代器(Iterator)对象。
<3>实例:
1 from collections import Iterator 2 print(isinstance((),Iterator)) #判断字典是否是迭代器 False 3 print(isinstance([],Iterator)) #判断列表是否是迭代器 False 4 print(isinstance({},Iterator)) #判断集合是否是迭代器 False 5 print(isinstance('congcong',Iterator)) #判断字符串是否是迭代器 False 6 print(isinstance(888,Iterator)) #判断数字是否是迭代器 False 7 print(isinstance((x for x in range(5)),Iterator)) #判断生成器是否是迭代器 True
<4> 可迭代对象转成迭代器的方法:
由上可知,生成器都是迭代器,然而list,dict,str虽然都是可迭代对象(Iterable),但不是
迭代器(Iterator),可以把list,dict,str等Iterable变成Iterator可以使用iter()函数。如下
所示:
1 from collections import Iterator 2 print(isinstance(iter([]),Iterator),type(iter([]))) #True <class 'list_iterator'> 3 print(isinstance(iter(()),Iterator),type(iter(()))) #True <class 'tuple_iterator'> 4 print(isinstance(iter({}),Iterator),type(iter({}))) #True <class 'dict_keyiterator'> 5 print(isinstance(iter('hytsc'),Iterator),type(iter('hytsc'))) #True <class 'str_iterator'>
3.一点疑问解答: 为什么list,dict,str等数据类型不是迭代器(Iterator)?
因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopItration错误。可以将这个数据流看成一个有序序列,但我们却不能提前知道序列的长度,只有不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
4. Python的for循环本质上就是通过不断调用next()函数实现的,
例如:
1 for x in range(5): 2 print(x) 3 #等价于 4 t = iter(range(5)) #首先获得Iterator对象 5 #print(dir(t)) #打印 t 可调用的所有方法 6 while True: #循环 7 try: 8 x = next(t) #获取下一个值 9 except StopIteration: #遇到StopIteration就退出循环 10 break
四、python内置函数大揭秘:
1 print(all([1,0,4])) #所有数据为真(非零即为真),空表也为假 输出:False 2 print(any((0,-1,4))) #任意数据为真 输出:True 3 print(bin(10)) #将十进制转为二进制 输出:0b1010 4 print(hex(10))#将十进制转为十六进制 输出:0xa 5 print(oct(8))#将十进制转为八进制 输出:0o10 6 print(bool([])) #判断真假(非零即为真),输出:False 7 8 a = bytes('abcde',encoding='utf-8') 9 print(a) #输出:b'abcde' 10 b = bytearray('abcde',encoding='utf-8') 11 print(b) #输出:bytearray(b'abcde') 12 b[0] = 65 #此处只能输入ASCII码值,A为97 13 print(b) #输出:bytearray(b'Abcde') 14 15 a = 'hello' 16 print(a.capitalize(),a) #字符串不能修改,只能重新生成新的,输出:Hello hello 17 18 def func(): 19 pass 20 print(callable(func)) #判断是否可调用 21 22 print(chr(97)) #打印ASCII码对应的字符,输出;a 23 print(ord('a')) #打印字符a对应的ASCII码值,输出;97 24 25 code = ''' 26 def fib(max): 27 n,a,b = 0,0,1 28 while n < max: 29 #print(b) 30 yield b 31 a,b = b,a+b 32 n = n + 1 33 return 'worked down' 34 #fib(10) 35 #异常处理 36 g = fib(10) 37 while True: 38 try: #未出错的时候执行 39 x = next(g) #next为内置方法,等同于_next_()方法 40 print('g:',x) #输出:g: 1 1 2 3 5 8 41 except StopIteration as e: #出错时捕获错误定义为e 42 print('Generator return value:',e.value) #输出Generator return value: worked down 43 break 44 ''' 45 exec(code) #将字符串编译成一段可执行文件 46 #py_obj = compile(code,"fib.log","exec") #将字符串编译成指定文件名的可执行代码 47 #exec(py_obj) 48 49 print(dir(code)) #打印 字符串code的所有方法 50 print(divmod(9,2)) #求两个数的商和余数,并打印出来,输出:(4, 1) 51 52 h = "['hello','world']" 53 print(eval(h)) #将字符串转成字典或列表 54 55 calc = lambda n:n**2 56 print(calc(3)) 57 calc = lambda n:4 if n<3 else n #lambda为匿名函数 58 print(calc(2)) #输出:4 59 60 res = filter(lambda x:(x%2==1),range(10)) #从列表中筛选0到100以内的奇数 61 for i in res: 62 print(i) #输出:1,3,5,7,9 63 64 res1 = map(lambda y:y*2,range(4))#将列表中元素全部处理 65 res2 = [lambda d:d*d for d in range(2)] 66 for i in res1: 67 print(i)#输出:0,2,4,6 68 for i in res2: 69 print(i)#输出:<function <listcomp>.<lambda> at 0x006BE4F8> 70 # <function <listcomp>.<lambda> at 0x002EE300> 71 72 import functools #functools意为函数工具 73 res3 = functools.reduce(lambda a,b:a*b ,range(1,6))#求列表1到6的阶乘,a接收a*b的值,b接收列表中的值 74 print(res3)
1 a = frozenset([1,2,3,5,6,8]) #frozenset函数修饰后为不可变列表,集合 2 3 print(globals()) #打印所在模块当前最大命名空间内的变量名和值(key-value) 4 print(hash('cc'))#哈希函数,建立字符串等于数字的特定位置关系,输出:1362460451 5 6 def test(): 7 local_test = 666 #局部变量 8 print(locals())#返回局部变量,输出:{'local_test': 666} 打印所在模块当前最小命名空间内的变量名和值 9 print(globals())#不包含local_test 10 test() 11 b = 999 12 print(globals()) #只打印全局变量,不打印局部变量 13 print(globals().get('local_test')) #输出:None 14 15 print(pow(2,4)) #表示求 2 的 4 次方 输出:16 16 17 print(round(3.14159,2)) #表示将3.14159保留两位小数 18 ''' 19 a = {'b':5,'a':1,'d':4,'c':8} 20 print(sorted(a.items())) #输出:[('a', 1), ('b', 5), ('c', 8), ('d', 4)],默认以key排序 21 print(sorted(a.items(),key=lambda x:x[1] ))#输出:[('a', 1), ('d', 4), ('b', 5), ('c', 8)],指定以value排序 22 23 d = [1,3,5,7] 24 e = ['h','e','l','l','o'] 25 for i in zip(d,e): #zip取最短的列表进行一一对应 26 print(i) #输出:(1, 'h') (3, 'e') (5, 'l') (7, 'l') 27 28 __import__('生成器') #导入字符串
五、序列化与反序列化
<1>序列化(json、pickle)
1 #序列化:将内存对象转换成字符串保存起来 2 '''import json 3 info = { 4 'name':'cc', 5 'age':20, 6 'job':'student' 7 } 8 f = open('test.txt','w',encoding='utf-8') 9 #f.write(str(info))#很low的方法 10 print(json.dumps(info),type(json.dumps(info)))#输出:{"age": 20, "job": "student", "name": "cc"} <class 'str'> 11 f.write(json.dumps(info)) #专业方法 12 f.close() 13 ''' 14 #json 与 pickle 的区别在于:pickle只能在python中使用,而json却可以在各个语言间转换 15 16 #pickle 17 import pickle 18 def hey(name): 19 print('hello',name) 20 21 info2 = { 22 'name':'hyt', 23 'age':18, 24 'func':hey 25 } 26 f = open('test2.txt','wb') 27 print(pickle.dump(info2,f))#输出:None 28 pickle.dump(info2,f) #与 f.write(pickle.dumps(info)) 作用相同 29 f.close()
<2>反序列化(json、pickle)
1 import json 2 f = open('test.txt','r') 3 #很low的方法 4 data = f.read() 5 f.close() 6 print(data,type(data)) #输出:{'age': 20, 'job': 'student', 'name': 'cc'} <class 'str'> 7 print(eval(data),type(eval(data))) #eval()是内置函数,可将字符串转为字典或列表, 8 #输出:{'name': 'cc', 'age': 20, 'job': 'student'} <class 'dict' 9 #专业的方法 10 data = json.loads(f.read()) 11 print(data,type(data))#输出:{'job': 'student', 'age': 20, 'name': 'cc'} <class 'dict'> 12 print(data['name'])#输出:cc 13 ''' 14 15 #pickle 16 import pickle 17 def hey(name): 18 print('hello',name) 19 info2 = { 20 'name':'hyt', 21 'age':18, 22 'func':hey 23 } 24 f = open('test2.txt','rb') 25 data = pickle.load(f)# data = pickle.loads(f.read()) 26 print(data,type(data)) #输出:{'age': 18, 'name': 'hyt', 'func': <function hey at 0x0094E468>} <class 'dict'> 27 print(data['func']('hyt')) 28 f.close()

浙公网安备 33010602011771号