Python中变量的赋值“=”问题

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容

  • 包(lib)、模块(module) 在Python中,存在包和模块两个常见概念。 模块:编写Python代码的py...
    清清子衿木子水心阅读 3,805评论 0 27
  • 一、快捷键 ctr+b 执行ctr+/ 单行注释ctr+c ...
    o_8319阅读 5,816评论 2 16
  • 1 实现通过线程池执行任务 创建了一个ThreadPoolExecutor,参数中使用了默认的线程创建工厂Defa...
    冷冷DerFan阅读 447评论 0 1
  • 表弟来家跟老爹喝了酒 喝多了老爹说想他老爹抹眼泪了 20年左右了吧 我也是第一次见老爹如此
    鬼懿阅读 132评论 0 0
  • 我写作业太磨蹭,每天都要写到十一二点,写作业太糊弄了,我要把这个错误改掉。承诺人:陈盈佳
    陈盈佳阅读 363评论 0 0