装饰器特点:
1>. 开放封闭原则, 即对扩展是开放的, 对修改时封闭的;
2>. 装饰器本质可以是任意可调用的对象, 被装饰的对象也可以是任意可调用对象;
3>. 装饰器的功能是在不修改被装饰器对象源代码以及被装饰器对象的调用方式的前提下为其扩展新功能;
4>. 装饰器本质是函数,(即装饰其他函数)就是为其他函数添加附加功能
一. 典型装饰器案例
- #!/usr/bin/env python
- #_*_coding:utf-8_*_
- #@author :yinzhengjie
- #blog:http://www.cnblogs.com/yinzhengjie/tag/python自动化运维之路/
- #EMAIL:y1053419035@qq.com
- #装饰器的语法: 在被装饰对象的正上方的单独一行,@装饰器名字
- import time
- import random
- def RunTime(TheCaller): #定义装饰器
- def MyCaller():
- start_time = time.time()
- TheCaller()
- stop_time=time.time()
- print(run time is %s %(stop_time-start_time))
- return MyCaller
- #被装饰函数
- @RunTime #等效于 index=RunTime(index)
- def index():
- time.sleep(random.randrange(2,4)) #可以在 1-3 秒钟 (不包括 4 秒哟) 随机睡眠指定范围的时长
- print(welecome to INDEX page)
- @RunTime #home=RunTime(home)
- def home():
- time.sleep(random.randrange(1,2))
- print(welecome to HOME page)
- index() #MyCaller()
- home()
- #以上代码执行结果如下:
- welecome to INDEX page
- run time is 2.0000088214874268
- welecome to HOME page
- run time is 1.0006351470947266
二. 多个装饰器案例展示
- #!/usr/bin/env python
- #_*_coding:utf-8_*_
- #@author :yinzhengjie
- #blog:http://www.cnblogs.com/yinzhengjie/tag/python自动化运维之路/
- #EMAIL:y1053419035@qq.com
- #装饰器的语法: 在被装饰对象的正上方的单独一行,@装饰器名字
- import time
- import random
- from functools import wraps
- def RunTime(TheCaller): #定义装饰器 +
- @wraps(TheCaller) #可以让用户查看帮助信息的时候查看其自己的源代码定义的帮助信息
- def MyCaller(*args,**kwargs):
- Runtimes help information
- start_time = time.time()
- res = TheCaller(*args,**kwargs)
- stop_time=time.time()
- print(run time is %s %(stop_time-start_time))
- return res
- return MyCaller
- def NewAddAuth(TheCaller):
- def Auth(*args,**kwargs):
- name=input(username: )
- password=input(password: )
- if name == yinzhengjie and password == 123:
- print(login successful)
- res = TheCaller(*args,**kwargs)
- return res
- else:
- print(login error)
- return Auth
- #被装饰函数
- # @NewAddAuth
- @RunTime #等效于 index=RunTime(index), 装饰器的执行顺序是自下而上
- def Index():
- Indexs help information
- time.sleep(random.randrange(2,4)) #可以在 1-3 秒钟 (不包括 4 秒哟) 随机睡眠指定范围的时长
- print(welecome to INDEX page)
- return "yinzhengjie"
- @RunTime #home=RunTime(home)
- def Home(name):
- Homes help information
- time.sleep(random.randrange(1,2))
- print(welecome to %s HOME page%(name))
- return 666
- res1 = Index() #MyCaller()
- res2 = Home("尹正杰")
- print("Index return :%s"%(res1))
- print("Home return :%s"%(res2))
- # print(help(Index))
- # print(Index().__doc__)
- #以上代码执行结果如下:
- welecome to INDEX page
- run time is 3.000018835067749
welecome to 尹正杰 HOME page
- run time is 1.0001890659332275
- Index return :yinzhengjie
- Home return :666
三. 有参装饰器
- #!/usr/bin/env python
- #_*_coding:utf-8_*_
- #@author :yinzhengjie
- #blog:http://www.cnblogs.com/yinzhengjie/tag/python自动化运维之路/
- #EMAIL:y1053419035@qq.com
编写装饰器, 为多个函数加上认证的功能(用户的账号密码来源于文件), 要求登陆成功一次, 后续的函数都无需再验证
- # user_dic = {
- # yinzhengjie:123,
- # Golang:"666",
- # Python:"888",
- # }
- #
- # with open("user.db","w",encoding="utf-8")as f:
- # f.write(str(user_dic))
- db_path = "user.db"
- login_dic ={
- user:None,
- "status":False,
- }
- def Decorator(AuthType="file"):
- def auth(func):
- def wrapper(*args, **kwargs):
- if AuthType == "file":
- if login_dic[user] and login_dic[status]:
- res = func(*args, **kwargs)
- return res
- username = input("username:")
- password = input("password:")
- with open(db_path, "r", encoding="utf-8")as f:
- user_dic = eval(f.read())
- if username in user_dic and password == user_dic[username]:
- print(login successful)
- login_dic[user] = username
- login_dic[status] = True
- res = func(*args, **kwargs)
- return res
- else:
- print(login error)
- elif AuthType == "ldap":
- print("LDAP 认证方式")
- elif AuthType == "MySQL":
- print("MySQL 认证方式")
- else:
- print("其他认证方式")
- return wrapper
- return auth
- @Decorator()
- def Index():
- print("Welcome to Index!")
- @Decorator(AuthType="MySQL")
- def home(name):
- print("Welecome %s to home page!"%name)
- Index()
- home("尹正杰")
- #以上代码执行结果如下:
- username:yinzhengjie
- password:123
- login successful
- Welcome to Index!
MySQL 认证方式
四. 小试牛刀
1. 编写装饰器, 为多个函数加上认证的功能(用户的账号密码来源于文件), 要求登陆成功一次, 后续的函数都无需再验证
- #!/usr/bin/env python
- #_*_coding:utf-8_*_
- #@author :yinzhengjie
- #blog:http://www.cnblogs.com/yinzhengjie/tag/python自动化运维之路/
- #EMAIL:y1053419035@qq.com
- # user_dic = {
- # yinzhengjie:123,
- # Golang:"666",
- # Python:"888",
- # }
- #
- # with open("user.db","w",encoding="utf-8")as f:
- # f.write(str(user_dic))
- db_path = "user.db"
- login_dic ={
- user:None,
- "status":False,
- }
- def auth(func):
- def wrapper(*args,**kwargs):
- if login_dic[user] and login_dic[status]:
- res = func(*args, **kwargs)
- return res
- username = input("username:")
- password = input("password:")
- with open(db_path, "r", encoding="utf-8")as f:
- user_dic = eval(f.read())
- if username in user_dic and password == user_dic[username]:
- print(login successful)
- login_dic[user] = username
- login_dic[status] = True
- res = func(*args,**kwargs)
- return res
- else:
- print(login error)
- return wrapper
- @auth
- def Index():
- print("Welcome to Index!")
- @auth
- def home(name):
- print("Welecome %s to home page!"%name)
- Index()
- home("尹正杰")
以上代码执行结果如下:
- username:yinzhengjie
- password:123
- login successful
- Welcome to Index!
Welecome 尹正杰 to home page!
2. 编写下载网页内容的函数, 要求功能是: 用户传入一个 URL, 函数返回下载页面的内容
- #!/usr/bin/env python
- #_*_coding:utf-8_*_
- #@author :yinzhengjie
- #blog:http://www.cnblogs.com/yinzhengjie/tag/python自动化运维之路/
- #EMAIL:y1053419035@qq.com
- from urllib.request import urlopen
- import os
- cache_path=rcache.txt
- def make_cache(func):
- def wrapper(*args,**kwargs):
- if os.path.getsize(cache_path):# 说明有缓存
print(\033[45m========= 有缓存 =========\033[0m)
- with open(cache_path,rb) as f:
- res=f.read()
- else:
- res=func(*args,**kwargs) #下载
- with open(cache_path,wb) as f: #制作缓存
- f.write(res)
- return res
- return wrapper
- @make_cache
- def get(url):
- return urlopen(url).read()
- print(============first============)
- print(get(http://www.cnblogs.com/yinzhengjie))
- print(============second===========)
- print(get(http://www.cnblogs.com/yinzhengjie))
- print(============third============)
- print(get(http://www.cnblogs.com/yinzhengjie))
来源: http://www.bubuko.com/infodetail-2506123.html