python装饰器与闭包

python 装饰器与闭包

1. 什么是函数?

  • 在程序中,函数是具备某一功能的工具(将代码封装在里面),事先将工具准备好 (锤子、扳手、工厂)即函数的定义
  • 遇到应用场景拿来就用即函数的调用
  • 所以,注意!函数的使用必须遵循先定义后调用的原则(先制造了工具,工具才能使用)

2. 为何要用函数 不用函数会产生什么问题?

  • 程序冗长
  • 程序的扩展性差
  • 程序的可读性差

3. 如何用函数?

# 1. 函数定义阶段:
# 只检测函数体的语法,不执行函数体代码(不调用)
# 定义语法
# def 函数名+()+:
# # # 缩进+函数体代码
# (缩进不一一对齐会报语法错误)

# 例如:
def fac():
    print("hello")
    print("hello")
    print("hello")
# 2. 函数调用阶段:
# 函数的调用:函数名+括号
# 先找到函数名(可以根据函数名打印出函数内存地址)
# 根据函数名调用代码(加括号)
# 例如:
def fac():
    print("hello");
    print("hello");
    print("hello");

print(fac)
fac()

在这里插入图片描述

4. 闭包函数(重点)

(1)定义

闭包函数
闭:该函数是一个内部函数
包:指的是该内部函数的名字在外部被引用

(2)代码例子

def outer():# 没有调用outer()
    # 1. 只检测函数体outer的语法,不执行函数体代码
    print("外面的函数在运行")
    def inner(): # 并没有被定义出来
        print("里面的函数在运行")


inner()
# 这样的调用必然报错

在这里插入图片描述

  • 因为这里面的函数没有被定义
  • 由前面可知:在函数定义阶段,只检测函数体的语法,不会执行函数体代码,所以inner并没有被定义,自然会报错
  • 先执行outer ,这样inner就会被创造出来(但是没有运行)
  • 代码:
def outer():
    print("外面的函数在运行")
    def inner():
        print("里面的函数在运行")

outer()

(3)那么在以上代码基础上,在我们定义了inner函数之后,可不可以直接函数名+()就可以调用了?

def outer():
    print("外面的函数在运行")
    def inner():
        print("里面的函数在运行")

outer()
inner() # error
  • 答案是不可以
  • 因为inner是在局部定义的,在外面是拿不到里面“inner”的一个地址(要先进入outer里面),这个地址我们需要一个返回值去返回它。
  • 代码如下:
# 3步
def outer():
    # 1 只检查函数体outer的语法,不执行函数体代码
    print("外面的函数在运行")
    def inner():
        print("里面的函数在运行")
    return inner # 3 返回了inner函数的内存地址 (拿到内存地址就可以执行inner函数了) return 给 address接收
address = outer() # 2 outer()执行定义了inner函数
print(address)
address() # 能拿到地址,这时候直接运行就可以了
# 这就是闭包
  • 运行结果如下:
    在这里插入图片描述

5. 为函数体传值的方式一:参数

(1)代码如下:

def funcTest(x, y):
    print(x * y)

funcTest(3, 6)
funcTest(3, 6)
funcTest(3, 6)

(2)函数执行结果如下:

在这里插入图片描述

6. 为函数体传值的方式二:闭包(参数传一次就可以了,不用向以上那样,每次都重复写参数,把参数一起封装到内存地址里去了)

(1)代码如下:

def outer(x, y):
    def inner():
        print(x * y)
    return inner

inner = outer(3, 3)

inner()
inner()
inner()

(2)运行结果如下:

在这里插入图片描述

7. 装饰器(一个特殊的闭包函数)

(1)定义:

什么是装饰器(就是一个函数,只不过这个函数不是给自己使用的,是给其他函数添加功能的)
器指的是工具,而程序中的函数就具备某一功能的工具
装饰指的是为被装饰器对象添加额外功能

(2)为什么要用装饰器

软件的维护应该遵循开放封闭原则
	# 开放封闭原则:
        # 软件一旦上线运行后对修改源代码是封闭的,对扩展功能的修改是开放的
        	# 这就用到了装饰器
    # 装饰器的实现必须遵循两大原则:
    	1. 不修改被装饰对象的源代码
        2. 不修改被装饰对象的调用方式

# 装饰器其实就在遵循1和2原则的前提下为被装饰对象添加新功能

(3)代码

# 装饰器
name = 'test'
def run(name):
    print('=====')
    print('this is %s'%name)
    print('=====')

# run(name)

def decorate(func): # func 等下要传入的函数run
    def inner(name): # run(name) 的 name
        print('我是装饰函数前的代码')
        func(name) # run(name)
        print('我是装饰函数后的代码')
    return inner

# 1 定义了inner(name)函数  | 2 返回了 inner内存地址/
# 3 传入了一个run函数名
run = inner = decorate(run)

print(run)
# 运行内层函数里面的所有代码
# inner(name) # 还不是装饰器,调用方式改变

run(name) #装饰器
# print(inner)
  • 先调用了外层函数,将里层函数定义出来
  • 拿到内存地址,调用将run传进去,最后还是赋值给了变量run

(4) 运行结果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值