首页 > 编程语言 >装饰器+闭包掌握(python一大重要功能)

装饰器+闭包掌握(python一大重要功能)

时间:2022-10-11 18:58:15浏览次数:50  
标签:闭包 func2 func1 python inner time print 装饰 def

目录

global与nonlocal

global  # 提升全局变量关键字,在函数内使用
name = '123'
def func()
	name = '1111'
func()
print(name)  # 123 

可变数据类型可以在函数内直接修改不要提升全局变量关键字就可以使用

a = [1,2,3]
def func()
	a.append(4)
func()
print(a) [1,2,3,4]


# 在不重新修改命名空间变量赋值的情况下,更改数据值

name = '123'
def func():
    global name
    name = 'zhang'
func()
print(name)  # zhang

nonlocal  # 嵌套函数内使用外部函数变量,在函数嵌套内使用

def outer():
    name = '123'
    def index():
        name = '111'
	print(name)  # '123'

def outer():
    name = '123'
    def index():
        nonlocal name
        name = '111'
	print(name)  # '111' 

函数名的多种用法

1.当作数据值
def func():
    print(123)
func2 = func
print(fun2)  # <function func2 at 0x000001D4D4069A60>
2.当作参数传递
def func1():
    print(1)
def func2(v1):
    print(v1)
func2(func1)  # <function func1 at 0x000002540EDF9A60>
3.当作返回值
def func1():
    print(1)
def func2():
    print(123)
    return func1
res = func2()
print(res)  # 123 <function func1 at 0x0000013B51BE9A60>
4.当做容器的数据值
def register():
    print('注册')
def login():
    print('登录')
def withdraw():
    print('提现')
def transfer():
    print('转账')
def shopping():
    print('购物')
    
d1 = {
    '1':register,
    '2':login,
    '3'withdraw,
    '4':transfer,
    '5':shopping
}    
while True:
    choice = input('选着编号')
    if choice not in d1;
    	print('功能不存在')
    res = d1.get('choie')
    res()

    

闭包函数

闭包的定义:
	1.在函数内定义函数
    2.使用外部变量名
    例如
    def outer():
        name = '123'
        def inner():
            print(name)  
    # 尽管没有调用,也叫闭包,因为函数在定义的时候就已经确定了名字查找顺序了
闭包的应用场景:
    是另外一种给函数传参的方式
    
    给函数传值的方式一:
    	直接传递参数
        def func(a):
            print(a)
        func(123)
    给函数另一种方式二:
    	闭包传值
        def func():
            name = '123'
            pwd = '456'
            def func2():
                print(name,pwd)
            func2()
        func()  # 123 456  # 写死了不好
    	
        # 可以这样
        def func(name,pwd):
            def inner()
            	print(name,pwd)
    	func(zhang,123)  # zhang 123
     
    
    
    name = '123'
    def func1():
        print(name)
    def func2():
        name = 111
        func1()
    func2()  # 123 函数调用使用变量名,跟在哪调用没关系,而是跟函数定义时的位置有关系
    

装饰器简介

1.概念

在不改变原有功能和调用方式的前提下实现新增功能

2.本质

​ 装饰器并不是一们新的技术,而是由函数,参数,返回值,变量名,命名空间,函数名多种用法,闭包组合到一起的结果

3.口诀

​ 对修改封闭 对扩展开放

4.超前知识time模块

time模块
如何导入模块
1.import 模块名
2.from 模块名 import 类\函数
time模块的使用
import time
time.time()  # 获取当前时间距1970 1 1 0:0 的时间为浮点型 1665475010.6782117

time.sleep(0.5)  # 运行到这一行暂停0.5秒


装饰器推导

import time
def func():
    time.sleep(0.5)
    print('func')

start_time = time.time()
func()
end_time = time.time()
print(f'运行函数耗时{end_time-start_time}')  # 运行函数耗时0.5023610591888428
# 如果需要在多个地方统计这一个函数就需要多次写了,太麻烦了
# 我直接科技很活 我闭包在套一层,先试一下


def func():
    time.sleep(0.5)
    print('func')
    
def func2():
	start_time = time.time() 
    func()
    end_time = time.time()
    print(f'运行函数耗时{end_time-start_time}')
    
    
func2()
func2()
# 哦可以了方便了
# 现在我又新的需求了,有好多个函数需要及时,这个时候怎么办,
# 我直接写多个函数,用来了用,感觉还是太麻烦了,诶,我想到了,可以直接把,需要统计的函数名,我直接传递给这个让他来,这样就不要写多个了,方便哈哈哈哈。试一下

def func1():
    time.sleep(0.5)
    print('func1')
    
def func2():
    time.sleep(0.5)
    print('func2')
    
def outer(funcs):
	start_time = time.time() 
    funcs()
    end_time = time.time()
    print(f'运行函数耗时{end_time-start_time}')

outer(func1)
'''
func1
运行函数耗时0.5023987293243408
'''
outer(func2)
'''
func2
运行函数耗时0.514385461807251
'''
# 这样是可以了但是改变调用了啊
# 嗯对,我在改改,那我再套一程把他返回出去

def func1():
    time.sleep(0.5)
    print('func1')
    
def func2():
    time.sleep(0.5)
    print('func2')
    
def outer(funcs):
    def inner():
        start_time = time.time() 
        funcs()
        end_time = time.time()
        print(f'运行函数耗时{end_time-start_time}')
    return inner  # 返回的是inner 的内存地址

func1 = outer(func1)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了,狸猫换太子
func1()  # 其实是调用inner的内存地址存放的代码
'''
func1
运行函数耗时0.5052452087402344
'''
func2 = outer(func2)
func2()
'''
func2
运行函数耗时0.5050647258758545
'''



# 嗯very good 很好 但是我现在我给你个函数需要一个参数,你在这样还可以吗?
# 我逝一下 
'''
def func1(a):
    time.sleep(0.5)
    print('func1')
    
def func2():
    time.sleep(0.5)
    print('func2')
    
def outer(funcs):
    def inner():
        start_time = time.time() 
        funcs()
        end_time = time.time()
        print(f'运行函数耗时{end_time-start_time}')
    return inner  # 返回的是inner 的内存地址

func1 = outer(func1)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了
func1()  # 其实是调用inner的内存地址存放的代码

TypeError: func1() missing 1 required positional argument: 'a'
'''
#啊寄,报错了,我看看什么错,哦原来是需要一个参数,让我see 一 see 怎么解决,
# 既然你需要,那我就直接给你
'''
def func1(a):
    time.sleep(0.5)
    print('func1')
    
def outer(funcs): 
    def inner(a):  # 我给你
        start_time = time.time() 
        funcs()
        end_time = time.time()
        print(f'运行函数耗时{end_time-start_time}')
	return inner
func1 = outer(func1)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了
func1(1)  # 其实是调用inner的内存地址存放的代码
TypeError: inner() missing 1 required positional argument: 'a'
'''
# 欸还是寄,怎么回事,哦没给原来的传啊,好的我加上
def func1(a):
    time.sleep(0.5)
    print('func1',a)
    
def func2(aa,bb):
    time.sleep(0.5)
    print('func2',aa,bb)
def outer(funcs): 
    def inner(a):
        start_time = time.time() 
        funcs(a)  #这里我加上
        end_time = time.time()
        print(f'运行函数耗时{end_time-start_time}')
	return inner
func1 = outer(func1)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了
func1(1)  # 其实是调用inner的内存地址存放的代码
'''
func1 1
运行函数耗时0.5107102394104004
'''
func2 = outer(func2)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了
func2(1,2)  # 其实是调用inner的内存地址存放的代码

'''
TypeError: inner() takes 1 positional argument but 2 were given
'''
#很好,成功啦,但没完全成功
#我再想想,想到了,可以用上次说到的,可变长形参呀,还有可变长实参。这样就可以了呀,好的,开始写代码

def func1(a):
    time.sleep(0.5)
    print('func1',a)
    
def func2(aa,bb):
    time.sleep(0.5)
    print('func2',aa,bb)
def outer(funcs): 
    def inner(*args,**kwargs):
        start_time = time.time() 
        funcs(*args,**kwargs)  #这里我加上
        end_time = time.time()
        print(f'运行函数耗时{end_time-start_time}')
	return inner
func1 = outer(func1)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了
func1(1)  # 其实是调用inner的内存地址存放的代码
'''
func1 1
运行函数耗时0.5107102394104004
'''
func2 = outer(func2)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了
func2(1,2)  # 其实是调用inner的内存地址存放的代码
'''
func2 1 2
运行函数耗时0.5015923976898193
'''
# 嘿嘿嘿,成功啦,成功啦,完全成功了
# 别高兴太早了,我还有需求呢,我有个函数有返回值,你看你的还能用吗?
def func1(a):
    time.sleep(0.5)
    print('func1',a)


def func2(aa,bb):
    time.sleep(0.5)
    print('func2',aa,bb)

def func3(ab,ac):
    print('func3',ab,ac)
    return ab

def outer(funcs):
    def inner(*args,**kwargs):
        start_time = time.time()
        funcs(*args,**kwargs)  # 这里我加上
        end_time = time.time()
        print(f'运行函数耗时{end_time - start_time}')
    return inner


func1 = outer(func1)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了,
func1(1)  # 其实是调用inner的内存地址存放的代码
'''
func1 1
运行函数耗时0.5107102394104004
'''
func2 = outer(func2)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了
func2(1,2)  # 其实是调用inner的内存地址存放的代码
'''
func2 1 2
运行函数耗时0.5015923976898193
'''
func3 = outer(func3)
res = func3('a','b') # 接收返回值啊
'''
None
'''
print(res)
# 额,好像不太行啊,我see see 该怎么做
# 那我可以直接接收真实函数的返回值,然后我再通过狸猫换太子的方式,我给再给他,返回出去啊,ok,想到了就要搞,开搞

def func1(a):
    time.sleep(0.5)
    print('func1',a)


def func2(aa,bb):
    time.sleep(0.5)
    print('func2',aa,bb)

def func3(ab,ac):
    print('func3',ab,ac)
    return ab

def outer(funcs):
    def inner(*args,**kwargs):
        start_time = time.time()
        res = funcs(*args,**kwargs)  # 这里我加上
        end_time = time.time()
        print(f'运行函数耗时{end_time - start_time}')
        return res
    return inner


func1 = outer(func1)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了,
func1(1)  # 其实是调用inner的内存地址存放的代码
'''
func1 1
运行函数耗时0.5107102394104004
'''
func2 = outer(func2)  # 这样就修改了变量名的绑定了,看起来就跟原来一样了
func2(1,2)  # 其实是调用inner的内存地址存放的代码
'''
func2 1 2
运行函数耗时0.5015923976898193
'''
func3 = outer(func3)
'''
运行函数耗时0.0
a
'''
# ok完成了。
# 结束但是还可以优化,下次再讲吧


装饰器模板

def outer(func):
    def inner(*args,**kwargs):
        
        res = func(*args,**kwargs)
        
        return res
    return inner

res = outer(func)

装饰器语法糖

def outer(func):
    def inner(*args,**kwargs):
        name = input('用户名')
        if name == 'zhang':
            res = func(*args,**kwargs)
            return res
        else:
            print('姓名不对')
    return inner

@outer  # 语法糖
def func1(v1):
    print('func1',v1)

作业

标签:闭包,func2,func1,python,inner,time,print,装饰,def
From: https://www.cnblogs.com/clever-cat/p/16780238.html

相关文章

  • Java设计模式之 装饰模式实验报告书
    Java设计模式之装饰模式实验报告书姓名:班级:学号:实验三:装饰模式的应用一、实验目的熟练使用JAVA实现装饰模式,理解设计模式的模式动机,掌握模式结构,学习如何使用代码实现......
  • 函数装饰器
    global与nonlocalmoney=666defindex():globalmoneymoney=123index()print(money)"""局部名称空间直接修改全局名称空间中的数据"""defindex(......
  • 41. JS闭包的原理和作用
    1.前言闭包(closures)是Javascript语言的一个难点,也是它的特色,很多高级应用都是依靠闭包实现的。闭包与变量的作用域以及变量的生命周期密切相关,本节我们就来简单介绍一......
  • 将Curl转为Python的方法
    怎样将Curl转为Python的方法作为一名后端程序员,在服务器调试的过程中,使用curl命令为我们调试接口带来了很多的方便,极大地提高了效率;如下可以实现Get请求:curl'http://ba......
  • 函数名的多种用法及装饰器
    目录global与nonlocal函数名的多种用法闭包函数装饰器简介装饰器推导流程装饰器模板装饰器语法糖作业global与nonlocalmoney=666defindex():globalmoneym......
  • python | scrapy
    进入某网页的步骤分为域名解析,找到域名对应的ip地址向ip地址的服务器发送请求服务器响应,返回内容(html/json浏览器解析网页内容爬虫即实现浏览器功能,通过发送请求而......
  • Python pdb模块的使用
    野路子出生,写Python也有段时间了,一般的调试都用的print,PyCharm的debug功能也用的比较少,主要一般也用不到,第二是自己也不怎么会用. 服务器开发,本地根本没有运行的环境,......
  • 装饰器
    目录前言函数名的多种用法闭包函数补充time模块时间戳装饰器概念装饰器模板使用装饰器模板装饰器推导过程前言函数名的多种用法#1.函数名是名字defindex():p......
  • python第十二课---
    昨日内容回顾函数参数"""短的简单的靠前长的复杂的靠后同一个形参在调用的过程中不能多次赋值"""位置参数 位置形参 函数定义阶段括号内依次填写的变量名......
  • python中items()函数作用
    参考链接:https://www.runoob.com/python3/python3-att-dictionary-items.htmlhttps://blog.csdn.net/weixin_43505418/article/details/115407835......