热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

函数进阶之装饰器

一、闭包函数1.1定义:何为闭:定义在函数内部的函数何为包:定义函数引引用外部函数的作用域1.定义在函数内部的函数2.内部函数引用外部函数的名称空间的作用域的名字如:defotte

  一、闭包函数

    1.1 定义:    

    何为闭:定义在函数内部的函数
    何为包:定义函数引引用外部函数的作用域

1.定义在函数内部的函数
2.内部函数引用外部函数的名称空间的作用域的名字

如: def otter(x): x= 222 # 把x 放到外部函数的参数这样就不会将参数固定死 def inner(): print(x) 思路:闭包函数就是局部作用域和全局作用域的使用, 查找循序在定义阶段已经确定好,不会因为函数的调用位置的变化而变化

    1.2 传参的两种方式:

     

1.直接传参:
def inner(name):
print(name)
2.通过闭包:内部函数数引用外部函数的变量(作用域)
  def outter(name): # 为了让变量是一个不固定死的函数将name 传入外部函数括号
    # name = 'coco' # 外部非全局作用域 怎么做
     def inner():
        print(name)
     #如何
      

如图闭包函数的执行过程::

 

 inner 和res  就好比一座桥梁 建立在外部调用res()—— 让内部inner()函数执行def inner()的关键

应用场景:

小爬虫
爬虫的本质就是爬取页面的html代码
从中获取到你想要的数据(url链接地址)
有了链接之后 你就可以顺着这个链接将所有的页面资源全部爬取下来

 

  二、函数装饰器

     2.1 定义:器 》》》就是一个工具

       装饰》》》给被装饰对象添加新的功能

    2.2 为什么要用装饰器:因为现在我们在写项目的时候不可能一次性把所有的=功能都全部写完或则上线前客户需求改变,需要对函数添加新功能。那此时必须要用闭包函数,装饰器也是闭包函数的一种体现。

那我们在修改项目写装饰器之前,一定要遵循的了两个原则一个开放封闭原则。软件开发都应该遵循开放封闭原则。

开放封闭原则
对扩展是开放:>>>>何为?就是对项目的拓展功能是开放的,可以进行添加新的功能
对修改是封闭的:>>>>何为?就是对原函数的源代码和调用方式是封闭的
为什么说要对扩展是开放的呢?
因为软件开发过程不可能一次性把所有的功能都考虑完全,肯定会有不同的新功能需要不停添加。也就是说需要我们不断地去扩展已经存在代码的功能,
这是非常正常的情况。
那为什么说对修改是封闭的呢?
比如说已经上线运行的源代码,比如某个函数内部的代码是不建议直接修改的。因为函数的使用分为两个阶段:函数的定义阶段和函数的调用阶段。
因为你不确定这个函数究竟在什么地方被调用了,你如果粗暴的修改了函数内部的源代码,对整个程序造成的影响是不可控的。
总结一下就是:不修改源代码,不修改调用方式,同时还要加上新功能。
在Python中就可以使用装饰器来实现上面的需求。
注意:如果你能够保证自己的每一次修改都是准确无误、万无一失的,那你可以直接修改源代码。
什么是装饰器?
从字面上讲它也是一个工具,装饰其他对象(可调用对象)的工具。
装饰器的本质
装饰器本质上可以是任意可调用对象,被装饰的对象也可以是任意可调用对象。

 

    结论:

    2.3 装饰器(可调用对象)必须遵循的两个原则:

      1.不可以改变被装饰对象的源代码

      2.不可改变被装饰对象(可调用对象)调用方式

    2.4 装饰器的实际应用:

      1.无参装饰器

# 装饰器:为何用装饰器:
from functools import wraps
def outer(func):
@wraps(func)
def inner(username,pwd):
# 这里可以添加在原函数执行执行的功能()
# 验证用户名是字符大于6
if not (len(username) >= 6 and username.isalpha()):
return False,'用户名输入不合法'
res = func(username,pwd)
# 验证密码大于6
# 这里可以添加原函数执行之后的功能()
if not len(pwd)>6:
return False,'失败'
return res
return inner # 为了让外部调用巧妙设计
@outer
def login(username, pwd):
if not (username == 'jasonn' and pwd == '1234567'):
return False,'登录失败'
return True, '登录成功'
rs =login('jasonn','1234567') # 执行函数的传参必须符合我们我们自己装饰添加功能的限制条件


print(rs) # (True, '登录成功')

 

 

  从上面可以看出来装饰器的强大之处   

 2.有参数装饰器:用法和无参装饰器的基本一模一样,无法区别于在最外层套了一个可以进行传参。外界可以进行传参。

 

 3.wrapper()的修复技术

 

      3.多层装饰器

def outter1(func1):
print('加载了outter1')
def wrapper1(*args, **kwargs):
print('执行了wrapper1')
res1 = func1(*args, **kwargs)
return res1
return wrapper1
def outter2(func2):
print('加载了outter2')
def wrapper2(*args, **kwargs):
print('执行了wrapper2')
res2 = func2(*args, **kwargs)
return res2
return wrapper2
def outter3(func3):
print('加载了outter3')
def wrapper3(*args, **kwargs):
print('执行了wrapper3')
res3 = func3(*args, **kwargs)
return res3
return wrapper3
@outter1 # index = outter1(wapper2)
@outter2 # wrapper2 = outter2(wrapper3)
@outter3 # wrapper3 = outter3(最原始的index函数内存地址)
def index():
print('from index')
"""
加载了outter3
加载了outter2
加载了outter1
执行了wrapper1
执行了wrapper2
执行了wrapper3
from index
"""
index()

 


3.装饰器的嵌套
1.装饰的时候 从下往上执行(******)
@outter1 # index = outter1(func2)
@outter2 # func2 = outter2(func1)
@outter3 # func1 = outter3(index)
def index():
pass

 

 

  三、装饰器语法糖

2.有参装饰器(最复杂就三层)
def wrappers(data):
# data = 'file'
def outter(func):
def inner(*args,**kwargs):
if data == 'file':
# 执行被装饰函数之前你可以做的操作
res = func(*args,**kwargs) # * **在实参中使用
# 执行被装饰函数之后你可以做到操作
return res
return inner
return outter

 

 

 

  四、作业

  

一:编写函数,(函数执行的时间是随机的)
二:编写装饰器,为函数加上统计时间的功能
三:编写装饰器,为函数加上认证的功能

四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式

五:编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录

六:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果

七:为题目五编写装饰器,实现缓存网页内容的功能:
具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中

扩展功能:用户可以选择缓存介质/缓存引擎,针对不同的url,缓存到不同的文件中

八:还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作

九 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到日志文件中,日志文件路径可以指定
注意:时间格式的获取
import time
time.strftime('%Y-%m-%d %X')


推荐阅读
  • Python15行代码实现免费发送手机短信,推送消息「建议收藏」
    Python15行代码实现免费发 ... [详细]
  • 提升Python编程效率的十点建议
    本文介绍了提升Python编程效率的十点建议,包括不使用分号、选择合适的代码编辑器、遵循Python代码规范等。这些建议可以帮助开发者节省时间,提高编程效率。同时,还提供了相关参考链接供读者深入学习。 ... [详细]
  • 本文介绍了如何使用python从列表中删除所有的零,并将结果以列表形式输出,同时提供了示例格式。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • Python基础知识:注释、输出和input交互
    本文介绍了Python基础知识,包括注释的使用、输出函数print的用法以及input函数的交互功能。其中涉及到字符串和整数的类型转换等内容。 ... [详细]
  • Python教学练习二Python1-12练习二一、判断季节用户输入月份,判断这个月是哪个季节?3,4,5月----春 ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • iOS Swift中如何实现自动登录?
    本文介绍了在iOS Swift中如何实现自动登录的方法,包括使用故事板、SWRevealViewController等技术,以及解决用户注销后重新登录自动跳转到主页的问题。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
author-avatar
S_o_m_n_u_211
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有