首页 > 编程语言 >Python-动态类型

Python-动态类型

时间:2024-03-06 15:14:42浏览次数:26  
标签:变量 Python 对象 引用 类型 动态 赋值

动态类型

在Python中,类型是在运行时自动确定的,而不是通过代码声明,即Python没有必要事先声明变量。

1. 变量、对象和引用

变量创建:一个变量在代码第一次给它赋值时就创建了它,之后的赋值将会改变已创建的变量的值;Python在代码运行之前会先检测变量名,是最初的赋值操作在创建变量

变量类型:变量永远不会拥有与它相关联的类型信息或约束。类型的概念存在于对象而不是变量名中,变量原本是通用的,它只是在特定的时间引用了一个特定的对象而已。

变量使用:当变量出现在表达式中时,它会马上被当前引用的对象所替代,无论这个对象是什么类型。因此所有变量必须在使用前被明确地赋值,使用未赋值的变量会产生错误。

变量在赋值的时候才被创建,它可以引用任何类型的对象,并且必须在引用之前赋值。

以赋值语句a = 3为例,Python会执行以下三个步骤:

  • 创建一个对象来代表值3
  • 创建一个变量a,如果它还没有创建的话
  • 将变量与新的对象3相连接

变量、对象和引用1

变量和对象保存在内存中的不同部分,并通过连接相关联。变量总是连接到对象,并且绝不会连接到其它变量上。在Python中,从变量到对象的连接称作引用,引用是一种关系,通过内存中的指针的形式来实现。一旦使用(引用)变量,Python将自动追踪这个变量到对象的连接。

  • 变量是一个系统表的入口,包含了指向对象的连接
  • 对象是被分配到的一块内存,有足够的空间去表示它们所代表的值
  • 引用是自动形成的从变量到对象的指针

对象包含了更复杂的结构,每个对象都有两个标准的头部信息——类型标志符(type designator)标识这个对象的类型;引用计数器(reference counter)决定何时回收这个对象。

2. 类型属于对象而不是变量

>>> a = 3
>>> type(a)
<class 'int'>
>>> a = 'spam'
>>> type(a)
<class 'str'>
>>> a = 1.23
>>> type(a)
<class 'float'>

上面的代码中,表面上看a的类型从一个整数变成了一个字符串最后又变成了一个浮点数。事实上并非如此,在Python中,类型属于对象而不是变量。上面的连续赋值只是把a修改为对不同对象的引用,因为变量没有类型,实际上并没有改变变量a的类型。实际上,Python的变量就是在一个特定的时间引用了一个特定的对象

从另一方面上看,对象知道自己的类型,每个对象都包含一个头部信息,其中标记了这个对象的类型。例如整数对象3,包含了值3以及一个标志符,标志符指向了一个整数类型。

3. 对象的垃圾回收

在Python中,每当一个变量被赋予一个新的对象时,如果原来的对象没有被其他的变量或对象所引用的话,那么之前那个对象占用的空间就会回收。这种自动回收对象空间的技术叫做垃圾回收

>>> x = 42
>>> x = 'shrubbery'    # 回收42
>>> x = 3.1415         # 回收'shrubbery'
>>> x = [1, 2, 3]      # 回收3.1415
# 当每一次x被赋值给一个新的对象,Python都会回收之前对象的空间(假设之前的对象没有被其他变量或对象所引用),回收之后对象的空间将会自动放入内存空间池,等待后来的对象使用

在内部Python的垃圾回收是这样实现的:Python在每个对象中保留了一个计数器,计数器记录当前指向该对象的引用的数目,一旦这个计数器被设置为零,那么这个对象的内存空间就会自动回收。

4. 共享引用

>>> a = 3
>>> b = a

语句b = a将会创建变量b,变量a正在被使用,并且变量b没有被赋值,因此变量b被替换成其引用的对象3。实际的效果就是变量a和变量b都引用了相同的对象(也就是说指向了相同的内存空间)。

image-20240305110229152

这种多个变量引用了同一个对象的情况在Python中称为共享引用虽然变量a和变量b是共享引用的,但它们并没有彼此关联,真实情况是两个变量通过它们的引用指向了同一个对象。

>>> a = 3
>>> b = a       # a = 3, b = 3
>>> a = 'spam'  # a = 'spam', b = 3
# 对变量a进行新的赋值并不会改变变量b的值,变量b任然引用对象3,只是变量a引用了新的对象'spam'

image-20240305111622737

将变量a赋值为一个值并不会连带着改变变量b,除非改变对象3的值,但是对象3是一个整数,整数是不可变的,因此无法在原位置修改它。

在Python中变量总是一个指向对象的指针,而不是可改变的内存区域的标签,该变量赋一个新值并不是替换原始的对象,而是让这个变量去引用完全不同的一个对象。

对于引用的对象是不可变类型时,共享引用的实际效果就是对一个变量赋值仅仅会影响那个被赋值的变量。

5. 共享引用和在原位置修改

在Python中有一些对象和操作(包括列表、字典和集合在内的Python可变类型)确实可以在原位置改变对象。

对于可变类型的对象,可变类型支持在原位置修改,此时使用共享引用要格外小心,因为对一个变量的修改会影响其他的变量。

>>> L1 = [2, 3, 4]
>>> L2 = L1
>>> L1[0] = 24
>>> L1
[24, 3, 4]
>>> L2
[24, 3, 4]

上面的代码中并没有改变L1,而是改变了L1所引用的一个元素,这类修改会在原位置覆盖列表对象的某部分值,因为这个列表对象是与其他对象共享的,那么像这样在原位置的修改就不不仅仅会影响L1,也会影响其他引用该列表的变量(如L2)。

如果不想这种对可变对象的共享引用导致所有引用的变量发送非预期改变,那么可以在创建对象时赋值可变对象而不是创建引用:

>>> L1 = [2, 3, 4]
>>> L2 = L1[:]  # 使用切片拷贝列表
>>> L1[0] = 24
>>> L1
[24, 3, 4]
>>> L2
[2, 3, 4]

对于字典和集合,复制一个字典或集合对象可以使用X.copy()方法:

import copy
X = copy.copy(Y)
X = copy.deepcopy(Y)

6. 共享引用与相等

对特定类型而言,垃圾回收机制并不总是当对象不被其他变量引用后就马上回收,Python缓存并复用了小的整数和小的字符串,这些缓存的对象可能仍被保存在一个系统表中,等待代码的下一次引用,但大多数其他类型的对象都会在不再被引用时马上回收

Python有两种检查是否相等的方法:

  • "=="运算符:"=="运算符用于测试两个被引用的对象是否有相同的值
  • "is"运算符:"is"运算符用于检查对象的同一性,只有两个变量精确地指向同一个对象,is运算符才会返回True
>>> L = [1, 2, 3]
>>> M = L
>>> L == M
True
>>> L is M
True

如果两个变量引用的值相同但是对象不同,is运算符将返回False:

>>> L = [1, 2, 3]
>>> M = [1, 2, 3]  # M和L都引用了值为[1, 2, 3]的对象,但那是创建的两个不同的列表对象
>>> L == M
True
>>> L is M
False

对于小整数和小字符串,由于Python会缓存它们,因此is运算符的结果将会有所不同:

>>> L = "abc"
>>> M = "abc"
>>> L == M
True
>>> L is M
True
>>> L = 42
>>> M = 42
>>> L == M
True
>>> L is M
True
# 本来L和M应该不是is同一个对象的,但是由于小整数和小字符串被缓存并复用了,所以是is同一个对象

可以使用Python标准库的sys模块中的getrefcount函数返回对象的引用次数:

import sys
sys.getrefcount(X)

弱引用

标签:变量,Python,对象,引用,类型,动态,赋值
From: https://www.cnblogs.com/N1rv2na/p/18056625

相关文章

  • SpringBoot中集成LiteFlow(轻量、快速、稳定可编排的组件式规则引擎)实现复杂业务解耦
    场景在业务开发中,经常遇到一些串行或者并行的业务流程问题,而业务之间不必存在相关性。使用策略和模板模式的结合可以解决这个问题,但是使用编码的方式会使得文件太多,在业务的部分环节可以这样操作,在项目角度就无法一眼洞穿其中的环节和逻辑。一些拥有复杂业务逻辑的系统,核心业......
  • 使用python编程实现多个csv文件数据的合并和输出
    具体代码importpandasaspdimportosdf01=pd.read_csv("D:\\12140\\Desktops\\111\\t11.csv",encoding='utf-8',dtype='str')df02=pd.read_csv("D:\\12140\\Desktops\\111\\t12.csv",encoding='utf-......
  • /usr/bin/install: 无法更改“/usr/local/python397/bin“ 的权限: 没有那个文件或目
    /usr/bin/install:无法更改“/usr/local/python397/bin“的权限:没有那个文件或目录dragoo1于2021-09-2116:39:21发布阅读量3.7k收藏9点赞数4分类专栏:python文章标签:pythoninstall没有那个文件或目录版权python专栏收录该内容3篇文章0订阅订阅专栏编译python......
  • Python实现五子棋人机对战的二次开发
    Python实现人机对战的二次开发    在网上找到了一个使用python实现五子棋游戏,其中通过加入一个简单的AI算法实现了人机对战的功能,我觉得这个人机对战还是蛮有意思的,下面我分析一下五子棋游戏的规则、棋盘表示方法、AI算法的实现原理以及代码实现过程。最后二次开发时引入新的......
  • python-合并大型Excel
    使用openpyxl库实在是太慢,使用openpyxl的只读模式又需要excel的准确尺寸信息,但是每个excel的尺寸都不一样。我使用zipfile解压excel文件,直接读取xml文件进行合并:importosfromopenpyxlimportload_workbookfromopenpyxlimportWorkbookimportzipfileimportretotal_......
  • 01_C++基本数据类型_算数类型
    1.算数类型算数类型主要分为两类——整型和浮点型带符号和无符号类型带符号:int、short、long和longlong,通过在这些类型名前添加unsigned可以得到无符号类型。 选择符号的准则:(1)数值不可能为负时,选择无符号类型。(2)使用int执行整数运算。(3)算数表达式不要使用char或bool,存放字......
  • C语言基础-1、逻辑类型和运算
    一、逻辑类型和运算#include<stdbool.h>之后就可以使用bool和true、falseex1:#include<stdio.h>#include<stdbool.h>intmain(){ boolb=6>5; boolt=true; printf("%d\n",t); t=2; printf("%d\n",t); printf("%d\n&q......
  • Rust 开发的高性能 Python 包管理工具,可替换 pip、pip-tools 和 virtualenv
    最近,我在Python潮流周刊中分享了一个超级火爆的项目,这还不到一个月,它在Github上已经拿下了8Kstar的亮眼成绩,可见其受欢迎程度极高!国内还未见有更多消息,我趁着周末把一篇官方博客翻译出来了,分享给大家。作者:@charliermarsh译者:豌豆花下猫@Python猫英文:uv:Pythonpackag......
  • python的方法
    调用方法是必须先要又一个字符串变量,然后用“.”引出方法,函数则是直用1.常用方法说明:str表示一个字符串变量(1)str.lower()作用:返回的是str的里面的小写形式,并没有改变str(2.)str.upper()作用和lower相反,返回的变量大写(3.)str.split()作用:拆分出参数并形成列表(4.)str.count(s......
  • Python zip函数及用法
    zip()函数是Python内置函数之一,它可以将多个序列(列表、元组、字典、集合、字符串以及range()区间构成的列表)“压缩”成一个zip对象。所谓“压缩”,其实就是将这些序列中对应位置的元素重新组合,生成一个个新的元组。importnumpyasnpmy_list=[11,12,13]my_tuple=(21......