首页 > 其他分享 >8_闭包和装饰器

8_闭包和装饰器

时间:2022-10-17 18:14:38浏览次数:48  
标签:闭包 函数 show sum func print 装饰 def

1.回顾函数

知识点:

函数定义格式: def 函数名(形参): pass

函数注意事项:
1: 先定义再调用
2: 每调用一次执行一次
3: 函数不调用不执行
4: 函数如果没有return 返回值,默认返回的是None,或者直接一个return,也是返回None
5: 函数名本质记录的是函数的地址
6: 函数调用:函数名(实参)
7: 即使不调用函数,但是在编译时系统也会给它初始化,也就是分配内存空间
7: 最好一个函数干一件事

注意:
函数名:  记录的是函数的内存地址
调用函数:本质是根据函数名对应的内存地址,执行地址内的代码

类里面叫方法,类外面叫函数,一样的其实

示例:

# 1.定义函数
def show():
    print('我是show函数...')

# 2.调用函数
show() # 正确调用
print(show()) # 先调用了show函数,然后打印了默认返回的None
print(show) # <function show at 0x0000020EFF157160>

# 3.直接用=传递引用地址
show2 = show # 本质是把show的地址传递给了show2
print(show2) #<function show at 0x000001EFAFB46160>
show2() # 本质调用的是show函数

# 4.通过函数参数传参引用地址
def func(f):
    print(f) # <function show at 0x0000024B23F57160>
    f()

func(show)

2.闭包

知识点:

闭包定义:使用外部函数变量的内部函数称为闭包。

闭包的构成条件:
1: 有嵌套(外部函数里面套了一个内部函数)
2: 有引用(内部函数使用了外部函数的变量或者形参)
3: 有返回(外部函数把内部函数名返回,本质返回的是内部函数的地址)

综上: 内部函数本质就是一个闭包

注意:函数内的变量是局部变量,函数运行结束就会被销毁
闭包好处:  由于内部函数调用外部函数,使得外部函数的变量不会被销毁,可以重复使用外部函数的变量
闭包缺点:  相对来说消耗内存

示例:

"""
闭包:
1.有嵌套
2.有引用
3.有返回
"""
# 1.定义闭包
# 外部函数
def outer(a):
    # 内部函数
    def inner(b):
        # 有引用
        sum = a + b
        print(sum)
    # 有返回,本质返回的是内部函数的内存地址
    return inner
# 2.使用闭包
# inner() # 报错,内部函数不能直接访问
# 闭包:  func=inner=<function outer.<locals>.inner at 0x00000218EA1F74C0>
func = outer(10) # func接收的就是内部函数的内存地址
# func()调用的就是内部函数
func(1)
func(2)
func(3)

3.装饰器

知识点:

装饰器作用(也是好处): 在不改变原有函数(不改变源码,不改变调用方式)的基础上,去增加额外的功能

装饰器: 本质是一个闭包函数

装饰器的构成条件:
1: 有嵌套(外部函数里面套了一个内部函数)
2: 有引用(内部函数使用了外部函数的变量或者形参)
3: 有返回(外部函数把内部函数名返回,本质返回的是内部函数的地址)
4: 有额外功能(不改变原有函数的基础上,去额外增加功能)  

装饰器使用: 装饰后的原有函数名本质接收的是内部函数地址

原始方式: 装饰后的原有函数名 = 外部函数名(装饰前的原有函数名)
语法糖方式: @外部函数名
语法糖方式的底层就是原始方式写法,他们等价


原始方式示例:

# 3.写装饰器
def outer(func):  # func = show 原有函数的地址传递给了func
    def inner():
        # 有额外功能
        print('请先登录...')
        func()  # func() = show() 本质调用的是原有函数

    return inner

# 1.定义一个原有函数
def show():
    print('发表评论...')

# 4. 使用装饰器(把原有函数传入到outer里装饰,返回内部函数地址)
show = outer(show) # show = inner

# 2.调用原有函数
show()  # 使用了装饰器后,show()本质调用的是inner()内部函数

语法糖方式示例:

# 3.写装饰器
def outer(func):  # func = show 原有函数的地址传递给了func
    def inner():
        # 有额外功能
        print('请先登录...')
        func()  # func() = show() 本质调用的是原有函数

    return inner


# 1.定义一个原有函数
@outer  # 4.语法糖方式调用,实际上编译时就已经完成了show = outer(show) 即==>show = inner的操作
def show():
    print('发表评论...')


# 2.调用原有函数
show()  # 使用了装饰器后,show()本质调用的是inner()内部函数

4.回顾函数定义和调用

知识点:

函数的四种常见定义:

无参无返回值
	定义: def 函数名(): 函数体 
	调用: 函数名()
	
有参无返回值
	定义: def 函数名(形参): 函数体 
	调用: 函数名(实参)
	
无参有返回值
	定义: def 函数名(): 函数体  return 返回值
	调用:  接收返回值 = 函数名()
	
有参有返回值
	定义: def 函数名(形参): 函数体  return 返回值
	调用: 接收返回值 = 函数名(实参)

示例:

# 1.1定义无参无返回值的函数
def show1():
    a = 10
    b = 20
    sum = a + b
    print(sum)


# 1.2调用无参无返回值函数
show1()


# 2.1定义无参有返回值的函数
def show2():
    a = 10
    b = 20
    sum = a + b
    return sum


# 2.2调用无参有返回值函数
sum = show2()
print(sum)


# 3.1定义有参无返回值的函数
def show3(a, b):
    sum = a + b
    print(sum)


# 3.2调用有参无返回值函数
show3(10, 20)


# 4.1定义有参有返回值的函数
def show4(a, b):
    sum = a + b
    return sum


# 4.2调用有参有返回值函数
sum = show4(10, 20)
print(sum)

5.装饰器基本使用

以无参无返回值的函数装饰器为例:

# 3.写装饰器
def outer(func): # func = get_sum
    def inner():
        # 额外功能
        print('正则努力计算中...')
        func() # func()调用的就是原有函数get_sum()
    return inner # 返回内部函数地址

# 1.1定义无参无返回值的函数
@outer # 4.使用装饰器
def get_sum():
    a = 10
    b = 20
    sum = a + b
    print(sum)

# 1.2调用无参无返回值函数
get_sum()

6.装饰器的通用格式

知识点:

这个格式是重点,它比较通用

*args : 元组方式存储数据    注意: 元组一个参数加逗号 ,

**kwargs: 字典方式存储数据  注意: kv键值对方式存储

注意位置传递和关键字传递同时存在的话: 位置传递需要放到关键字传递前

示例:

# 3.定义装饰器
def outer(func):
    def inner(*args, **kwargs):  # args=(10,20,30)  kwargs={b:40,c:50,d:60}
        # 额外功能
        print('正在努力计算中...')
        sum = func(*args, **kwargs)  # 此处func其实就是原有函数
        return sum

    return inner

# 1. 原有函数
@outer  # 4.使用装饰器
def get_sum(*args, **kwargs):  # 形参 *args默认封装成元组,**kwargs默认封装成字典
    # args=(10,20,30)  kwargs={b:40,c:50,d:60}
    sum = 0
    # 遍历元组
    for i in args:  # i:10, 20, 30
        sum += i
    # 遍历字典
    for i in kwargs.values(): # i:40,50,60
        sum += i
    return sum

# 2.调用
sum = get_sum(10, 20, 30, b=40, c=50, d=60)  # 此处get_sum是内部函数inner
print(sum)


示例2:

# 3.定义装饰器
def outer(func):
    def inner(*args, **kwargs):  # args=(10,20)  kwargs={}
        # 额外功能
        print('正在努力计算中...')
        result = func(*args, **kwargs)  # 此处func(10,20)其实就是原有函数  get_sum(10,20)
        return  result

    return inner


# 1.1原有函数(加法)
@outer  # 4.1使用通用装饰器
def get_sum(a, b):  # a=10  b=20
    return a + b


# 2.1调用
sum = get_sum(10, 20)  # 此处get_sum是内部函数
print(sum)


# 1.2原有函数(减法)
@outer  # 4.2使用通用装饰器
def get_diff(a, b):
    return a - b


# 2.2调用
diff = get_diff(10, 20)
print(diff)

7.带参数的装饰器

知识点:

带参数的装饰器:  
有嵌套: 嵌套3层,最外层函数去携带参数,用于传递参数
有引用: 最内层函数引用参数,做判断
有返回: 返回内部2层函数
有额外功能

示例:

# 3.定义装饰器
def logging(flag):
    def outer(func):
        def inner(*args, **kwargs):  # args=(10,20)  kwargs={}
            # 额外功能
            if flag=='+':
                print('正在努力做加法运算中...')
            elif flag == '-':
                print('正在努力做减法运算中...')
            result = func(*args, **kwargs)  # 此处func(10,20)其实就是原有函数  get_sum(10,20)
            return result

        return inner
    return outer

# 1.1原有函数(加法)
@logging('+')  # 4.1使用通用装饰器     
def get_sum(a, b):  # a=10  b=20
    return a + b


# 2.1调用
sum = get_sum(10, 20)  # 此处get_sum是内部函数
print(sum)


# 1.2原有函数(减法)
@logging('-')   # 4.2使用通用装饰器
def get_diff(a, b):
    return a - b


# 2.2调用
diff = get_diff(10, 20)
print(diff)

标签:闭包,函数,show,sum,func,print,装饰,def
From: https://www.cnblogs.com/nanguyhz/p/16800113.html

相关文章

  • 【设计模式之装饰模式】
    前言:装饰模式,属于二十三个设计模式中之一,那么,什么是装饰模式,下面,大家请跟着我一起走进装饰模式,来看看装饰模式:核心:(一)、结构图想知道设计模式吗?那么看了它的UML图,你就一目......
  • 文档操作、函数基础、装饰器及迭代器相关基础知识
    本周内容概要文档操作相关知识函数相关基本知识名称空间相关知识闭包函数及装饰器递归函数与代码简化常用内置函数迭代器相关基础知识异常捕获基础知识本周内容......
  • 闭包函数
    目录闭包函数一、基础知识二、作用闭包函数一、基础知识所谓闭包函数就是定义在函数内部的函数,但是他有一些限制条件:1、定义在函数内部2、用到了外部函数名称空间中......
  • 装饰器
    目录装饰器一、装饰器简介为何要用装饰器什么是装饰器本质口诀储备知识二、装饰期推导流程步骤一:步骤二:步骤三:步骤四:步骤五:步骤六:步骤七:步骤八:三、装饰器模版四、装饰器语......
  • Python在Class中实现装饰器
    函数装饰器普通的装饰器较为简单,关键点只有两个,一个是闭包的概念,一个是函数作为参数进行传递,让我们先实现一个简单的装饰器。defhuat(f):deffunc():prin......
  • Python 3.9 新特性:任意表达式可作为装饰器!
    一个月前(2月20日),一则新的PEP没有受到任何阻碍就被官方采纳了,这么快的速度,似乎并不多见。然而,更为高效率的是,仅在半个月内,它的实现就被合入了代码仓。也就是说,我们最快有望......
  • 图解Java设计模式之装饰者模式
    图解Java设计模式之装饰者模式​​星巴克咖啡订单项目(咖啡馆)​​​​方案1-解决星巴克咖啡订单项目​​​​方案1-解决星巴克咖啡订单问题分析​​​​方案2-解决星......
  • 在考虑闭包的情况下JS变量存储在栈与堆的区分
    变量存储在闭包中的问题按照常理来说栈中数据在函数执行结束后就会被销毁,那么 ​​JavaScript​​ 中函数闭包该如何实现,先简单来个闭包:functioncount(){letnum=......
  • 【JS】167-JavaScript设计模式——装饰者模式
    四、装饰者模式(DecoratorPattern)1.概念介绍装饰者模式(DecoratorPattern):在不改变原类和继承情况下,动态添加功能到对象中,通过包装一个对象实现一个新的具有原对象相同接口......
  • 装饰器与递归函数
    多层语法糖"""多层语法糖加载顺序由下往上每次执行之后如果上面还有语法糖则直接将返回值函数名传给上面的语法糖如果上面没有语法糖了则变形index=outter1(wrapper......