1. 编写函数(函数的执行时间是随机的)
import random, time # 导入模块
def random_time(): # 定义random_time函数
print('Start')
time.sleep(random.randint(1, 5)) # 实现随机执行时间
print('End')
random_time() # 调用random_time函数
2. 编写装饰器,为函数加上统计时间的功能
from functools import wraps # 导入模块
import time, random
def timmer(func): # 定义装饰器函数
@wraps(func) # 为装饰器加上一个装饰器,使咱们写的装饰器更完美
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
stop_time = time.time()
print('Run time is %s' % (stop_time - start_time))
return res # 将原函数返回值返回
return wrapper # 将wrapper函数地址返回
@timmer # 调用timmer装饰器
def random_time():
print('Start')
time.sleep(random.randint(1, 5))
print('End')
random_time() # 调用random_time函数(实则是调用的wrapper函数。)
3. 编写装饰器,为函数加上认证的功能
from functools import wraps
def auth(func): # 定义装饰器
@wraps(func) # 使装饰器更完美
def wrapper(*args, **kwargs):
inp_name = input('Username >>:').strip()
inp_pwd = input('Password >>:').strip()
if inp_name == 'Catalog Spri' and inp_pwd == '123': # 认证成功
res = func(*args, **kwargs)
return res
else: # 认证失败
print('Username or password error.')
return wrapper
@auth
def home(name):
print('Hello %s, welcome' % name)
home('Catalog Spri') # 调用home函数(实则调用的wrapper函数)
4. 编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登陆成功一次,后续的函数都无需再输入用户名和密码
注意:从文件中读出来的字符串形式的字典,可以用eval('{'name' : 'egon', 'password' : '123'}')转成字典格式
from functools import wraps # 从functools库导入wraps功能
auth_status = {'name': None} # 定义登录状态
def auth(func): # 定义装饰器
@wraps(func) # 使装饰器更完美
def wrapper(*args, **kwargs):
if auth_status['name'] is not None: # 判断登录状态
res = func(*args, **kwargs)
return res
inp_name = input('Username >>:').strip()
inp_pwd = input('Password >>:').strip()
with open('account.txt') as f:
for line in f:
info = eval(line.strip('\n')) # eval可以将字典、列表、元组等与字符串进行转换
if info['name'] == inp_name and info['password'] == inp_pwd:
auth_status['name'] = inp_name # 记录登录状态
res = func(*args, **kwargs) # 认证成功
return res
else: # 认证失败
print('Username or password error.')
return wrapper
@auth
def home(name):
print('Hello %s, welcome.' % name)
@auth
def index():
print('Welcome to the index page')
index() # 这里的函数的调用实则都是在调用wrapper函数。
home(auth_status['name'])
5. 编写装饰器,为多个函数加上认证功能,要求登陆成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录
from functools import wraps
import time # 导入模块
auth_status = {'name': None} # 记录登录状态
def auth(func): # 定义装饰器
@wraps(func) # 使装饰器变得完美
def wrapper(*args, **kwargs):
if auth_status['name'] is not None: # 判断登录状态
res = func(*args, **kwargs)
return res
inp_name = input('Username >>:').strip()
inp_pwd = input('Password >>:').strip()
if inp_name == 'egon' and inp_pwd == '123': # 认证成功
auth_status['name'] = inp_name # 记录登录状态
res = func(*args, **kwargs)
return res
else: # 认证失败
print('Username or password error.')
return wrapper
@auth
def home():
print('Welcome to home page')
@auth
def index():
print('Welcome to the index page')
while True: # 循环执行
home()
index()
time.sleep(10) # 10秒钟后清除登录状态,让用户重新登录再进行操作
auth_status['name'] = None
6. 编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的内容
import requests # 导入requests模块
def get(url): # 定义函数
response = requests.get(url) # 爬取网址url的内容
if response.status_code == 200: # 判断状态
return response.text
url = input('>>:')
print(get(url))
7. 为题目五编写装饰器,实现缓存网页内容的功能:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中
扩展功能:用户可以选择缓存介质/缓存引擎,针对不同的url,缓存到不同的文件中
# 这一题实现的并不完美,做到了写入不同文件内,但是看了一眼老师的标准答案,发现自己可能理解有误。
# 扩展功能实现的不够标准。但是还是实现了。各位有什么好的思路可以一起讨论一下
import requests # 导入模块
from functools import wraps
def download(func):
@wraps(func) # 令装饰器变得完美
def wrapper(*args, **kwargs):
with open(db, mode='a+', encoding='utf-8') as data: # 按用户输入的文件路径打开文件
data.seek(0) # 移动文件指针到开头
if len(data.read()) > 0: # 判断文件是否有内容
data.seek(0) # 前面read了一次,所以要再次移动文件指针
res = data.read()
return res
else: # 文件没内容则执行get函数进行下载
res = func(*args, **kwargs)
data.write(res) # 将爬取的内容按照用户规定路径写入文件中
return res
return wrapper
@download
def get(url, db): # 爬取一个网页的内容
response = requests.get(url)
if response.status_code == 200:
return response.text
url = input('URL >>:')
db = input('File path >>:')
get(url, db)
8. 还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作
from functools import wraps
functions = {} # 定义空字典方便将函数放进去
def add(func):
@wraps(func) # 一定要记得有这一步,会令装饰器变得完美
def wrapper(*args, **kwargs):
for i in functions: # 循环字典,判断func是否已经存在
if functions[i] == func:
break
else: # 遍历字典没找到func则将func添加进字典
functions[str(len(functions))] = func # 添加时要与数字建立关系
res = func(*args, **kwargs)
return res
return wrapper
@add
def login():
print('Log in successful')
@add
def shopping():
print("I'm shopping now")
@add
def pay():
print("Pay for goods")
@add
def charge():
print('Charge money')
9. 编写日志装饰器,实现功能:一旦函数f1执行,则将消息2018-09-27 13:30:21 f1 run 写入到日志文件中,日志文件路径可以指定
注意:时间格式的获取
import time
time.strftime('%Y-%m-%d %X')
from functools import wraps # 导入模块
import time
def log(file_path): # 需要传入文件路径,所以要再外包一层
def inner(func):
@wraps(func) # 这一步真的很重要!一定要记得
def wrapper(*args, **kwargs):
with open(file_path, mode='a', encoding='utf-8') as f: # 打开日志文件
time_now = time.strftime('%Y-%m-%d %X') # 获取当前时间
res = func(*args, **kwargs) # 运行func函数
f.write('%s | %s | run\n' % (time_now, func.__name__)) # 写入日志
return res # 通过func.__name__可以获取函数名
return wrapper
return inner
@log('log.txt')
def f1():
pass
f1()