文章目录
# 自律 学习日记03-2
一.装饰器
讲装饰器之前我们先来了解一下开放封闭原则(面向对象原则的核心)
开放封闭原则:软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。
装饰器的作用:在不更改原功能函数内部代码,并且不改变调用方法的情况下为原函数添加新的功能,装饰器其实就是闭包应用。
(一)无参装饰器:
username='python'
password='123456'
def login(func):
def fun():
user=input('请输入账号:')
pw=input('请输入密码:')
if username==user and password==pw:
func()#哪里需要反回被装饰的内容,这个函数就放在哪里
else:
print('登录信息错误')
return fun
@login
def index():
print('这是个网站首页')
index()
>>
请输入账号:python
请输入密码:123456
这是个网站首页
(二)无参与带参公用装饰器:
- 装饰函数不需要return,装饰类要+return
def add(func):
def fun(*args,**kwargs):
print('装饰器的功能代码')
func(*args,**kwargs) #装饰函数不需要return,装饰类要+return
return fun
@add
def add_num(a,b,c):
print("相加",a+b+c)
@add
def good_list(num,n):
print("我是{0},今年{1}".format(num,n))
@add
def index():
print("测试测试测试")
add_num(11,22,33)
good_list('美女',18)
index()
>>>
装饰器的功能代码
相加 33
装饰器的功能代码
测试测试测试
装饰器的功能代码
第二段10
(三)脱外套:
1.脱衣服:加* 与 不加*的区别:
加*:脱外套
不加*:穿外套
def fun(*args):
print(args)
fun(1,2,3,4,5)
>>>输出元组:(1,2,3,4,5)
def fun(*args):
print(*args)
fun(1, 2, 3, 4, 5)
>>>输出:1,2,3,4,5
(四)装饰器:装饰类
def add(func):
def fun(*args,**kwargs):
print('装饰器代码')
#装饰器装饰函数一定要有return,函数如果没有返回值,默认返回none
return func(*args,**kwargs)
return fun
@add
class Myclass():
def __init__(self):
pass
def add(self):
print('我爱你')
m=Myclass()
print("m的值:",m)
m.add()
>>>装饰器代码
m的值: <__main__.Myclass object at 0x00000000027B8550>
我爱你
def add(func):
def fun(*args,**kwargs):
print('装饰器代码')
return func(*args,**kwargs)
return fun
@add
class Myclass():
def __init__(self,name,age):
self.name=name
self.age=age
m=Myclass('vivi',18)
print("m的值:",m)
>>>装饰器代码
m的值: <__main__.Myclass object at 0x00....
(五)return func()与return func区别
def func1():
pass
print(type(func1))
#执行结果:<class 'function'>
print(type(func1()))
#执行结果:<class 'NoneType'>
由此可见:
使用return func 返回的是函数;
使用return func() 返回的是值,如果func()函数没有返回值则返回值为None
(六)一个函数被多个装饰器装饰
import time
with open('ceshi.txt')as f:
users=eval(f.read())
def login_check(func):
'''
登录验证的装饰器
:param func:
:return:
'''
def ado(*args, **kwargs):
if not users['token']:
print('----登录页面-------')
username=input('账号:')
password=input('密码:')
#登录校验
if users['user']==username and users['pwd']==password:
users['token']=True #修改token值
func(*args, **kwargs)
else:
func()
return ado
def wrapper(func):
def count_time(*args, **kwargs):
print("开始了2")
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
print("{}函数运行的时间为:{:.5f}秒".format(func.__name__, end_time - start_time))
return count_time
多个装饰器从上往下执行
@wrapper #func=wrapper(func)
@login_check #func=login_check(func)
def func():
time.sleep(3)
print('这是需要被装饰器的函数')
func()
(七)类里面三个内置的装饰器
class MyTest(object):
def __init__(self):
pass
被classmethod装饰了之后,该方法就是一个类方法
被classmethod装饰了之后,只能类调用MyTest.add(),不能实例调用[t=MyTest,t.add()]
@classmethod
def add(cls):
print(cls)
静态方法 实例和类都可以调用
静态方法可以不传参,要是传参,那么调用的时候也一定要传
@staticmethod
def static():
print("这个静态方法")
设定只读属性,不可修改
@property
def read_attr(self):
print("这个装饰器装饰完了之后,该方法可以像属性一样被调用")
def sub(self): #self:代表实例本身
print("---")
t=MyTest()
(八)作业
定义一个计算函数运行时间的装饰器
import time
def wrapper(func):
def count_time(*args,**kwargs):
start_time=time.time()
func(*args,**kwargs)
end_time=time.time()
print('函数的运行时间为:{}秒'.format(end_time-start_time))
return count_time
@wrapper
def test(n):
time.sleep(n)
print('运行结束')
test(10)
运行结束了
test函数运行的时间为:10.00000秒
编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次
后续的函数都无需再输入用户名和密码。{"user":"python01","pwd":"123456","token":False}
with open('ceshi.txt')as f:
users =eval(f.read())
def login_check(func):
'''
登录验证的装饰器
:param func:
:return:
'''
def ado():
if not users['token']:
print('----登录页面-------')
username =input('账号:')
password =input('密码:')
# 登录校验
if users['user']==username and users['pwd' ]==password:
users['token' ] =True # 修改token值
func()
else:
func()
return ado
@login_check
def index():
print('这是index首页')
@login_check
def page1():
print('这个是page1页面')
@login_check
def page2():
print('这个是page2页面')
if __name__=='__main__':
index()
page1()
page2()
>>>>>>>>
----登录页面-------
账号:python01
密码:123456
这个是page1页面
这个是page2页面