《Abaqus GUI程序开发指南(Python语言)》——2.5 动态类型简介

简介:

本节书摘来自异步社区《Abaqus GUI程序开发指南(Python语言)》一书中的第2章,第2.5节,作者: 贾利勇 , 富琛阳子 , 贺高 , 周正光 更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.5 动态类型简介

前面讲述了Python中常用的数据类型,可以看出,在Python语言中使用变量时,都没有声明变量的存在以及类型,但变量还可以工作。这一点与静态编译语言C、C++或Java有很大的区别。这就是Python语言的动态类型模型。

在Python语言中,数据类型是在运行过程中自动决定的,而不是通过代码声明。变量在赋值的时候才被创建,它可以引用任何类型的对象,变量和对象分别存储在内存中的不同位置,两者通过链接进行关联。

对于下列代码:

>>>a=5

Python将会执行3个不同的步骤去完成这个请求,这些步骤反映了Python语言中所有赋值的操作过程。

(1)创建一个新对象来代表数字5。

(2)创建一个变量a。

(3)将变量a与新对象a相关联。

在Python中从变量到对象的链接称作引用。也就是说,引用是一种关系,以内存中的指针形式实现。一旦变量被使用(也就是被引用),Python自动跟随这个变量到对象的链接。

2.5.1 类型的归属
在Python语言中,类型属于对象,不属于变量,我们可以对一个变量进行多次赋值,且允许每次赋值的类型不同,例如:

【实例2.20】单变量多次赋值

>>>a=5         #将变量a与整型对象关联 
>>>a='five'       #将变量a与字符串型对象关联 
>>>a=5.0        #将变量a与浮点型对象关联

上述代码中,变量a一开始是整型,然后变成一个字符串,最后变成了浮点数。这一点,在C语言中是无法理解的。但是在Python中,理解起来就很简单,因为变量名根本没有类型。实际上Python的变量就是在特定的时间引用了一个特定的对象,而对象是具有类型的,每个对象都包含了一个头部信息,其中标记了对象的类型。

可以看出,Python代码比通常惯用的代码更加灵活,如果能正确地使用Python,代码能够自动以多种类型进行工作。

2.5.2 垃圾回收机制
在实例2.20中,当重新给变量a赋值时,它前一个引用对象是会发生变化的。在Python中,每当一个变量名被赋予了一个新的对象时,且之前的那个对象没有被其他变量名或对象所引用的话,那么之前的那个对象占用的空间就会被回收,这种自动回收对象占用空间的技术叫作垃圾回收。

在Python内部,垃圾回收是如何实现的呢?实际上,每个对象中都保持了一个计数器,计数器记录了当前指向该对象的引用次数,也就是该对象被引用的次数。一旦这个计数器被设置为零,这个对象的内存空间就会被自动回收。

垃圾回收最直接且可感受的好处就是,可以在脚本中任意使用该对象而不需要考虑释放内存空间。与C和C++这样的底层语言相比,省去了大量基础代码。

2.5.3 共享引用及原处修改
首先看一个两个变量的重复赋值实例。

【实例2.21】

>>> a=5 
>>> b=a 
>>> a,b 
(5, 5)

该实例中,第一行创建了对象5,并将变量a与之关联,第二行创建了变量b,变量b也成为对象5的一个引用。实际上,变量a和变量b都引用了相同的对象,都指向了相同的内存空间,这在Python语言中叫作共享引用——多个变量名引用同一对象。

对上述代码做如下修改:

>>> a=5 
>>> b=a 
>>> a ='five' 
>>> a,b 
('five', 5)

第三行代码创建了一个新的对象'five',并设置a对这个新的对象进行引用,而b仍然继续引用之前的对象5。

与其他语言不同,在Python中,给一个变量赋一个新的值,并不是替换了原始的对象,而是重新创建一个不同的对象,并让这个变量去引用这个新的对象。实际效果就是,对一个变量赋值,仅仅会影响被赋值的变量。

但是,也有一些特殊的情况,当引用一些可变对象时,在原处对对象进行修改时,就会出现不一样的情况。例如,在一个列表中对某一个偏移位置进行重新赋值时,会改变这个列表对象,而不是生成一个新的对象。首先看一个容易理解的实例:

【实例2.22】

>>> a=[1,2,3] 
>>> b=a 
>>> a 
[1, 2, 3] 
>>> b 
[1, 2, 3] 
>>> a=999 
>>> a 
999 
>>> b 
[1, 2, 3]

由程序执行结果可以看出,上述实例中一开始变量a和b都引用了列表对象[1,2,3],后来当对a重新赋值后,创建了新的对象999,并让a引用了这个新的对象,整个过程中b并没有发生变化,这与前面的实例类似,同属于共享引用的范畴。

然而,列表中的元素都是通过其索引位置进行读取的,例如:

>>> a=[1,2,3] 
>>> b=a 
>>> a[0],a[1],a[2] 
(1, 2, 3)

其中,a[0]引用的是对象1,a[1]引用的是对象2,a[2]引用的是对象3。当然,列表自身也是一个对象,接下来对上述代码做一下简单的修改,就会出现明显不同的结果。

【实例2.23】

>>> a=[1,2,3]    #创建列表对象[1,2,3]和变量a,并让a引用该对象 
>>> b=a      #创建变量b,并让b引用同一列表对象 
>>> a 
[1, 2, 3] 
>>> b 
[1, 2, 3]          #变量a和b数值相同 
>>> a[0]='one'       #修改变量所引用的对象的一个元素 
>>> a 
['one', 2, 3]         #变量a数值发生变化 
>>> b 
['one', 2, 3]         #变量b数值也发生变化

在上述程序中,我们没有改变a,只是改变了a所引用对象的一个元素,这类修改会覆盖列表对象中的某些部分,它不仅仅会影响变量a,也会同时影响变量b,因为它们引用的是同一个列表对象。对于这种在原处修改的对象,共享引用时需要加倍小心,不注意的话非常容易出错。

如果不希望上述情况出现时,需要使用Python的对象复制,而不是创建引用。Python有多种复制列表的方法,现列举如下。

【实例2.24】列表对象复制

>>> a=[1,2,3] 
>>> b=a[:]         #复制列表 
>>> a 
[1, 2, 3] 
>>> b 
[1, 2, 3] 
>>> a[0]=999 
>>> a 
[999, 2, 3] 
>>> b 
[1, 2, 3]           #a引用的列表中某一元素变化时,b未改变。

这种情况下,对a的修改不会影响b,因为b引用的是a所引用对象的复制,两个变量指向了不同的内存区域。需要注意的是,这种分片技术不能用于集合和字典等非序列类型的对象中。

除了上述复制方法之外,还可以使用copy()函数实现,例如:

【实例2.25】copy()函数

>>> import copy 
>>> a=[1,2,3] 
>>> b=copy.copy(a) 
>>> b 
[1, 2, 3] 
>>> a[0]=999 
>>> a 
[999, 2, 3] 
>>> b
[1, 2, 3]

另外,需要注意的是,copy()函数可以用于集合或者字典等无序的对象类型中。
**
2.5.4 共享引用和相等**
由于Python的引用机制,在Python程序中有两种不同的方法去检查两个变量是否相等,以下面的共享引用来说明。

【实例2.26】

>>> a=[1,2,3] 
>>> b=a 
>>> a==b 
True 
>>> a is b 
True

上述代码中,第一种判断方法是采用“==”操作符,测试两个变量所引用的对象是否有相同的值。第二种方法“is”操作符,是检查对象的同一性,如果两个变量a和b均指向同一个对象,它会返回True,所以这是一种更严格的相等测试。如果两个变量名引用的对象值相等,但是是不同的对象,那么在使用“is”操作符进行判断时,它会返回False,例如:

【实例2.27】

>>> a=[1,2,3] 
>>> b=[1,2,3] 
>>> a==b 
True 
>>> a is b 
False

上面的代码中,第一行创建了一个列表对象[1,2,3]和变量a,并将变量a与之关联,第二行又创建了一个列表对象[1,2,3]和变量b,变量a和b引用的对象数值相同,却不是同一个对象。

另外,需要特别注意的就是,当我们对小的数字采用上述同样的操作时,返回的结果会有所不同,例如:

【实例2.28】

>>> a=1 
>>> b=1 
>>> a==b 
True 
>>> a is b 
True

为什么这组测试的结果和实例2.27测试的结果互相矛盾呢?原因就是,对于小的整数和字符串,Python会将其缓存并复用,所以在本实例中才会出现a和b引用的是同一个对象的现象。

如果读者想弄清楚一个对象被引用的次数的话,可以使用sys模块下的getrefcount函数来查询一个对象被引用的次数。例如:

>>> import sys 
>>> sys.getrefcount(1) 
1044 
>>> sys.getrefcount(5) 
91
相关文章
|
1月前
|
存储 索引 Python
Python散列类型(1)
【10月更文挑战第9天】
|
1月前
|
计算机视觉 Python
Python实用记录(一):如何将不同类型视频按关键帧提取并保存图片,实现图片裁剪功能
这篇文章介绍了如何使用Python和OpenCV库从不同格式的视频文件中按关键帧提取图片,并展示了图片裁剪的方法。
77 0
|
1月前
|
存储 数据安全/隐私保护 索引
Python 散列类型三以及函数基础
【10月更文挑战第11天】
Python 散列类型三以及函数基础
|
1月前
|
网络协议 Java Linux
PyAV学习笔记(一):PyAV简介、安装、基础操作、python获取RTSP(海康)的各种时间戳(rtp、dts、pts)
本文介绍了PyAV库,它是FFmpeg的Python绑定,提供了底层库的全部功能和控制。文章详细讲解了PyAV的安装过程,包括在Windows、Linux和ARM平台上的安装步骤,以及安装中可能遇到的错误和解决方法。此外,还解释了时间戳的概念,包括RTP、NTP、PTS和DTS,并提供了Python代码示例,展示如何获取RTSP流中的各种时间戳。最后,文章还提供了一些附录,包括Python通过NTP同步获取时间的方法和使用PyAV访问网络视频流的技巧。
248 4
PyAV学习笔记(一):PyAV简介、安装、基础操作、python获取RTSP(海康)的各种时间戳(rtp、dts、pts)
|
24天前
|
数据可视化 开发者 Python
Python GUI开发:Tkinter与PyQt的实战应用与对比分析
【10月更文挑战第26天】本文介绍了Python中两种常用的GUI工具包——Tkinter和PyQt。Tkinter内置于Python标准库,适合初学者快速上手,提供基本的GUI组件和方法。PyQt基于Qt库,功能强大且灵活,适用于创建复杂的GUI应用程序。通过实战示例和对比分析,帮助开发者选择合适的工具包以满足项目需求。
77 7
|
1月前
|
Python
【10月更文挑战第6天】「Mac上学Python 11」基础篇5 - 字符串类型详解
本篇将详细介绍Python中的字符串类型及其常见操作,包括字符串的定义、转义字符的使用、字符串的连接与格式化、字符串的重复和切片、不可变性、编码与解码以及常用内置方法等。通过本篇学习,用户将掌握字符串的操作技巧,并能灵活处理文本数据。
55 1
【10月更文挑战第6天】「Mac上学Python 11」基础篇5 - 字符串类型详解
|
1月前
|
Python
【10月更文挑战第6天】「Mac上学Python 10」基础篇4 - 布尔类型详解
本篇将详细介绍Python中的布尔类型及其应用,包括布尔值、逻辑运算、关系运算符以及零值的概念。布尔类型是Python中的一种基本数据类型,广泛应用于条件判断和逻辑运算中,通过本篇的学习,用户将掌握如何使用布尔类型进行逻辑操作和条件判断。
62 1
【10月更文挑战第6天】「Mac上学Python 10」基础篇4 - 布尔类型详解
WK
|
1月前
|
存储 Python
Python内置类型名
Python 内置类型包括数字类型(int, float, complex)、序列类型(str, list, tuple, range)、集合类型(set, frozenset)、映射类型(dict)、布尔类型(bool)、二进制类型(bytes, bytearray, memoryview)、其他类型(NoneType, type, 函数类型等),提供了丰富的数据结构和操作,支持高效编程。
WK
18 2
|
1月前
|
程序员 PHP Python
Python3 简介
【10月更文挑战第8天】Python3 简介。
28 4
|
1月前
|
存储 编译器 索引
Python 序列类型(2)
【10月更文挑战第8天】
Python 序列类型(2)
下一篇
无影云桌面