首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
高性能编程基础:类、对象
高性能编程基础:进程与线程
多进程与多线程
高并发编程的挑战
高性能编程的挑战
Python线程安全性的实现
Python线程同步的实现
Python原子性的实现
CPython虚拟机
Python代码执行过程分析
Python代码执行性能优化原理
基于Pypy的Python代码执行性能优化原理
高并发与高性能之间的关系
从源码角度剖析Python对象的创建过程
Python对象的状态
Python对象的内存回收机制
Threading模块与高并发
Threading模块中常用方法和类的实现原理解析
Python线程的创建与使用
Python协程的基本概念
EventLoop的运作原理
Python中EventLoop的实现
深入理解Asyncio库
使用EventLoop和Asyncio库实现Python协程
Python线程阻塞现象及原因分析
为什么会出现Python线程竞争
如何保证Python线程顺序执行
线程间通信-单线程的等待
多线程之间的通信
Python线程死锁现象及原因分析
Python中如何实现锁
Python中主流的内置锁及其实现原理
Python中GIL与线程锁的区别和联系
公平锁与非公平锁
Python线程安全介绍
实现Python线程安全
什么是线程优先级
Python线程优先级的实现
线程同步与异步
Python中的线程同步实现
Python中的线程异步实现
Python中的原子变量与原子性操作
原子变量与原子性操作的实现原理
什么是线程池
Python线程池的实现方式
当前位置:
首页>>
技术小册>>
Python高并发编程与实战
小册名称:Python高并发编程与实战
### 1.1 Python中的类 Python作为一门面向对象的高级编程语言,提供了丰富的面向对象编程的实现,包括面向对象语言中的类、对象。对于任意一门面向对象的高级编程语言,最基础的特性都是封装、继承和多态,而实现这些特性的基础正是面向对象编程语言中的类。 类是真实世界中的事务在Python语言中的一种实现,其规定了真实世界中的事务在Python语言中的组成,是使用Python来描绘真实世界中事务的手段。在真实世界中,事务可能是一个非常大的问题,也可能是一个非常小的问题,即在真实世界中,事务本身不是一个定数,所以,Python中类的设计也是如此。 Python中的类规定了真实世界中的事务在Python中的定义和实现,我们可以通过以下代码定义Python中的类: ![](/uploads/images/20231206/47bfdb4b9066836181731f648e41210a.png) 执行上述代码即可创建一个名为[className]的Python类。在Python中存在一个全局解释器,该解释器用来执行Python代码。Python解释器将处理类的过程全部执行完毕后,通过上述代码创建的Python类才能被真正创建。 Python中的类在被创建之后,在类的同一生命周期下,就不允许继续修改了,因为该类已经被转义为Python解释器可识别的代码,这些代码已经被解释和执行了。如果需要继续修改该Python类,我们可以先在该Python类中编写需要修改的内容,然后手动执行并重新解释。 在了解了Python类的创建过程和解释过程之后,我们真正创建一个Python类来进一步了解Python类的组成。根据上述创建类的代码,我们创建一个名为HelloPython的类,并且在HelloPython类中先定义两个成员变量strA和strB,再定义两个方法:一个方法被声明为Hello,另一个方法被声明为World。创建HelloPython类的代码如下所示。 ![](/uploads/images/20231206/0d1e6117a71c2a984b41afa33ab931ff.png) 我们再来看一下HelloPython类所在的目录结构,以PyCharm代码编辑器为例,HelloPython所在目录结构如图1-1所示。 ![](/uploads/images/20231206/24f9b00a0f2ac362798da8da03dae832.png) 这里是在一个名为highPro的项目中创建HelloPython类。highPro项目是本书所使用的项目,该项目会在后文进行介绍。 通过图1-1可知,HelloPython类所在的Python文件名为HelloWorld,并不是HelloPython,这在Python语言中是允许的,但是在Java语言中会直接报错,连编译都不能。这就是Python语言和Java语言最显著的区别。 Python解释器在解释Python代码时,会先对Python代码进行编译,在编译通过之后,才会将编译的Python代码交给Python解释器(虚拟机)来执行,这是Python代码解释的全过程,而在这个过程中会有不同类型的文件产出。我们以HelloPython类为例展开介绍,如图1-2所示。 ![](/uploads/images/20231206/877eba20f8d60ff7fc2c8eacd494034f.png) 通过图1-2可知,HelloPython类会先被Python编译器进行编译。在编译阶段,Python编译器会检查HelloPython类代码是否符合Python语言所规定的语法格式和语义规范,还会检查各种变量的定义和引用等。只有这些检查项全部通过,编译才能通过,这些检查项中只要有一项存在异常或错误,Python编译器就会立即中断编译,向用户抛出异常或错误。重复该过程,直到编译通过。 在HelloPython类编译通过后会输出HelloPython类字节码文件,如图1-3所示。 ![](/uploads/images/20231206/930398372fb967b120e69fe65c36bb16.png) 通过图1-3可知,HelloPython类生成的字节码文件名为HelloWorld.cpython-39.pyc,大小为1KB。HelloPython类字节码文件名称由4部分组成。 ● HelloWorld:表示Python文件的名称,即HelloPython类所在的Python文件的名称。 ● cpython:表示HelloPython类被哪种虚拟机编译,本书使用的是Python默认实现的CPython虚拟机,所以这里是cpython。 ● 39:表示当前Python版本在CPython虚拟机中对应的字节码版本号,该版本号默认由采用的Python版本的第一位大版本号和第二位小版本号组成,忽略其余位数的版本号。本书采用的Python版本是3.9.5,取前两位来表示这一字节码版本号,忽略后面的5,所以这里是39。 ● pyc:这是文件的后缀名,表示当前的文件类型是Python字节码文件,而不是Java字节码文件。Java字节码文件名以javac结尾。 接着将HelloPython类字节码文件交由CPython虚拟机处理。CPython虚拟机的主要工作是解析HelloPython类字节码文件,并根据该字节码文件中的内容为HelloPython类中的各种变量分配内存空间,为各种方法创建执行所需的栈帧空间。如果该类中存在类的实例,CPython虚拟机会为该类的实例分配内存空间,并初始化该类的实例的其他属性。下面介绍HelloPython类字节码文件中的底层内容,以便更好地理解Python类字节码文件,如图1-4所示。 ![](/uploads/images/20231206/23a2e97996c6c82a921f40e3c612a462.png) 这里我们只需要看3个部分。第一部分是图1-4所示的前8位,即610D0D0A。这部分是Python字节码的第一部分,即Python语言中的魔数。CPython虚拟机根据这8位内容判断当前需要处理的字节码文件是不是Python字节码文件。 如果一个字节码文件的头内容中包含610D0D0A,就表示该字节码文件是Python字节码文件,此时CPython虚拟机才会继续向下解析该文件,否则会终止解析,并向用户抛出异常或错误。CPython虚拟机所能识别的Python字节码的魔数,同样会随着Python版本而发生改变,并不是固定不变的。 第二部分是图1-4所示的第8列到第B列的内容,即DA808C62。这8位表示Python字节码文件头的大小。我们可以使用数据解释器计算出该类字节码文件头的大小,如图1-5所示。 第三部分是Offset,即偏移量从00000000往下一直到该文件结束(不包含00000000)的内容,这部分就是HelloPython类中的字段、方法或者实例被编译成字节码之后的内容。 ![](/uploads/images/20231206/06b61d83bd2d8dccd05a7b524bec7c59.png) 回到我们平常所说的Python代码解释过程,结合笔者对HelloPython类代码的解析过程可以得出,Python语言中所说的解释器其实就是Python编译器和Python虚拟机结合的产物,即Python代码的编译和Python虚拟机的处理是同一时机触发的,只不过这个过程没有对外暴露而已。 ### 1.2 Python中的对象 本质上来说,Python中的对象是对Python中的类进行实例化后输出的产物。Python中的对象和Python中的基本类型变量在实现方式上是完全不同的。 对于Python中的基本类型变量来说,Python官方在Python语言层面已经进行了规定或约束。以数字类型变量来说,在Python语言对外发布时,数字类型已经被固化到了Python语言当中,并且通过一定的数字占位,与Python虚拟机中的语义规范进行对应,即我们在Python中声明了数字类型的基本变量之后,Python虚拟机通过已经固化好的数字占位来识别这一变量所属的类型。 Python中的对象本身也是一种变量,只不过这种变量的类型是随机的、可变的,这是与Python中的基本类型变量最大的不同之处。Python官方规定了Python对象在Python虚拟机中的存活方式,即以一种对象地址的形式在Python虚拟机中存在,且对象的生命周期交由Python虚拟机自动管理,不需要开发者手动管理Python对象的生命周期。需要开发者做的,只是创建Python对象。 在Python中,创建一个类的对象的代码如下所示。 ![](/uploads/images/20231206/f9297defafcd457c53d07336e0bd62a0.png) 在上述代码中,我们定义了一个名为ExampleClass的类,并且在ExampleClass类中声明了两个数字类型变量NumsA和NumsB,还声明了一个名为demo的方法,该方法最终返回hello python。我们将ExampleClass类定义完毕之后,就可以在需要用到的地方对它进行实例化了。在上述代码中,ExampleClassObject=ExampleClass()代码通过ExampleClass()的方式将定义好的ExampleClass类实例化,即通过ExampleClass()的方式创建ExampleClass类的对象,并用ExampleClassObject变量来接收。 和其他面向对象的编程语言创建类的对象的方式不同,在Python中不需要通过new关键字创建对象,只需要在类的名称后面添加一对英文状态下的小括号就可以了。其他面向对象的高级编程语言中的对象的基本组成,如对象的头信息、对象的实例数据、对象的填充数据,在Python语言中也有。 在执行了ExampleClass()之后,Python解释器会首先确定与ExampleClass()对应的类的类型。在确定对应类的类型后,Python解释器便和Python虚拟机共同为ExampleClass()类型对象分配一定的内存空间,从而存储ExampleClass()对象。在这些基础的分配流程完成之后,我们还为ExampleClass()对象赋予一个变量,即ExampleClassObject。 所以,访问ExampleClass()对象中的字段或者方法可以通过ExampleClassObject变量来实现。值得注意的是,ExampleClassObject变量中并不会存储ExampleClass()对象本身,而是存储ExampleClass()对象的副本地址,使其成为ExampleClass()对象的一个引用,并最终以这种引用的方式存在。在Python中,通过ExampleClassObject变量来访问ExampleClass()对象时始终会使用引用的方式。
下一篇:
高性能编程基础:进程与线程
该分类下的相关小册推荐:
Python合辑8-变量和运算符
Python机器学习基础教程(下)
Python合辑2-字符串常用方法
Python与办公-玩转PDF
Python合辑1-Python语言基础
Python3网络爬虫开发实战(上)
Python数据分析与挖掘实战(下)
Python机器学习实战
Python编程轻松进阶(一)
Python与办公-玩转Excel
Python编程轻松进阶(三)
机器学习算法原理与实战