一篇文章让你明白python的装饰器

简介: 在看闭包问题之前先来看看关于python中作用域的问题 变量作用域 对于上述代码中出现错误,肯定没什么疑问了,毕竟b并没有定义和赋值,当我们把代码更改如下后: 再看一个例子:   首先这个错误已经非常明显:说在赋值之前引用了局部变量b 可能很多人觉得会打印10然后打印6,其实这里...

在看闭包问题之前先来看看关于python中作用域的问题

变量作用域

对于上述代码中出现错误,肯定没什么疑问了,毕竟b并没有定义和赋值,当我们把代码更改如下后:

再看一个例子:

 

首先这个错误已经非常明显:说在赋值之前引用了局部变量b

可能很多人觉得会打印10然后打印6,其实这里就是涉及到变量作用域的问题
当Python编译函数的的定义体的时候,它判断b是局部变量,毕竟在函数中有b = 9表示给b赋值了,所以python会从本地环境获取b,当我们调用方法执行的时候,定义体会获取并打印变量a的值,但是当尝试获取b的值的时候发现b没有绑定值,所以要想让上述代码运行还可以把b设置为全局变量,或者把b赋值放到调用之前

函数对象的作用域

python中一切皆对象,同其他对象一样,函数对象也有其使用的范围即函数对象的作用域。
在python中我们通过def定义函数,函数对象的作用域与def所在的层级相同,
通过下面代码进行理解:

def func1():
    def func2(x):
        return 2*x
    print(func2(5))

func1()
print(func2(5))

这个例子中我们在def func1函数内可以调用fun2,但是我们在外面是无法调用到func2的,所以结果为看到如下:

闭包

关于闭包主要有下面两种说法:

  • 闭包是符合一定条件的函数,定义为:闭包是在其词法上下文中引用了自由变量的函数
  • 闭包是由函数与其相关的引用环境组合而成的实体。定义为:在实现绑定时,需要创建一个能显示表示引用环境的东西,并将它与相关的子程序捆绑在一起,这样捆绑起来的整体称为闭包

个人觉得第二种说法更准确,闭包只是在形式上表现像函数,实际不是函数。
我们对函数的定义是:一些可执行的代码,这些代码在函数定义后就确定了,不会在执行时发生变化,所以一个函数只有一个实例。

闭包在运行的时候可以有多个实例,不同的引用环境和相同的环境组合可以产生不同的实例。

这里有一个词:引用环境,其实引用环境就是在执行运行的某个时间点,所有处于活跃状态的变量所组成的集合,这里的变量是指变量的名字和其所代表的对象之间的联系。

可以使用闭包语言的特点:

  • 函数可以作为另外一个函数的返回值或者参数,还可以作为一个变量的值。
  • 函数可以嵌套使用

而认为闭包是函数的有一句话是:
闭包是指延伸了作用域的函数,其中包含函数定义体中引用。但是不在定义体中定义的非全局变量。

上面这种说法个人觉得也是一种理解方式

相信看了这些概念也还是不好理解,还是通过下面例子更好理解:

先实现一种计算平均值的方法:

从结果我们可以看出这里保存了每次的历史值
换一种方法实现:

实现了第一种相同的效果,对这种方法分析:
通常我们会认为我们调用avg(10)的时候make_averager函数已经返回了,而它的本地作用域也一去不复返,但这里其实series是自由变量,是指未在本地作用域绑定的变量
我们可以通过print(dir(avg)),看到如下结果:

其实这里面保存着均布变量和自由变量的名称,我们可以通过下面方法查看:

eries的绑定在返回的avg函数的__closure__属性中这或许就是有的人会认为闭包一种函数。闭包会保留定义函数时存在的自由变量的绑定,这样调用函数时虽然定义作用域不能用了,但是仍能使用那些绑定

关于nonlocal

刚开始了解闭包之后,如果尝试使用这种编程方式容易出现以下错误使用例子:

def make_averager():
    count = 0
    total = 0

    def averager(new_value):
        count += 1
        total += new_value
        return total / count
    return averager

先来看一下错误提示:

这个例子中和我们上面使用的不同之处是:这里的count和total是数字,是不可变类型,而之前的例子中series是一个列表是可变类型
所以这里重新回到了最开始说的作用域问题了,当我们在averager中使用
count += 1的时候其实就是count = count + 1,这样就是在averager函数定义体中对count进行赋值,count就变成了局部变量。

问题小结:当时数字,字符串,元组等不可变类型时,只能读取不能更新,如果使用类似count += 1就会隐式的把count变成局部变量,所以开始例子中使用series,我们后面的操作是append并且列表还是可变对象

不过python3引入了一个新的关键词nonlocal,通过它把变量标记为自由变量,这样我们把上面这个错误的例子简单更改:

def make_averager():
    count = 0
    total = 0

    def averager(new_value):
        nonlocal count,total
        count += 1
        total += new_value
        return total / count
    return averager

到这里装饰器的前奏就说完了,下面就是装饰器,我个人觉得装饰器只是闭包的一种应用,闭包在很多情况下都是一种非常好的变成技巧

装饰器

关于装饰器本来是想重新整理一下,看了自己之前整理的博客,已经挺详细的,就把连接直接放这里了
http://www.pythonsite.com/?p=113

所有的努力都值得期许,每一份梦想都应该灌溉!
目录
相关文章
|
8天前
|
监控 Python
Python中的装饰器:提升代码灵活性与可读性
在Python编程中,装饰器是一种强大的工具,能够提升代码的灵活性和可读性。本文将介绍装饰器的基本概念、使用方法以及实际应用场景,帮助读者更好地理解和利用这一功能。
|
11天前
|
缓存 监控 Python
解密Python中的装饰器:优雅而强大的编程利器
Python中的装饰器是一种强大而又优雅的编程工具,它能够在不改变原有代码结构的情况下,为函数或类添加新的功能和行为。本文将深入解析Python装饰器的原理、用法和实际应用,帮助读者更好地理解和利用这一技术,提升代码的可维护性和可扩展性。
|
29天前
|
缓存 算法 测试技术
Python中的装饰器:原理与实践
【2月更文挑战第29天】 在Python编程领域,装饰器是一种强大的工具,它允许我们在不修改原始函数代码的情况下,增加或修改函数的行为。本文将深入探讨Python装饰器的概念、实现原理以及实际应用,帮助读者掌握这一技术并在实际项目中灵活运用。
|
1天前
|
数据安全/隐私保护 Python
Python中的装饰器:提升代码可读性与灵活性
Python中的装饰器是一种强大的工具,可以在不改变函数原有逻辑的情况下,为函数添加额外的功能。本文将介绍装饰器的基本概念和用法,并通过实例演示如何利用装饰器提升代码的可读性和灵活性,使代码更加简洁、易于维护。
|
3天前
|
程序员 Python
Python中的装饰器:提升代码可读性与灵活性
在Python编程中,装饰器是一种强大的工具,可以在不修改原始代码的情况下,动态地添加功能。本文将深入探讨Python中装饰器的原理、用法和实际应用,以及如何利用装饰器提升代码的可读性和灵活性。
|
5天前
|
缓存 开发者 Python
深入探讨Python中的装饰器:提升代码可读性与灵活性
在Python编程中,装饰器是一种强大的工具,可以在不修改原始函数代码的情况下,对其行为进行扩展或修改。本文将深入探讨装饰器的原理和用法,以及如何利用装饰器提升代码的可读性和灵活性,为Python开发者提供更加优雅和高效的编程方式。
|
6天前
|
测试技术 开发者 Python
Python中的装饰器:优雅而强大的函数修饰工具
在Python编程中,装饰器是一种强大的工具,用于修改函数或方法的行为。本文将深入探讨Python中装饰器的概念、用法和实际应用,以及如何利用装饰器实现代码的优雅和高效。
|
16天前
|
缓存 数据安全/隐私保护 Python
Python中的装饰器:提升代码灵活性和可维护性
Python中的装饰器是一种强大的工具,能够在不修改原始函数代码的情况下,为函数添加额外的功能。本文将深入探讨装饰器的原理、用法以及实际应用场景,帮助读者更好地理解和利用Python中的装饰器提升代码的灵活性和可维护性。
|
22天前
|
缓存 程序员 Python
深入理解Python装饰器:从概念到应用
Python装饰器是函数,用于在不修改原代码的情况下为函数添加新功能。它们基于Python的函数一阶对象特性,通过`@decorator`语法应用。装饰器工作原理是接收函数作为参数,创建新函数对象并在调用时执行额外操作。常见应用场景包括日志记录、性能分析、权限校验和缓存。装饰器增强了代码的可读性和可维护性。
|
24天前
|
测试技术 Python
Python中的装饰器:提升代码可读性和灵活性
在Python编程中,装饰器(Decorator)是一种强大的工具,它可以在不修改原有代码的情况下,为函数或方法添加额外的功能。本文将深入探讨Python中装饰器的使用方法和实际应用,帮助读者更好地理解和运用这一重要的编程概念。

热门文章

最新文章