读懂python代码_读懂花里胡哨的14行Python代码!
最近在项目里发现一段代码,初看比较难看懂,细看,也还是比较难看懂。遂研究了一下,证实了这段代码确实,没啥作用,遂删之。记录在下。
去掉几个用于封装的函数,保留最小代码后,剩下以下14行代码。你能说出这段代码是干嘛的?每行代码分别被执行了几次吗?
class CachedProperty():
def __init__(self,func,name=None):
self.func = func
self.name = name or func.__name__
def __get__(self,instance,cls=None):
res = instance.__dict__[self.name] = self.func(instance)
return res
class MyClass():
@CachedProperty
def caches(self):
return {}
mc = MyClass()
mc.caches['key'] = 1
print(mc.caches['key'])
要读懂上面14行代码,需要理解两样东西,一个是类装饰器,一个是描述器。
类装饰器
装饰器比较常见,类装饰器就不常见了。
给func1加上func2装饰器,等同于令func1=func2(func1), func1依然是一个callable的对象。给func1加上class2装饰器,同样需要返回的是一个callable的对象。所以在class2中,要求实现__call__方法。
进群:960410445 即可获取数十套PDF!
例子:
class log():
def __init__(self,func):
self.func = func
def __call__(self, *args, **kwargs):
print('log...')
return self.func(*args, **kwargs)
@Log
def func1(x):
return x
以上就等同于令func1=Log(func1), 实际上就是一个callable的Log类实例了。调用func1的时候,就触发__call__方法完成调用过程。
描述器
描述器是一个有"绑定行为"的对象属性,用其他编程语言做一个较通俗的对比,就是实现了setter和getter的属性。
定义一个描述器,需要为属性至少定义__delete__, __get__, __set__中的任意一个方法。这些方法会在进行属性访问时自动被调用。
一个简单的例子:
class Ds():
def __init__(self, v):
self.v = v
def __set__(self, obj, v):
self.v = v
def __get__(self, obj, objtype):
return self.v
class T():
x = Ds(10)
print(T.x) # 10
这里还要扯到一个优先级的问题, 如果只定义了__get__方法,那么当T.__dict__拥有同名属性的时候,优先使用T.__dict__的,若还定义了__set__方法,则描述器永远优先,称为非资料描述器,反之称为资料描述器。这一点对读懂14行代码至关重要。
代码解释
回到最初的14行代码,可以说是'使用类装饰器的方式来定义一个非资料描述器,利用优先级的特性,完成方法调用结果缓存的功能'。
一行行来看
class CachedProperty():
def __init__(self,func,name=None):
# func == caches
self.func = func
# self.name == 'caches'
self.name = name or func.__name__
# instance等于对象实例, 在本例子中,等同于mc,cls等同于MyClass
def __get__(self,instance,cls=None):
# 最右边返回{},赋值给中间的mc.__dict__['caches']和最左边的res
res = instance.__dict__[self.name] = self.func(instance)
return res
class MyClass():
# 类装饰器, 和下面三行一起,等同于 caches = CachedProperty(lambda: {})
@CachedProperty
def caches(self): # 不需要被当成方法调用, 所以不需要实现__call__
return {}
mc = MyClass()
# 第一步,获得mc.caches, 按优先级, mc.__dict__['caches']不存在,
# 所以触发__get__方法调用,得到{}, 且mc.__dict__['caches']也等于{}
# 第二步,为mc.__dict__['caches']['key']赋值1
mc.caches['key'] = 1
# 按优先级,mc.__dict__['caches']已存在,不再触发__get__方法和cahces(self)方法执行
# 取mc.__dict__['caches']['key'], 返回1。
print(mc.caches['key'])
以上,经过一通花里胡哨的操作,实际效用就是: 实现了caches(self)方法只会被执行一次,其结果将被缓存起来,供以后再次调用时使用。
在这个例子中,caches(self)只有一行代码,返回{},在简化前,也是大概这个意思,所以,在本项目中,这段代码实际上毫无作用,遂可删之。
之后,发现同样的做法出现在django和flask等框架中,我的理解是,CacheProperty目的是为了实现view等较耗资源函数的结果缓存,并做到懒加载。例如,某类方法需要加载一个大模板并进行渲染,就可以使用CacheProperty, 保证在一次调用后,将结果缓存起来。若目标方法只是一个不耗计算资源的简单方法,就没必要再使用了。
读懂python代码_读懂花里胡哨的14行Python代码!相关推荐
- python人脸检测代码_如何用不到25行Python代码实现人脸检测
本文我们会讲讲怎样利用不到 25 行 Python 代码和开源库 OpenCV,以很简单的方式实现人脸识别. 在正式开始前,先提以下两点小小的建议:先别急着跳到代码部分,最好在前文理解一下代码是干什么 ...
- python鲜花_【实战案例】90 行Python代码实现一棵鲜花盛开树
今天请各位读者朋友欣赏用 Python 实现的鲜花盛宴,你准备好了吗?90 行代码即可实现一棵美丽的鲜花盛开树.对于知识的运用也是如此,需要不断吸收新知识,学习新技能,才能盛开出美丽的花朵.接下来就看 ...
- python简单好玩的代码_只需要9步100行Python代码就可以实现一个简单又好玩的弹球游戏...
今天给大家分享一个有趣又好玩的弹球的游戏,一来可以把类的知识融会一下,二来加深对Python的兴趣.你会发现哎呀Python写小游戏还是蛮方便的,蛮有意思的~~ 需要本文源码:私信回复[源码]即可获取 ...
- python酷炫图形代码_牛批了,1 行 Python 代码就可实现炫酷可视化
之前画图一直在用 matlibplot.pyecharts,最近学习了一个新的可视化库--cufflinks,用了两天我已经深深爱上它了 主要是因为它用法简单.图形漂亮.代码量少,用一两行代码,就能画 ...
- 简单且有创意的python作品_适合练手的 14 个Python 小项目,趣味十足!
掌握一门技术,迅速提升能力,最好方法是通过实践项目,最好是完整且有趣的.分享一本,我认为非常不错的书籍,<Python Playground>,这本书每个章节就是一个完整的小项目. ...
- python60行绘图程序_不敢相信,60行python代码就写出了贪吃蛇游戏
通过写游戏玩编程是一个非常有趣的事,网上用Python写贪吃蛇的代码很多,大部分都用类来写的,比较复杂.今天看到一个非常简洁的贪吃蛇游戏代码,只有60几行,非常适合小白上手,而且思路极其清晰,赶紧分享 ...
- 贪吃蛇python撞墙不死_不敢相信,60行python代码就写出了贪吃蛇游戏
通过写游戏玩编程是一个非常有趣的事,网上用Python写贪吃蛇的代码很多,大部分都用类来写的,比较复杂.今天看到一个非常简洁的贪吃蛇游戏代码,只有60几行,非常适合小白上手,而且思路极其清晰,赶紧分享 ...
- python 快速排序_小白入门知识详解:Python实现快速排序的方法(含实例代码)...
前言: 今天为大家带来的内容是:小白入门知识详解:Python实现快速排序的方法(含实例代码)希望通过本文的内容能够对各位有所帮助,喜欢的话记得点赞转发收藏不迷路哦!!! 提示: 这篇文章主要介绍了P ...
- bp神经网络预测python代码_机器学习之多层神经网络(附Python代码和数据)
1 引言 多层神经网络,Multiple-layers Perceptron (MLP),又被称为多层感知机,是机器学习中深度学习的典型算法.关于多层神经网络的算法原理,我们在Stata和R实现的文章 ...
最新文章
- OEA 框架演示 - 快过原型的开发
- Kotlin 在kotlin内使用Java的一些注意(长篇)
- linux下boost的一个扩展线程池-threadpool-的学习
- SSM-网站后台管理系统制作(2)---SSM基本工作原理
- centos7安装telnet后/etc/xinetd.d/telnet下没有telnet
- 勇攀监控高峰-EMonitor之根因分析 背景
- mysql 触发器 new.id,mysql触发器的使用方法
- 数据治理的好处有哪些
- 快速搭建一个本地FTP服务器
- idea取消vim模式
- GIS应用实例--模型预测、多元回归、空间自相关分析
- 一氧化碳(CO)荧光探针cas855751-82-5,二氧化硫荧光探针 激发波长653 nm,发射波长836 nm-齐岳介绍
- JavaScript动态创建DOM(七)
- 微型计算机主要性能指标是什么,微型计算机的主要性能指标
- 安卓开发——视频播放器
- 合唱队形c语言编程,洛谷 P1091 合唱队形
- 用s函数实现Lugre摩擦模型
- matlab定义双精度型变量_MATLAB小数(浮点数)类型
- Unity之引导功能遮罩事件穿透
- 咕咚已上传服务器怎到不丁微信,微信运动怎样使用咕咚数据?