python将变量i的值增加1_Python中变量的赋值“=”问题

本文详细探讨了Python中变量赋值的原理,包括内存分配、引用计数和对象共享。通过实例展示了整型、字符串型、列表型、元组型和字典型对象在赋值时的不同行为,解释了为什么小整数和特定长度的字符串会被共享内存。
摘要由CSDN通过智能技术生成

1.jpg

写在前面

python中的“变量”是一个可以被赋值的广义对象,更确切地说是“引用”,它仅仅只是一个标签,其作用就是将它与内存中的某个实际对象(狭义对象)相联系,从而通过操作这个标签来操作实际对象。

一个变量不能孤立存在,创立之时就必须将其指向内存中的某个实际对象(即用‘=’操作),此时变量的类型、内存地址、值就是它指向对象的类型、内存地址、值。

一个变量本身不属于任何一种数据类型,python不会为一个变量分配内存,同一个变量可以指向不同类型的对象(例a=300,a='a', a=[300,'a'])。

Python通过引用计数机制实现自动垃圾回收功能,Python内存中的每个对象都有一个引用计数器,用于统计该对象还被哪些变量引用着。多一次引用,计数多一次,少一次引用,计数少一次。当计数为零时,Python会将该对象销毁,回收内存。

赋值操作,表面上是将“=”右边的量的值赋给左边的变量,但本质上是将右边的量对应的内存对象与左边的变量相联系的过程。见下例:

>>>a = 300

该赋值语句做了三件事:1)开辟了一块内存(可用id(a)查看地址);2)将该内存的值设为300;3)将变量a指向该内存。在重新将a指向其他对象之前,a就一直指向该内存,也就一直代表整数300。这里内存中的300是狭义“对象”,是个实实在在存在的东西。

在赋值语句中,通常有两种情况:

一种是将狭义对象赋值给变量,形如:“变量=对象”,例如a = 300、a = 'python cgx'、a = [1,2,3]、a = (1,2,3)等,这几个赋值语句右边都是实实在在的对象,是存在于内存中的。

另一种是将变量赋值给变量,形如:“变量=变量”,例如b=a,右边是一个已经存在的变量,注意它只是个引用,是个标签,不是具体对象,但它肯定已经指向某个真实的对象了,否则a是不能存在的。

这两种情况在python中有很大的不同,下面分别详细讨论。

(一)变量=对象,对象赋值给变量的情况

对于这种形式,我们也分两种情况讨论:

(1)赋值时,待赋值“对象”在内存中不存在

这种情况非常简单,遵循三步骤:开辟内存,指定内存对应的值,将其与变量相联系。如下:

>>>a = 300 #int

>>>b = 'python cgx' #string

>>>c = [1,2,3] #list

>>>d = (1,2,3) #tuple

>>>e = {'age':25} #字典

(2)赋值时,值相同的“对象”在内存中已经存在至少一个

对于这种情况稍微复杂,必须根据具体数据类型分别进行讨论:

1)int,整型

>>>a = 1

>>>b = 1

>>>id(a) #1598778384

>>>id(b) #1598778384

上例中a和b的指向的内存地址都是1598778384,说明在执行b=1时,并没有重新开辟内存,而是将变量b也指向已经存在的对象1上。但千万不要认为所有的int情况都一样,比如:

>>>a = 300

>>>b = 300

>>>id(a) #96391536

>>>id(b) #96391664

根据前一个例子的经验,这里a和b两个变量都指向对象300,因此id(a)和id(b)应该相同才对,然而实际上两者却是不同的,这是什么情况?到底哪些整数会相同,哪些会不同呢?为了解决这一问题,我们做如下实验

>>>for i in range(-1000,1000):

a = i #直接将i赋给a

b = int(i.__str__()) #先将i转化为字符串再转化为int,以区别将同值但新的i赋给b

if a is b: #判断a和b的地址是否相同

print(i)

-5

-4

-3

……

255

256

上述代码的目的是查看到底哪些整数会共享内存,从结果可以看出从-5开始到256结束,共262个整数会共享内存。这真是神奇的存在,特别是为啥负整数只到-5。这个问题暂时先不去深究。

python之所以这么干,是因为这些小的整数在编程时出现的频率非常高,如果不停地都生成销毁生成销毁,会使计算效率降低,为了减少这种操作,干脆就将所有重复创建小整数的情况都统统指向同一个已经存在的小整数上,只要还有一个变量连接到该小整数,他就不会被销毁。而且int数据是不可变对象,因此该小整数一旦在内存中被创建,就会一直存在,直到没有变量指向他才被销毁。

对于浮点数则不存在这种情况。

2)string,字符串型

字符串的情况跟int有点类似,对于短字符串(没有空格)和空字符串('')而言,共享内存;对于长字符串(有空格)而言,不共享内存。

>>>a = '' #空字符串

>>>b = ''

>>>id(a) #3504816

>>>id(b) #3504816

>>>a = 'sssssssssssssssssssssssssssssssss' #没空格,短字符串

>>>b = 'sssssssssssssssssssssssssssssssss'

>>>id(a) #96397424

>>>id(b) #96397424

>>>a = 's s' #有空格,长字符串

>>>b = 's s'

>>>id(a) #96387624

>>>id(b) #96388856

3)list,列表型

对于列表而言,比较简单,每次都开辟新的内存,生成新的对象,包括空列表[]。如下:

>>>a = [] #空列表

>>>b = []

>>>id(a) #96384072

>>>id(b) #96384264

>>>a = [1] #短列表

>>>b = [1]

>>>id(a) #41856328

>>>id(b) #41877640

>>>a = list(range(10000)) #长列表

>>>b = list(range(10000))

>>>id(a) #41880840

>>>id(b) #41880904

4)tuple,元组型

对于元组而言,每次都开辟新的内存,生成新的对象;但是对于空元组(),则共享内存。如下:

>>>a = () #空元组

>>>b = ()

>>>id(a) #3342408

>>>id(b) #3342408

>>>a = (1,) #短元组

>>>b = (1,)

>>>id(a) #37476560

>>>id(b) #37702512

>>>a = tuple(range(10000)) #长元组

>>>b = tuple(range(10000))

>>>id(a) #40619720

>>>id(b) #40699784

4)dict,字典型

对于字典而言,比较简单,每次都开辟新的内存,生成新的对象,包括空字典{}。如下:

>>>a = {} #空字典

>>>b = {}

>>>id(a) #34237752

>>>id(b) #34237824

>>>a = {'x':1} #短字典

>>>b = {'x':1}

>>>id(a) #5467448

>>>id(b) #5467520

>>>a = dict(enumerate(range(10000))) #长字典

>>>b = dict(enumerate(range(10000)))

>>>id(a) #41778560

>>>id(b) #41778632

(二)变量B=变量A,变量赋值给变量的情况

对于变量A对变量B赋值的情况(变量A必然已经指向某个内存对象了),无论哪种数据类型,无论长短复杂简单,都只有一个结果,即两个变量都指向相同的内存单元。这里用int举例, 其他情况不再赘述。

>>>a = 1 #简短整数,-5~256

>>>b = a

>>>id(a) #1598778384

>>>id(b) #1598778384

>>>a = 300 #复杂整数

>>>b = a

>>>id(a) #33205968

>>>id(b) #33205968

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值