python--有参装饰器、迭代器
有参装饰器的引入:
import time import random from functools import wraps def timmer(func): @wraps(func) def wrapper(): # wrapper.__doc__=func.__doc__ start_time = time.time() func() stop_time = time.time() print('run time is %s' % (stop_time-start_time)) # wrapper.__doc__=func.__doc__ return wrapper @timmer def index(): 'index function' time.sleep(3) print('welcome to index page') # print(index.__doc__) index() print(index.__doc__) 结果: welcome to index page run time is 3.000171661376953 index function
先来简单介绍一下functools.wraps。
我们在使用 Decorator 的过程中,难免会损失一些原本的功能信息。而functools.wraps 则可以将原函数对象的指定属性复制给包装函数对象, 默认有 __module__、__name__、__doc__,或者通过参数选择。
def foo(): 'foo function------------>' pass print(help(foo)) 结果: foo() foo function------------> None
help函数是python的一个内置函数(它是python自带的函数,任何时候都可以被使)。
help函数能作什么:
在使用python来编写代码时,会经常使用python 调用函数自带函数或模块,一些不常用的函数或是模块的用途不是很清楚,这时候就需要用到help函数来查看帮助。
这里要注意下,help()函数是查看函数或模块用途的详细说明,而dir()函数是查看函数或模块内的操作方法都有什么,输出的是方法列表。
怎么使用help函数查看python模块中函数的用法:
help( )括号内填写参数,操作方法很简单。
使用help函数查看帮助时需要注意哪些问题:
1、查看一个模块的帮助
>>>help('sys')
之后它回打开这个模块的帮助文档
2、查看一个数据类型的帮助
>>>help('str')
返回字符串的方法及详细说明
>>>a = [1,2,3]
>>>help(a)
这时help(a)则会打开list的操作方法
>>>help(a.append)
会显示list的append方法的帮助
下面来几个栗子:
def foo(): 'foo fuction' print(foo.__doc__) foo.__doc__ = 'asdfasdfasdfasdfsadfasdfasdfsadfasdfasfas' pass print(help(foo)) 结果: Help on function foo in module __main__: foo() foo fuction None
def foo(): 'foo fuction' print(foo.__doc__) foo.__doc__ = 'asdfasdfasdfasdfsadfasdfasdfsadfasdfasfas' pass print(foo.__doc__) 结果: foo fuction
def foo(): 'foo fuction' print(foo.__doc__) foo.__doc__ = 'asdfasdfasdfasdfsadfasdfasdfsadfasdfasfas' pass foo.__doc__ = 'abcdefg' print(foo.__doc__) 结果: abcdefg
def foo(): 'foo fuction' print(foo.__doc__) foo.__doc__ = 'asdfasdfasdfasdfsadfasdfasdfsadfasdfasfas' pass foo.__doc__ = 'abcdefg' print(help(foo)) 结果: Help on function foo in module __main__: foo() abcdefg None
def foo(): 'foo fuction' print(foo.__doc__) foo.__doc__ = 'asdfasdfasdfasdfsadfasdfasdfsadfasdfasfas' pass foo() print(foo.__doc__) 结果: foo fuction asdfasdfasdfasdfsadfasdfasdfsadfasdfasfas
有参装饰器
db_path=r'C:\Users\Administrator\PycharmProjects\untitled4\db.txt' login_dic = { 'user': None, 'status': False, } def deco(auth_type='file'): def auth(func): def wrapper(*args, **kwargs): if auth_type == 'file': if login_dic['user'] and login_dic['status']: res = func(*args, **kwargs) return res name = input('your name: ') password = input('your password: ') with open(db_path, 'r', encoding='utf-8') as f: user_dic = eval(f.read()) if name in user_dic and password == user_dic[name]: print('login ok') login_dic['user'] = name login_dic['status'] = True res = func(*args, **kwargs) return res else: print('login err') elif auth_type == 'ldap': print('ldap认证方式') elif auth_type == 'mysql': print('mysql认证方式') else: print('不知到的认证方式') return wrapper return auth @deco(auth_type='abc') #@auth #index=auth(index) def index(): print('welcome to index') @deco(auth_type='ldap') def home(name): print('welcome %s to home page' % name) index() home('egon') 结果: 不知到的认证方式 ldap认证方式
def deco(auth_type='file'): def auth(func): def wrapper(*args,**kwargs): if auth_type == 'file': print('文件的认证方式') elif auth_type == 'ldap': print('ldap认证方式') elif auth_type == 'mysql': print('mysql认证方式') else: print('不知到的认证方式') return wrapper return auth @deco(auth_type='abc') #@auth #index=auth(index) def index(): print('welcome to index') @deco(auth_type='ldap') def home(name): print('welcome %s to home page' % name) index() home('egon') 结果: 不知到的认证方式 ldap认证方式
思考:
- 缓存多个不同网站的内容:
- 思路:hash每个url,用得到的值做成文件名,一个网站一个文件名,
- 然后每次根据传进来的url进行hash得到的结果去寻找文件
迭代器
- 迭代:
- 重复
- 下一次重复是基于上一次的结果
'''
python为了提供一种不依赖于索引的迭代方式,
python会为一些对象内置__iter__方法
obj.__iter__称为可迭代的对象
'''
obj.__iter__() 得到的结果就是迭代器
得到的迭代器:既有__iter__又有一个__next__方法
d={'a':1,'b':2,'c':3} i=d.__iter__() #i叫迭代器 print(i) print(i.__next__()) print(i.__next__()) print(i.__next__()) # print(i.__next__()) #StopIteration 结果: <dict_keyiterator object at 0x0000000001DBF2C8> a b c
迭代器的优点:
- 1:提供了一种不依赖于索引的取值方式
- 2:惰性计算。节省内存
迭代器的缺点:
- 1:取值不如按照索引取值方便
- 2:一次性的。只能往后走不能往前退
- 3:无法获取长度
迭代器的应用:
- 1. 提供了一种不依赖索引的统一的迭代方法
- 2. 惰性计算,比如取文件的每一行
l = [1, 2, 3] for item in l: #i=l.__iter__() print(item) 结果: 1 2 3
作业: 2 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到文件中 注意:时间格式的获取 import time time.strftime('%Y-%m-%d %X') 3 判断下列数据类型是可迭代对象or迭代器 s='hello' l=[1,2,3,4] t=(1,2,3) d={'a':1} set={1,2,3} f=open('a.txt') 4 分别用依赖索引和不依赖索引两种方式迭代上述对象 5 选做题: 基于课上所讲网页缓存装饰器的基础上,实现缓存不同网页的功能 要求,用户提交的不同url,都能缓存下来,对相同的url发起下载请求,优先从缓存里取内容
答案: # 2 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到文件中 # 注意:时间格式的获取 # import time # time.strftime('%Y-%m-%d %X') # # import time # # log_path=r'C:\Users\Administrator\PycharmProjects\untitled\log.txt' # def log_deco(func): # def wrapper(*args,**kwargs): # with open(log_path,'w') as f: # func(*args, **kwargs) # a = f.write(time.strftime('%Y-%m-%d %X')) # return a # # # res=func(*args,**kwargs) # # return res # return wrapper # # @log_deco # def f1(): # print('welcome to f1 page') # # f1() # 3 判断下列数据类型是可迭代对象or迭代器 # # s='hello' # l=[1,2,3,4] # t=(1,2,3) # d={'a':1} # set={1,2,3} # f=open('a.txt') # #字符串,列表,元祖,字典,集合,文件都是可迭代对象,可以object.__iter__ # s='hello' # s1=s.__iter__() # print(s1.__next__()) # print(s1.__next__()) # print(s1.__next__()) # print(s1.__next__()) # print(s1.__next__()) # l=[1,2,3,4] # l1=l.__iter__() # print(l1.__next__()) # print(l1.__next__()) # print(l1.__next__()) # print(l1.__next__()) # t=(1,2,3) # t1=t.__iter__() # print(t1.__next__()) # print(t1.__next__()) # print(t1.__next__()) # d={'a':1} # d1=d.__iter__() # print(d1.__next__()) # set={1,2,3} # set1=set.__iter__() # print(set1.__next__()) # print(set1.__next__()) # print(set1.__next__()) # f=open('a.txt') # f1=f.__iter__() # print(f1.__next__()) # print(f1.__next__()) # print(f1.__next__()) # print(f1.__next__()) # print(f1.__next__()) # print(f1.__next__()) # 4 分别用依赖索引和不依赖索引两种方式迭代上述对象 # s='hello' # l=[1,2,3,4] # t=(1,2,3) # d={'a':1} # set={1,2,3} # f=open('a.txt') # # # for i1 in s: # print(i1) # # i1=0 # while i1<len(s): # print(s[i1]) # i1+=1 # # # for i2 in l: # print(i2) # # i2=0 # while i2<len(l): # print(l[i2]) # i2+=1 # # # for i3 in t: # print(i3) # # i3=0 # while i3<len(t): # print(t[i3]) # i3+=1 # # # for i4 in d: # print(i4) # for i5 in set: # print(i5) # # with open('a.txt','r',encoding='utf-8')as f: # for line in f: # print(line,end='') # # 5 选做题: # 基于课上所讲网页缓存装饰器的基础上,实现缓存不同网页的功能 # 要求,用户提交的不同url,都能缓存下来,对相同的url发起下载请求,优先从缓存里取内容