一.闭包函数

1.闭函数:被封闭起来的函数==>定义在函数内部的函数,特点是只能在函数内调用

2.包函数:该函数引用了一个名字,该名字来自于E这一层

  总结:闭包函数指的是定义在函数内部的函数引用了一个来自于外层函数作用域中的名字

#例如wrapper函数
# def outter():
# x = 100
# def wrapper():
# print(x)

3.闭包函数升级:结合函数对象

# def outter():
# x = 100
# def wrapper():
# print(x)
# return wrapper # 千万不要加括号
#
# f = outter()
#
# print(f)
#
# def foo():
# x = 666
# f()
#
# foo()

4.为函数体传参的两种解决方案

方案一:直接以参数的形式传入

# def wrapper(x):
# print(x)
#
# wrapper(100)

方案二:闭包函数方式 

# def outter(x):
# # x = 100
# def wrapper():
# print(x)
# return wrapper # 千万不要加括号
#
# f = outter(100)
# f()

二.装饰器

1.什么是装饰器

    ’装饰’代指为被装饰对象添加新的功能

    ’器’代指器具/工具

但实现装饰器必须遵循的原则是:开放封闭原则

  开放指的是对拓展新功能是开放的,封闭指的则是对修改源代码以及调用方式是封闭的  

#综上装饰器指的是我们要创建一个工具,该工具可以在遵循原则1和2的前提下还能为被装饰对象添加新功能

        原则1、不修改被装饰对象源代码

        原则2、不修改被装饰对象调用方式

2.为什么要用装饰器

软件包含的所有功能的源代码以及调用方式,都应该避免修改,否则一旦改错,则极有可能产生连锁反应,最终导致程序崩溃,而对于上线后的软件,新需求或者变化又层出不穷,我们必须为程序提供扩展的可能性,这就用到了装饰器。

3.用法

**装饰器的推导**

# 被装饰者:给被装饰者添加新功能
# import time
#
# def index():
# print('from index')
# time.sleep(3)
#
# index() # 方案一:改变被装饰者的源代码
# import time
#
# def index():
# start = time.time()
# print('from index')
# time.sleep(1)
# end = time.time()
# print('run time is %s' %(end - start))
#
# index() # # 方案二:装饰器的功能需要重复编写,代码冗余
# import time
#
# def index():
# print('from index')
# time.sleep(1)
#
# start = time.time()
# index()
# end = time.time()
# print('run time is %s' %(end - start))
#
# start = time.time()
# index()
# end = time.time()
# print('run time is %s' %(end - start))
# # # 方案三:解决方案二的代码冗余问题,但是存在问题-》装饰器的功能写死了,只能装饰index函数
# import time
#
# def index():
# print('from index')
# time.sleep(1)
#
# def wrapper():
# start = time.time()
# index()
# end = time.time()
# print('run time is %s' %(end - start))
#
# wrapper()
# wrapper() # # 方案四:装饰器的功能写活
# import time
#
# def index():
# print('from index')
# time.sleep(1)
#
# def outter(func):
# # func = index
# def wrapper():
# start = time.time()
# func()
# end = time.time()
# print('run time is %s' %(end - start))
# return wrapper
#
# index = outter(index) # index = wrapper的内存地址
# # print(index)
# index() # 方案五:装饰器的功能写活
import time def index():
print('from index')
time.sleep(1) def home(name):
print('welcome %s to home page' % name)
time.sleep(0.5)
return 123 def outter(func):
# func = 最原始那个home的内存地址
def wrapper(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs) # 最原始那个home的内存地址()
end = time.time()
print('run time is %s' % (end - start))
return res
return wrapper home = outter(home) # home = wrapper的内存地址
index = outter(index) # home = wrapper的内存地址 res = home('egon')
print(res) # res = index()
# print(res)

**装饰器语法糖**(简化)

import time

def outter(func):
# func = 最原始那个home的内存地址
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs) # 最原始那个home的内存地址()
end = time.time()
print('run time is %s' % (end - start))
return res return wrapper @outter # index = outter(index)
def index():
print('from index')
time.sleep(1) @outter # home = outter(home)
def home(name):
print('welcome %s to home page' % name)
time.sleep(0.5)
return 123 res = home('lzl')
print(res)

**多个装饰器叠加**

# 装饰器模板
# def deco(func):
# def wrapper(*args,**kwargs):
# res = func(*args,**kwargs)
# return res
# return wrapper # 统计时间的装饰器
# import time
#
# def timmer(func):
# def wrapper(*args,**kwargs):
# start = time.time()
# res = func(*args,**kwargs)
# stop = time.time()
# print(stop - start)
# return res
# return wrapper # 认证功能装饰器
# def auth(func):
# def wrapper(*args,**kwargs):
# inp_user = input('Username: ').strip()
# inp_pwd = input('Password: ').strip()
# if inp_user == 'egon' and inp_pwd == '123':
# res = func(*args,**kwargs)
# return res
# else:
# print('登录失败')
# return wrapper
#
# @auth # index = auth(index)
# def index():
# print('from index')
#
# index() """
def deco1(func1): # func1 = wrapper2的内存地址
def wrapper1(*args,**kwargs):
print('===>wrapper1')
res1 = func1(*args,**kwargs)
print('=====>end wrapper1')
return res1
return wrapper1 def deco2(func2): # func2 = wrapper3的内存地址
def wrapper2(*args,**kwargs):
print('===>wrapper2')
res2 = func2(*args,**kwargs)
print('=====>end wrapper2')
return res2
return wrapper2 def deco3(func3): # func3 = 最原始那个index的内存地址
def wrapper3(*args,**kwargs):
print('===>wrapper3')
res3 = func3(*args,**kwargs)
print('=====>end wrapper3')
return res3
return wrapper3 # index = wrapper1的内存地址
@deco1 # deco1(wrapper2的内存地址) ---> wrapper1的内存地址
@deco2 # deco2(wrapper3的内存地址) ---> wrapper2的内存地址
@deco3 # deco3(最原始那个index的内存地址) ---> wrapper3的内存地址
def index():
print('=======>index') index()
""" # print(index) import time def timmer(func):
def wrapper1(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
stop = time.time()
print(stop - start)
return res
return wrapper1 def auth(func):
def wrapper2(*args,**kwargs):
inp_user = input('Username: ').strip()
inp_pwd = input('Password: ').strip()
if inp_user == 'egon' and inp_pwd == '123':
res = func(*args,**kwargs)
return res
else:
print('登录失败')
return wrapper2 @auth
@timmer
def index():
print('====>index')
time.sleep(3)
index()

 有参装饰器:

def outter2(mode,yyy):
# mode = 'mysql'
def outter(func): # func = index
def wrapper(*args ,**kwargs):
print(yyy)
inp_user = input('Username: ').strip()
inp_pwd = input('Password: ').strip()
if mode == 'file':
if inp_user == "egon" and inp_pwd == "123":
res = func(*args ,**kwargs)
return res
else:
print('login failed')
elif mode == 'mysql':
print("基于mysql数据库的认证")
elif mode == 'ldap':
print("基于ldap数据库的认证")
else:
print('未知的认证来源')
return wrapper
return outter @outter2('mysql',111) # @outter # index = outter(index) # index = wrapper
def index():
print('from index') @outter2('ldap',222)
def home(name):
print('hello %s' %name)

 ###functools模块下提供一个装饰器wraps专门用来保留原函数属性####

4.总结

1、无参装饰器模板

# def outter(func):
# def wrapper(*args,**kwargs):
# res = func(*args,**kwargs)
# return res
# return wrapper
#
# @outter
# def index():
# pass

2、有参装饰器模板

def outter2(xxx):
def outter(func):
def wrapper(*args,**kwargs):
xxx
res = func(*args,**kwargs)
return res
return wrapper
return outter @outter2(xxx=111)
def index():
pass

  

 

day10.闭包函数与装饰器的更多相关文章

  1. day11 闭包函数和装饰器

    1.函数不是新知识点 主要是学习函数的用法 在面向对象编程中,一切皆对象,函数也不例外 具体的表现 1.函数可以引用 2.函数可以作为函数的参数 3.函数可以作为函数的返回值 4.可以被存储到容器类型 ...

  2. python基础-闭包函数和装饰器

    闭包函数和装饰器 闭包函数 概念:在函数中(嵌套)定义另一个函数时,内部函数引用了外层函数的名字. 特性 闭包函数必须在函数内部定义 闭包函数可引用外层函数的名字 闭包函数是函数嵌套.函数对象.名称空 ...

  3. Python之函数对象、函数嵌套、名称空间与作用域、闭包函数、装饰器

    目录 一 函数对象 二 函数的嵌套 三 名称空间和作用域 四 闭合函数 五 装饰器 一.函数对象 1.函数是第一类对象 #第一类对象的特性:# 可以被引用 # 可以当做参数传递 # 返回值是函数 # ...

  4. 【Python3的命名空间与作用域,闭包函数,装饰器】

    一.命名空间与作用域 命名空间是名字和对象的映射,就像是字典,key是变量名,value是变量的值 1.命名空间的定义 name='egon' #定义变量 def func(): #定义函数 pass ...

  5. day11_7.11 闭包函数与装饰器

    补充: callable 代表可调用的,加括号可以执行.(函数或者类) import this  查看python之禅 一.闭包函数 所谓闭包函数,就是定义在函数内部的函数,也就是函数定义的嵌套.而在 ...

  6. CSIC_716_20191112【闭包函数和装饰器】

    闭包函数 什么是闭包函数:闭包函数是函数嵌套.函数对象.名称空间和作用域的集合体. 闭包函数必须在函数内部定义,闭包函数可以引用外层函数的名字. # _*_ coding: gbk _*_ # @Au ...

  7. Python--day13(函数嵌套定义,global、nonlocal、闭包函数、装饰器)

    今日主要内容 1.  函数的嵌套定义 2.  global.nonlocal关键字 3.  闭包及闭包的应用场景 4. 装饰器 1.  函数的嵌套定义 概念:在一个函数的内部定义另一个函数 为什么要有 ...

  8. python---基础知识回顾(二)(闭包函数和装饰器)

    一.闭包函数: 闭包函数: 1.在一个外函数中定义了一个内函数 2.内函数里运用了外函数的临时变量,而不是全局变量 3.并且外函数的返回值是内函数的引用.(函数名,内存块地址,函数名指针..) 正确形 ...

  9. Python之闭包函数、装饰器

    1.闭包函数 #作用域关系在函数定义阶段时就已经固定死了,与调用位置无关 # 即:在任意位置调用函数都需要跑到定义函数时寻找作用域关系 # def f1(): # x=1 # def inner(): ...

随机推荐

  1. 死磕Spring之IoC篇 - BeanDefinition 的解析阶段(XML 文件)

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...

  2. WPF 数据绑定实例一

    前言: 数据绑定的基本步骤: (1)先声明一个类及其属性 (2)初始化类赋值 (3)在C#代码中把控件DataContext=对象: (4)在界面设计里,控件给要绑定的属性{Binding 绑定类的属 ...

  3. 微信小程序(二十)-UI组件(Vant Weapp)-01按装配置

    1.官网 https://vant-contrib.gitee.io/vant-weapp/#/intro https://gitee.com/vant-contrib/vant-weapp 2.按装 ...

  4. 京东数科二面:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?

    IO 模型这块确实挺难理解的,需要太多计算机底层知识.写这篇文章用了挺久,就非常希望能把我所知道的讲出来吧!希望朋友们能有收货!为了写这篇文章,还翻看了一下<UNIX 网络编程>这本书,太 ...

  5. Vue脚手架中默认的margin怎么清除

    问题情景:开发中发现我的项目四周有白边,但是并没有设置样式 问题原因:vue脚手架中静态文件夹public中的index.html造成的 解决方案:找到vue脚手架中index.html页面,设置ma ...

  6. WPF权限控制框架——【4】抛砖引玉

    写第一篇"权限控制框架"系列博客是在2021-01-29,在这不到一个月的时间里,收集自己零碎的时间,竟然写出了一个"麻雀虽小,五脏俱全"的权限控制框架:对于一 ...

  7. Java基础自学小项目

    实现一个基于文本界面的<家庭记账软件> 需求:能够记录家庭的收入,支出,并能够收支明细表 主要涉及一下知识点: - 局部变量和基本数据类型 - 循环语句 - 分支语句 - 方法调用和返回值 ...

  8. How DRI and DRM Work

    How DRI and DRM Work Introduction This page is intended as an introduction to what DRI and DRM are, ...

  9. createNewFile() 报错 open failed: ENOENT (No such file or directory) 的解决方案

    在写Android应用中使用createNewFile() 遇到open failed: ENOENT (No such file or directory) 错误,在网上查了许多方法,不过都不能解决 ...

  10. android 调用js,js调用android

    Java调用JavaScript   1.main.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml v ...