Python类的动态绑定实现原理


Posted in Python onMarch 21, 2020

使用实例引用类的属性时,会发生动态绑定。即python会在实例每次引用类属性时,将对应的类属性绑定到实例上。

动态绑定的例子:

class A:
  def test1(self):
    print("hello")
  
  def test2(self):
    print("world")

def bound():
  a = A()
  a.test1()
  A.test1 = A.test2
  a.test1()

if __name__ == "__main__":
  bound()

输出结果:

hello2 world

从上述代码中可以看到,类方法的变化是实时影响实例对方法的调用的,这说明python是在实例调用方法的过程中动态地查找类方法。

动态绑定的代价:

class A:
  def test(self):
    pass
def one_loop(limited_time):
  a = A()
  for i in range(limited_time):
    a.test()
  f = a.test
  for i in range(limited_time):
    f()

上图两个循环中,一个调用a.test(),不断进行动态绑定,另一个则先把a.test赋值给f,只有一次动态绑定,通过对两个循环计时,测试动态绑定的代价。

输出结果:

Python类的动态绑定实现原理

1 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0009999275207519531, 0.008995771408081055, 0.19991111755371094, 1.2715933322906494, 15.831915855407715]
2 [0.0, 0.0, 0.0, 0.0, 0.0, 0.12503726671039295, 0.09472344399590288, 0.1999776288967874, 0.131608969147562, 0.1553209370384522]

折线图中横坐标为log10(循环次数),纵坐标为秒数。

输出数据中,第一行为动态绑定和一次绑定耗费时间的差值,第二行为差值占动态绑定总时间的比例。

可以看出,在次数很小的时候,两者基本没有差距,或者说差距忽略不计。

在10^7次循环,即千万次循环的时候,动态绑定与静态绑定的耗费时间才出现了明显差异,当循环次数达到十亿级的时候,耗费时间相差15秒之多,约占总时间的15%。

由上可知,动态绑定效率低于静态绑定,但由于绑定代价耗时很少,在次数很少的时候基本没有影响。

动态绑定的优点:

class A:
  def test_hello(self):
    print("hello")

def test_world(self):
  print("world")

def main():
  s = A()
  # 提前绑定
  f = s.test_hello
  # 改变方法
  A.test_hello = test_world
  f()
  # 动态绑定
  s.test_hello()

if __name__ == "__main__":
  main()

输出结果:

hello2 world

类方法的变动能够实时反应在动态绑定上,而提前绑定则无法感知到类方法的变动。

总结:

1. 一次动态绑定代价很小,当绑定次数少的时候基本不影响效率,当绑定次数达到千万级时影响才会很显著。

2. 动态绑定实时跟踪类方法的变动,更具灵活性。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Java中重定向输出流实现用文件记录程序日志
Jun 12 Python
Eclipse中Python开发环境搭建简单教程
Mar 23 Python
实现python版本的按任意键继续/退出
Sep 26 Python
一个基于flask的web应用诞生 用户注册功能开发(5)
Apr 11 Python
python利用socketserver实现并发套接字功能
Jan 26 Python
Python3导入自定义模块的三种方法详解
Apr 13 Python
Python实现的查询mysql数据库并通过邮件发送信息功能
May 17 Python
对PyTorch torch.stack的实例讲解
Jul 30 Python
使用Python OpenCV为CNN增加图像样本的实现
Jun 10 Python
Flask框架中request、请求钩子、上下文用法分析
Jul 23 Python
基于python连接oracle导并出数据文件
Apr 28 Python
matplotlib自定义鼠标光标坐标格式的实现
Jan 08 Python
Python类和实例的属性机制原理详解
Mar 21 #Python
Python生成器常见问题及解决方案
Mar 21 #Python
Python作用域与名字空间原理详解
Mar 21 #Python
Python小整数对象池和字符串intern实例解析
Mar 21 #Python
Python描述符descriptor使用原理解析
Mar 21 #Python
Python如何省略括号方法详解
Mar 21 #Python
Python如何使用bokeh包和geojson数据绘制地图
Mar 21 #Python
You might like
优化NFR之一 --MSSQL Hello Buffer Overflow
2006/10/09 PHP
PHP读取ACCESS数据到MYSQL的代码
2011/05/11 PHP
二招解决php乱码问题
2012/03/25 PHP
php实现文件下载功能的几个代码分享
2014/05/10 PHP
php获取网页里所有图片并存入数组的方法
2015/04/06 PHP
Javascript里使用Dom操作Xml
2007/01/22 Javascript
js实现两个值相加alert出来精确到指定位
2013/09/25 Javascript
JS for循环中i++ 和 ++i的区别介绍
2016/07/20 Javascript
详解使用nodeJs安装Vue-cli
2017/05/17 NodeJs
js 开发之autocomplete="off"在chrom中失效的解决办法
2017/09/28 Javascript
详解react、redux、react-redux之间的关系
2018/04/11 Javascript
React性能优化系列之减少props改变的实现方法
2019/01/17 Javascript
nodejs中实现修改用户路由功能
2019/05/24 NodeJs
React冒泡和阻止冒泡的应用详解
2020/08/18 Javascript
uni-app 自定义底部导航栏的实现
2020/12/11 Javascript
[45:40]Ti4 冒泡赛第二天NEWBEE vs NaVi 1
2014/07/15 DOTA
python海龟绘图实例教程
2014/07/24 Python
Python sys.argv用法实例
2015/05/28 Python
Python中MySQL数据迁移到MongoDB脚本的方法
2016/04/28 Python
Python中xrange与yield的用法实例分析
2017/12/26 Python
python实现m3u8格式转换为mp4视频格式
2018/02/28 Python
PyQt5 QSerialPort子线程操作的实现
2018/04/21 Python
python随机在一张图像上截取任意大小图片的方法
2019/01/24 Python
python实现代码统计程序
2019/09/19 Python
numpy ndarray 取出满足特定条件的某些行实例
2019/12/05 Python
Python实现分数序列求和
2020/02/25 Python
Python异常原理及异常捕捉实现过程解析
2020/03/25 Python
Python任务调度模块APScheduler使用
2020/04/15 Python
如何通过安装HomeBrew来安装Python3
2020/12/23 Python
如何用Matlab和Python读取Netcdf文件
2021/02/19 Python
使用canvas绘制贝塞尔曲线
2014/12/17 HTML / CSS
购房意向书
2014/04/01 职场文书
2014财产信托协议书范本
2014/11/18 职场文书
个人政治思想总结
2015/03/05 职场文书
谢师宴家长致辞
2015/07/27 职场文书
爱护环境建议书
2015/09/14 职场文书