# python之装饰器

def outer():
a = 1
def inner():
print(a)
inner()
outer()

def outer():
a = 1
def inner():
print(a)
return inner

inn = outer()
inn()

## 闭包函数最常用的用法

def func():
name = 'liu'
def inner():
print(name)
return inner

f = func()
f()

name = 'liu'
def func2():
def inner():
print(name)
print(inner.__closure__)
return inner

f2 = func2()
f2()

from urllib.request import urlopen
def get_url():
url = 'https://www.baidu.com'
def get():
print(ret)
return get

inn = get_url()
inn()

## 装饰器形成的过程

import time
def func1():
start = time.time()
print('in func1')
print(time.time() - start)

func1()

import time
def timer(func):
start = time.time()
func()
print(time.time() - start)

def func1():
print('in func1')

def func2():
print('in func2')

timer(func1)
timer(func2)

import time

def func1():
print('in func1')

def timer(func):
def inner():
start = time.time()
func()
end = time.time()
print(end - start)
return inner

func1 = timer(func1)
func1()

## 语法糖

import time
def timer(func):
def inner():
start = time.time()
func()
print(time.time() - start)
return inner

@timer   #==> func1 = timer(func1)
def func1():
print('in func1')

func1()

## 带参数的函数

import time
def timer(func):
def inner(*args,**kwargs):
start = time.time()
re = func(*args,**kwargs)
print(time.time() - start)
return re
return inner

@timer   #==> func1 = timer(func1)
def func1(a,b):
print('in func1')

@timer   #==> func2 = timer(func2)
def func2(a):
print('in func2 and get a:%s'%(a))
return 'fun2 over'

func1('aaaaaa','bbbbbb')
print(func2('aaaaaa'))

def index():
'''这是一个主页信息'''
print('from index')

print(index.__doc__)    #查看函数注释的方法
print(index.__name__)   #查看函数名的方法

from functools import wraps

def deco(func):
@wraps(func) #加在最内层函数正上方
def wrapper(*args,**kwargs):
return func(*args,**kwargs)
return wrapper

@deco
def index():
'''哈哈哈哈'''
print('from index')

print(index.__doc__)
print(index.__name__)

## 装饰器的固定格式

def wrapper(f):    #装饰器函数，f是被装饰的函数
def inner(*args,**kwargs):
'''在被装饰函数之前要做的事'''
ret = f(*args,**kwargs)    #被装饰的函数
'''在被装饰函数之后要做的事'''
return ret
return inner

@wrapper         #语法糖 @装饰器函数名

## 装饰器原则

1.对扩展是开放的 　　　　为什么要对扩展开放呢？ 　　　　我们说，任何一个程序，不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。 2.对修改是封闭的 　　　　为什么要对修改封闭呢？ 　　　　就像我们刚刚提到的，因为我们写的一个函数，很有可能已经交付给其他人使用了，如果这个时候我们对其进行了修改，很有可能影响其他已经在使用该函数的用户。 装饰器完美的遵循了这个开放封闭原则。

## 习题练习

1.编写装饰器，为多个函数加上认证的功能（用户的账号密码来源于文件）， 要求登录成功一次，后续的函数都无需再输入用户名和密码

FLAG = False

def log(func):
def inner(*args,**kwargs):
global FLAG
if FLAG :
ret = func(*args,**kwargs)
return ret
else:
FLAG = True
ret = func(*args, **kwargs)
return ret
else:
print('登录失败')
return inner

@log

print('增加一件商品')

def shoplist_del():
print('删除一件商品')

2.编写装饰器，为多个函数加上记录调用功能，要求每次调用函数都将被调用的函数名称写入文件

def log(func):
def inner(*args,**kwargs):
with open('log','a',encoding='utf-8') as f:
f.write(func.__name__+'\n')
ret = func(*args,**kwargs)
return ret
return inner

@log
print('增加一件物品')

@log
def shoplist_del():
print('删除一件物品')

1.编写下载网页内容的函数，要求功能是：用户传入一个url，函数返回下载页面的结果 2.为题目1编写装饰器，实现缓存网页内容的功能： 具体：实现下载的页面存放于文件中，如果文件内有值（文件大小不为0），就优先从文件中读取网页内容，否则，就去下载，然后存到文件中

import os
from urllib.request import urlopen
def cache(func):
def inner(*args,**kwargs):
if os.path.getsize('web_cache'):
with open('web_cache','rb') as f:
ret = func(*args,**kwargs)  #get()
with open('web_cache','wb') as f:
f.write(b'*********'+ret)
return ret
return inner

@cache
def get(url):
return code

# {'网址':"文件名"}
ret = get('http://www.baidu.com')
print(ret)

0 条评论

• ### Paloalto 系统初始化和管理

Device > Setup > Management > General Settings

• ### Nginx重装与平滑升级

第一步：停止Nginx软件 第二步：删除/usr/local/nginx文件夹 第三步：下载Nginx-1.16重新进行配置、编译以及安装 缺点：在重装升级的过...

• ### 12步轻松搞定Python装饰器

原文链接：http://www.cnblogs.com/imshome/p/8327438.html 呵呵！作为一名教python的老师，我发现学生们基本上一...

• ### 12步轻松搞定Python装饰器

Python里面的装饰器比较复杂，下面12步可以帮你你较好的理解Python中的装饰器 1. 函数 在python中，函数通过 def关键字、函数名和可选的参数...

• ### JSONP 的工作原理

很简单，就是利用<script>标签没有跨域限制的“漏洞”（历史遗迹啊）来达到与第三方通讯的目的。当需要通讯时，本站脚本创建一个<script>元素，地址指向第...

• ### 医学假阴性？看看在机器学习中如何用来衡量分类模型的效果（附代码）

近日来，新冠肺炎核酸检测“假阴性”引起了关注。所谓的假阴性，就是患者是新型冠状病毒感染者，但是核酸没检测出来，报告阴性。有专家分析，任何核酸检测的检出率都不可能...

• ### Applet小应用程序之间的通讯

1、 首先解压：如何运行applet.zip文件，解压后如图

• ### 8.python之面相对象part.3

在python这门编程语言中，一个类可以去继承一个父类甚至多个父类，只继承一个父类就是单继承，如果一个子类继承了多个父类，那么这就是多继承。原始类被称为“基类”...