装饰器

1.1 开放封闭原则

开放封闭原则具体定义是这样:

1.对扩展是开放的

我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

2.对修改是封闭的

因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对函数内部进行修改,或者修改了函数的调用方式,很有可能影响其他已经在使用该函数的用户。

定义:在不改变原被装饰的函数的源代码以及调用方式下,为其添加额外的功能。

实现真正的开放封闭原则:装饰器。

运用闭包原理:

import time
def index():
    time.sleep(2)  # 模拟一下网络延迟以及代码的效率
    print('这是一个主页')

def access_index(name):
    time.sleep(3)  # 模拟一下网络延迟以及代码的效率
    print(f'欢迎访问{name}主页')

套一层最外面的函数timer,然后将里面的inner函数名作为最外面的函数的返回值

def timer(func):  # func = index
    def inner():
        start_time = time.time()
        func()
        end_time = time.time()
        print(f'此函数的执行效率为{end_time-start_time}')
    return inner
# f = timer(index)
# f()

我们分析一下代码,代码执行到这一行:f = timer(index) 先执行谁?看见一个等号先要执行等号右边, timer(index) 执行timer函数将index函数名传给了func形参。内层函数inner执行么?不执行,inner函数返回 给f变量。所以我们执行f() 就相当于执行inner闭包函数。 f(),这样既测试效率又执行了原函数,有没有问题?当然有啦!!我们要解决原函数执行方式不改变的问题,怎么做? 所以你可以把 f 换成 index变量就完美了! index = timer(index) 特别要注意 函数外面的index实际是inner函数的内存地址而不是index函数。这个timer就是最简单版本装饰器,在不改变原index函数的源码以及调用方式前提下,为其增加了额外的功能,测试执行效率。

1.2标准版装饰器

def wrapper(func):
    def inner(*args,**kwargs):
        '''执行被装饰函数之前的操作'''
        ret = func(*args,**kwargs)
        '''执行被装饰函数之后的操作'''
        return ret
    return inner
import time
def wrapper(f):
    def inner(*args,**kwargs):
        start = time.time()     #调用函数之前的操作
        f(*args,**kwargs)
        end = time.time()
        print(end - start)  #调用函数之后的操作
    return inner

def func(*args,**kwargs):
    time.sleep(0.5)
    print(f"{args[0]}暴打{args[1]}页面!")

func = wrapper(func)
func("章超印","煞笔周道镕")

语法糖:@xxx

import time
def wrapper(f):
    def inner(*args,**kwargs):
        start = time.time()     #调用函数之前的操作
        f(*args,**kwargs)
        end = time.time()
        print(end - start)  #调用函数之后的操作
    return inner

@wapper     # 等于 func = wapper(func)
def func(*args,**kwargs):
    time.sleep(0.5)
    print(f"{args[0]}暴打{args[1]}页面!")

# func = wapper(func)
func("章超印","煞笔周道镕")

带参数的装饰器:

在装饰器的基础上再套一层

你现在要完成的就是你的装饰器要分情况去判断账号和密码,不同的函数用的账号和密码来源不同。 但是你之前写的装饰器只能接受一个参数就是函数名,所以你写一个可以接受参数的装饰器。

dic = {
    "flag":False,
    "username":None

}
msg ="""
QQ
微信
抖音
邮箱
>>>
"""
choose = input(msg).upper()
def auth(argv):
    def wrapper(func):
        def inner(*args, **kwargs):
            if dic["flag"]:
                foo(*args, **kwargs)
            else:
                if argv == "QQ":
                    print("欢迎来到QQ!")
                    user = input("username:")
                    pwd = input("password:")
                    if user == "zcy1" and pwd == "123":
                        dic["flag"] = True
                        dic["username"] = user
                elif argv == "微信":
                    print("欢迎来到微信!")
                    user = input("username:")
                    pwd = input("password:")
                    if user == "zcy2" and pwd == "1234":
                        dic["flag"] = True
                        dic["username"] = user
                elif argv == "抖音":
                    print("欢迎来到抖音!")
                    user = input("username:")
                    pwd = input("password:")
                    if user == "zcy3" and pwd == "12345":
                        dic["flag"] = True
                        dic["username"] = user
                else:
                    print("欢迎来到邮箱!")
                    user = input("username:")
                    pwd = input("password:")
                    if user == "zcy4" and pwd == "123456":
                        dic["flag"] = True
                        dic["username"] = user
            ret = func(*args, **kwargs)
            return ret
        return inner
    return wrapper

@auth(choose)
# wrapper = auth(choose)
# foo = wrapper()
def foo():
    return "我不管,章超印超帅!"

# @auth(choose)  等于下面的两行
# wrapper = auth(choose)
# foo = wrapper()
print(foo())

@auth('choose') :分两步:

第一步先执行auth('choose')函数,得到返回值wrapper

第二步@与wrapper结合,形成装饰器@wrapper然后在依次执行。

这样就是带参数的装饰器,参数可以传入多个

2.多个装饰器装饰一个函数

被装饰的函数正上方有多个装饰器,先执行离被装饰函数最近的装饰器

我们现在知道标准装饰器和带参数的装饰器,我们来看看多个装饰器装饰一个函数:

def wrapper1(func):
    def inner1(*args,**kwargs):
        print("这是装饰器一开始")
        func(*args,**kwargs)
        print("这是装饰器一结束")
    return inner1

def wrapper2(func):
    def inner2(*args,**kwargs):
        print("这是装饰器二开始")
        func(*args,**kwargs)
        print("这是装饰器二结束")
    return inner2

@wrapper1
@wrapper2
def func():
    print("这是被装饰的函数")

func()

大家来推断一下,这个的打印结果

这是装饰器一开始
这是装饰器二开始
这是被装饰的函数
这是装饰器二结束
这是装饰器一结束
 先执行离被装饰的函数最近的语法糖
# 小技巧:进入装饰器从上往下,走到最会一个装饰器执行被装饰的函数,退出装饰器从下往上走

百万年薪python之路 -- 装饰器的更多相关文章

  1. 百万年薪python之路 -- 装饰器进阶

    本文链接:https://blog.csdn.net/xiemanR/article/details/72510885 一:函数装饰函数 def wrapFun(func): def inner(a, ...

  2. python之路--装饰器

    二 .通用装饰器的写法 python里面的动态代理. 存在的意义: 在不破坏原有的函数和原有函数的调用基础上,给函数添加新的功能 def wrapper(fn): # fn是目标函数. def inn ...

  3. python之路——装饰器函数

    阅读目录 楔子 装饰器的形成过程 开放封闭原则 谈装饰器主要功能和装饰器固定结构 带参数的装饰器 多个装饰器装饰一个函数 返回顶部 楔子 作为一个会写函数的python开发,我们从今天开始要去公司上班 ...

  4. 百万年薪python之路 -- 面向对象之所有属性及方法

    1.私有成员公有成员 1.1 类的私有属性 # class A: # # name = '周道镕' # __name = 'zdr' # 私有类的属性 # # def func(self): # pr ...

  5. 百万年薪python之路 -- 软件的开发规范

    一. 软件的开发规范 什么是开发规范?为什么要有开发规范呢? 你现在包括之前写的一些程序,所谓的'项目',都是在一个py文件下完成的,代码量撑死也就几百行,你认为没问题,挺好.但是真正的后端开发的项目 ...

  6. python之路---装饰器函数

    阅读目录 楔子 装饰器的形成过程 开放封闭原则 谈装饰器主要功能和装饰器固定结构 带参数的装饰器 多个装饰器装饰一个函数 返回顶部 楔子 作为一个会写函数的python开发,我们从今天开始要去公司上班 ...

  7. 百万年薪python之路 -- 闭包

    2.闭包 闭包的定义: 闭包是嵌套在函数中的函数. 闭包必须是内层函数对外层函数的变量(非全局变量)的引用. 一句话定义就是:在嵌套函数内,对非全局变量 (且不是本层的变量)的引用 如何判断判断闭包? ...

  8. 百万年薪python之路 -- 前端CSS样式

    CSS样式 控制高度和宽度 width宽度 height高度 块级标签能设置高度和宽度,而内联标签不能设置高度和宽度,内联标签的高度宽度由标签内部的内容来决定. 示例: <!DOCTYPE ht ...

  9. 百万年薪python之路 -- 面向对象之 反射,双下方法

    面向对象之 反射,双下方法 1. 反射 计算机科学领域主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省) python面向对象中的反射:通过字符串的形式操作对象相关的属性.python ...

随机推荐

  1. Linux 文件/目录操作详解

    目录 Linux 文件/目录操作详解 初识Linux 一.文件/目录显示命令 ls 二.目录创建命令 mkdir 三.目录转移命令 cd 四.当前目录显示命令 pwd 五.文件处理命令 rmdir 六 ...

  2. 一个js破解教程

    很好的一篇文章,先存着以后用到. 为了防止官网更新修复,存一下版本 https://pan.lanzou.com/b220073/ 密码:这是秘密 这篇文章以 JavaScript 为例讲解了破解的一 ...

  3. 基于操作系统原理的Webmin管理工具的安装使用

    一.实验目的 1.了解Webmin管理工具的功能. 2.掌握Webmin的安装. 3.掌握Webmin管理工具的使用 二.实验内容 1.下载Webmin安装包. 2.在Linux主机中安装Webmin ...

  4. 基于Docker搭建大数据集群(一)Docker环境部署

    本篇文章是基于Docker搭建大数据集群系列的开篇之作 主要内容 docker搭建 docker部署CentOS 容器免密钥通信 容器保存成镜像 docker镜像发布 环境 Linux 7.6 一.D ...

  5. Spring Boot 梳理 - 4个核心

    Spring Boot 魔法的核心:自动配置.起步依赖.命令行界面.Actuator 自动配置: 不用手动配置JdbcTemplate的Bean 不用手动配置DataSource的Bean Sprin ...

  6. RecyclerView实现Gallery画廊效果

    使用RecyclerView实现一个画廊效果,主要是使用support库中最新加入的PagerSnapHelper类,通过计算滑动偏移来计算scale的值. 基本实现 首先需要为RecyclerVie ...

  7. poi下载excel模板

    /** * 下载模板 * @param tplName * @param returnName * @param response * @param request * @throws Excepti ...

  8. WebGL简易教程(六):第一个三维示例(使用模型视图投影变换)

    目录 1. 概述 2. 示例:绘制多个三角形 2.1. Triangle_MVPMatrix.html 2.2. Triangle_MVPMatrix.js 2.2.1. 数据加入Z值 2.2.2. ...

  9. C++——指针

    目录 一.地址和指针 1.1内存 1.2针和指针变量 二.指针变量 2.1始化 2.2赋值 2.3指针类型算术运算 2.4指针类型关系运算 2.5指向指针的指针 三.指针与数组 3.1指针运算 3.2 ...

  10. python正则表达式贪婪算法与非贪婪算法与正则表达式子模式的简单应用

    先引入一下百度百科对于正则表达式的概念: 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种 ...