首页 > 其他分享 >函数对象与闭包函数与装饰器

函数对象与闭包函数与装饰器

时间:2022-10-11 20:56:47浏览次数:39  
标签:闭包 index 函数 func time print 装饰 def

目录

一.global与nonlocal

global关键字:
若要在函数内修改全局名称空间中的"名字"的值,当值为不可变类型时,则需要添加global关键字。若值为可变类型则不需要

# 修改a的值
a = 123  
def index():
    global a  # 声明修改的是全局名称空间中的a,而不是产生新的a
    a = 666
index()
print(a)  
# 666

nonlocal:
若嵌套多层函数时,内层函数想要修改外层函数局部名称空间中‘名字’的值,可以使用nonlocal关键字(非全局)

a = 10
def func():
    a = 1  # 局部变量a
    def func1():
		nonlocal a  # 声明修改的时外层局部名称空间的a 而不是产生新的a
    	a = 2  # 将值2重新赋值给a
    func1()  # 调用func1
    print(a) # 此时func()函数代码体中的变量a被func1()重新赋值2
func()  # 调用函数func
# 2
print(a)  # 这是全局空间的a
# 10

注意:
​ 使用global关键字修饰的变量之前可以并不存在,而使用nonlocal关键字修饰的变量在嵌套作用域中必须已经存在,否则会报错。

二.函数名的多种用法

​ 函数名其实绑定的也是一块内层地址,只不过该地址里面存放的不是数据值而是一段代码,函数名加括号就会找到该代码并执行

1.可以当做变量名赋值

def index():
    print('哈哈哈')
res = index  # 将index赋值给res
res()  # 调用index函数 其实就等于index()
# 哈哈哈

2.可以当做函数的参数

def index():
    print('from index')
def func(a):
    print(a)
    a()
func(index)  # 此时就是将函数index作为实参和形参a对应
# from index

3.可以当做函数的返回值

def index():
    print('from index')

def func():
    print('from func')
    return index
res = func()  
# 调用函数func 先执行print('from func') 然后返回值index 此时返回的是index函数 然后执行print('from index')
print(res)  # 等同于prin(index)
res()
# from func
# 打印res内存地址
# from index
-------------------------------------------------------------------
def index():
    print('from index')  # 先执行
    def func():
        print('from func')
    return func	 # 返回func
res = index()  # 此时index()就是内层函数func()
print(res)
res()
# from index
# 打印res内存地址
# from func

4.可以当做容器类型的数据

def register():
    print('注册功能')
  
def login():
    print('登录功能')
      
def withdraw():
    print('提现功能')
     
def transfer():
    print('转账功能')
      
def shopping():
    print('购物功能')

# 定义功能编号与功能的对应关系
func_dict = {
    '1': register, 
    '2': login, 
    '3': withdraw, 
    '4': transfer, 
    '5': shopping
}
while Ture:
    print("""
    1.注册功能
    2.登录功能
    3.提现功能
    4.转账功能
    5.购物功能
    """)
    choice = input('输入功能编号>>>:').strip()
    if choice in func_dict:
        func_name = func_dict.get(choice)
        func_name()
    else:
        print('功能编号不存在')
    if choice == '1':
        register()
    elif choice == '2':
        login()
    elif choice == '3':
        withdraw()
    elif choice == '4':
        transfer()
    elif choice == '5':
        shopping()
    else:
        print('没有该功能') 

三.闭包函数

概念:

​ 定义在函数内部的函数,并且用到了外部函数名称空间中的名字
​ 1.定义在函数内部
​ 2.用到外部函数名称空间中的名字

def index():
    name = 'jason'
    def innder():
        print(name)

​ 闭包函数实际应用>>>:是另外一种给函数体代码传参的方式!!!

给函数体代码传参的方式1:代码里面缺什么变量名形参里面就补什么变量名
def register(name, age):
    print(f"""
    姓名:{name}
    年龄:{age}
    """)
    register('jason', 18)
    
给函数体代码传参的方式2:闭包函数
def outer(name, age):
    # name = 'jason'
    # age = 18
    def register():
        print(f"""
        姓名:{name}
    	年龄:{age}
        """)
    return register
res = outer('jason', 18)
res()
res()
res = outer('kevin', 28)
res()
res()

四.装饰器

1.装饰器简介

  • 概念

    在不改变被装饰对象原代码和调用方式的情况下给被装饰对象添加新的功能

  • 本质

    并不是一门新的技术 而是由函数参数、名称空间、函数名多种用法、闭包函数组合刀一起的结果

  • 口诀

    对修改封闭,对扩展开放

  • 储备知识

    时间相关操作

    import time
    print(time.time())  # 时间戳(距离1970-01-01 00:00:00所经历的秒数)
    time.sleep(3)  # 让程序等待三秒再执行
    print('休息三秒')
    
    count = 0
    # 循环之前先获取时间戳
    start_time = time.time()
    while count < 100:
        print('哈哈哈')
        count += 1
    end_time = time.time()
    print('循环消耗的时间:', end_time - start_time)
    
    

2.装饰器推导流程

import time

def index():
    time.sleep(3)
    print('from index')
    
index()

1.首先我们想统计index函数执行产生的时间戳

import time

def index():
    time.sleep(3)
    print('from index')
strat_time = time.time()
index()
end_time = time.time()
print('函数执行的时间:', end_time - strat_time)
# from index
index运行的时间: -3.007066249847412

2.由上可看出我们可以在调用函数index的前后添加代码,但是如果我们在其他地方多次调用函数index的时候,也需要查看时间戳,那么就需要多次输入以上代码,就显得多余费力,那么我们就要用到函数去定义这段代码方便调用

def get_time():
    strat_time = time.time()
    index()
    end_time = time.time()
    print('函数执行的时间:', end_time - strat_time)

get_time()

3.这样是方便以后调用查看,但是却给函数体代码写死了,如果有另一个函数也要统计时间要怎么查看呢,那么我们就需要直接传参变换统计的函数

import time

def index():
    time.sleep(3)
    print('from index')
def func():
    time.sleep(2)
    print('from func')

def get_time(a):
    strat_time = time.time()
    a()
    end_time = time.time()
    print('函数执行的时间:', end_time - strat_time)

get_time(index)
get_time(func)

"""
from index
函数执行的时间: -3.0028903484344482
from func
函数执行的时间: -2.0058066844940186
"""

4.实现了多个函数可用,但是却违背了装饰器规则,更改了调用方式,第一种传参不能用,我们要考虑闭包

def outer(b):
    # b = index
    def get_time():
        strat_time = time.time()
        b()
        end_time = time.time()
        print('函数执行的时间:', end_time - strat_time)
    return get_time
res = outer(index)
res()
res = outer(func)
res()
"""
from index
函数执行的时间: 3.0039374828338623
from func
函数执行的时间: 2.0016427040100098
"""

5.调用方式还是不对,如何去变形呢?我们考虑变量名赋值绑定,我们把res 直接换成函数名(其实就是在欺骗我们的眼睛)

def outer(b):
    # b = index
    def get_time():
        strat_time = time.time()
        b()
        end_time = time.time()
        print('函数执行的时间:', end_time - strat_time)
    return get_time
index = outer(index)  # 赋值符号的左边是一个变量名 可以随意命名
index()
func = outer(func)
func()
"""
from index
函数执行的时间: 3.0039374828338623
from func
函数执行的时间: 2.0016427040100098
"""

6.这时调用方式我们看起来就和之前一样了,但是!!!这只能装饰无参函数,兼容性太差,如果是有参函数呢?

import time

def index(a):
    time.sleep(3)
    print('from index', a)

def outer(b):
    # b = index
    def get_time(a):
        strat_time = time.time()
        b(a)
        end_time = time.time()
        print('函数执行的时间:', end_time - strat_time)
    return get_time
index = outer(index)
index(1)

7.以上只适用于只有一个形参的情况,如果是有多个参数或者没有参数,如何兼容

import time

def index(a):
    time.sleep(3)
    print('from index', a)
def index1(a, b):
    time.sleep(1)
    print('from index1', a, b)
def index2():
    time.sleep(1)
    print('from index2')
def outer(b):
    # b = index
    def get_time(*args, **kwargs):
        strat_time = time.time()
        b(*args, **kwargs)
        end_time = time.time()
        print('函数执行的时间:', end_time - strat_time)
    return get_time
index = outer(index)
index(1)
index1 = outer(index1)
index1(1, 2)
index2 = outer(index2)
index2()
"""
from index 1
函数执行的时间: 3.0133862495422363
from index1 1 2
函数执行的时间: 1.0149316787719727
from index2
函数执行的时间: 1.0117344856262207
"""

8.如果被执行函数有返回值

def func(a):
    time.sleep(0.1)
    print('from func', a)
    return 'func'
def func1(a,b):
    time.sleep(0.2)
    print('from func1', a, b)
    return 'func1'
def outer(xxx):
    def get_time(*args, **kwargs):
        start_time = time.time()
        res = xxx(*args, **kwargs)
        end_time = time.time()
        print('函数执行的时间>>>:', end_time - start_time)
        return res
    return get_time
func = outer(func)
res = func(123)
print(res)

func1 = outer(func1)
res = func1(123, 123)
print(res)

3.装饰器模板

def outer(func_name)
	def inner(*args, **kwargs)
    print('执行被装饰对象之前可以做的额外操作')
    res = func_name(*args, **kwargs)
    print('执行被装饰对象之后可以做的额外操作')
    return res
return inner

4.装饰器语法糖

def outer(fucn_name):
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func_name(*args, **kwargs)
        print('执行被装饰对象之后可以做的额外操作')
        return res
    return inner
"""
语法糖会自动将下面紧挨着的函数名当做第一个参数自动传给@函数调用
"""
@outer  # func = outer(func)
def func():
    print('from func')
    return 'func'
@outer  # index = outer(index)
def index():
    print('from index')
    return 'index'

func()
index()

标签:闭包,index,函数,func,time,print,装饰,def
From: https://www.cnblogs.com/LZXSDM/p/16782505.html

相关文章

  • python基础之闭包函数与装饰器
    python基础之闭包函数与装饰器目录一、global与nonlocal二、函数名的多种用法1.可以当变量名2.可以当函数的参数3.可以当函数的返回值三、闭包函数1.闭包函数的实际应用四......
  • 装饰器
    1.global与nonlocal1.global:局部名称空间修改全局名称空间的数据n=100defindex():globalnn=999index()print(n)#9992.nonlocal:内层局部名......
  • C语言-函数
    1:函数的概念函数是一个命名了的代码块,我们通过调用函数执行相应的代码,函数可以有0个或者多个参数,而且会产生一个结果对于我的总结:我觉得函数可以说是一个能够实现一定功......
  • python重点之装饰器
    global与nonlocal函数名的多种用法闭包函数装饰器简介无参装饰器有参装饰器装饰器模板装饰器语法糖今日详细内容global与nonlocalmoney=666defind......
  • 函数(三)
    函数(三)global与nonlocal1.global的用法1.当不使用global时 number=89defindex(): number=34index()print(number)#89......
  • 装饰器、global与nonlocal
    目录global与nonlocal函数名的多种用法闭包函数装饰器简介装饰器推导流程装饰器模版装饰器语法糖作业global与nonlocalglobalmoney=666defindex():globalmone......
  • python进阶之路11 闭包函数 装饰器
    函数名的多种用法函数名其实绑定的也是一块内存地址只不过该地址里面存放的不是数据值而是一段代码函数名加括号就会找到该代码并执行1.可以当作变量名赋值defindex......
  • 函数名的用法,闭包函数与装饰器
    函数的多种用法与装饰器global与nonlocal1.global用在局部名称空间直接修改全局名称空间中的数据x=111deffunc():globalx#修改全局名称空间x值x=2......
  • hive窗口函数极速入门
    1over()窗口函数1.1语法结构分析函数over(partitionby列名orderby列名rowsbetween开始位置and结束位置)1.2over中的三个函数具体含义orderby:排序的意......
  • 装饰器+闭包掌握(python一大重要功能)
    目录global与nonlocal函数名的多种用法闭包函数装饰器简介1.概念2.本质3.口诀4.超前知识time模块装饰器推导装饰器模板装饰器语法糖作业global与nonlocalglobal#提升......