IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> <Fluent Python>剖析装饰器实现原理 -> 正文阅读

[Python知识库]<Fluent Python>剖析装饰器实现原理

装饰器在python中真的很重要,几乎所有的框架都在用装饰器,装饰器Python面试中避不开的话题,今天我们就来彻底搞清楚装饰器

1 一个有状态的类

代码是枯燥的,结合生活中的实例就会变得很有意思,我们定义一个类,这个类的作用是计算平均数,语言上可能不是很好描述,直接敲代码。

方式一

class MakeAvg:
	"""
    定义一个有状态的求序列平均数的类
    """
    def __init__(self):
        self.total = [] # 实例化过程中初始化一个列表

    def avg(self,val):
        self.total.append(val)
        # 返回列表平均数
        return f'{self.total}的平均数是{sum(self.total) / len(self.total)}' 


if __name__ == '__main__':
    make_avg = MakeAvg()
    avg = make_avg.avg(10)
    print(avg)
    avg = make_avg.avg(11)
    print(avg)
    avg = make_avg.avg(12)
    print(avg)
"""
OUT:
[10]的平均数是10.0
[10, 11]的平均数是10.5
[10, 11, 12]的平均数是11.0
"""

通过结果可以看的出来,这个类是一个有状态的类,实例属性total是可以累加的

方式二

class MakeAvg:
    """
    定义一个有状态的求序列平均数的类
    """
    def __init__(self):
        self.total = 0
        self.count = 0

    def avg(self,val):
        self.total += val
        self.count += 1
        return f'{self.count}个数的和={self.total}的平均数是{self.total / self.count}'


if __name__ == '__main__':
    make_avg = MakeAvg()
    avg = make_avg.avg(10)
    print(avg)
    avg = make_avg.avg(11)
    print(avg)
    avg = make_avg.avg(12)
    print(avg)

"""
OUT:
1个数的和=10的平均数是10.0
2个数的和=21的平均数是10.5
3个数的和=33的平均数是11.0
"""

1 一个有状态的函数“闭包”

def make_avg():
    total = []
    def inner(val):
        total.append(val)
        avg = sum(total)/len(total)
        return avg
    return inner

if __name__ == '__main__':
    avg = make_avg() # avg = inner
    print(avg)       # 输出是一个函数
    res = avg(10)    
    print(res)     # 10
    res = avg(11)
    print(res)     #10.5
    res = avg(12)
    print(res)     #11.0
    print(avg.__code__.co_varnames)  # 获取局部变量
    print(avg.__code__.co_freevars)  # 获取到自由变量
    print(avg.__closure__[0].cell_contents) # 获取闭包中的过程值
"""
OUT:
<function make_avg.<locals>.inner at 0x0000023364622A60> 
10.0
10.5
11.0
('val', 'avg')
('total',)
[10, 11, 12]
"""

在这里插入图片描述
闭包就是能够读取其他函数内部变量的函数,一个函数内部的函数,也就是嵌套函数,执行的过程中不会释放自由变量

def make_avg():
    total = 0
    count = 0
    def inner(val):
        #nonlocal total, count
        total += val
        count += 1
        return total/count
    return inner


if __name__ == '__main__':
    avg = make_avg()
    print(avg)
    res = avg(10)
    print(res)
    res = avg(11)
    print(res)
    res = avg(12)
    print(res)
    print(avg.__code__.co_varnames)
    print(avg.__code__.co_freevars)
    print(avg.__closure__[0].cell_contents)
"""
OUT:
<function make_avg.<locals>.inner at 0x0000025C36682A60>
UnboundLocalError: local variable 'total' referenced before assignment
"""

我先解决这个报错然后再解释出现这种状况的原因

...
nonlocal total, count
...

上面和下面的代码我就不写了,直接把nonlocal这行注释打开程序就不会报错了,读者自己可以试一下,这是为什么呢?
这是Python可变类型与不可变类型的原因,列表是一个可变数据类型,对列表进行append操作不会更改列表的在内存中的地址,但是对于int型数据,total += val 等价于 total = total +val 左边的total等于一个新变量,但是这个变量没有在当前作用域中进行声明,所以会报错,python3中给了一个nonlocal关键字,作用就是让这个变量去自由变量里面去查找看看有没有定义,如果有,那就应用自由变量的定义。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-12 16:33:29  更:2021-08-12 16:34:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 6:50:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码