python对象地址学习

来源:互联网 发布:淘宝为什么打压外贸店 编辑:程序博客网 时间:2024/05/16 07:12

一、对象地址基础知识

python内置id()函数,这个函数用于返回对象的唯一标识(identity)。对象实际内存地址为hex(id(obj)),本文我将id()和内存地址划等号。

内置函数is(),用于比较两个对象的identity是否一样,举例:
(ob1 is ob2) 等价于 (id(ob1) == id(ob2))

a1 = '5'print id(a1)#输出:42662728,这个是a1指向的内存地址a1 = '100'a2 = '100'print id(a1), id(a2)#输出:43510440 43510440#这里python做了优化,没有为a2申请新的内存,而且将a1和a2指向相同的内存地址s1 =  'a' * 20s2 =  'a' * 20print id(s1), id(s2)#输出:43997704 43997704,说明20个char情况下,python仍然将两个引用指向了相同内存地址s1 =  'a' * 21s2 =  'a' * 21print id(s1), id(s2)#输出:50071400 50071568,在21个char的时候,python就没有做优化了,python为s2开辟了新的内存# int valuei1 = 10000000000000000000000..0000i2 = 10000000000000000000000..0000print id(i1), id(i2)#输出:39278152 39278152,两个变量大约测试650位,内存地址仍然是一样的。linux下行为不太一样,值为256后,两变量指向内存就不一样了。# float valuef1 = 250.5f2 = 250.5  print id(f1), id(f2)#输出:37976712 37976712,但在linux上两者的地址是不一样的

二、python的不可变(immutable)变量和可变变量

python不可变类型:int,string,float,tuple

#测试修改不可变变量u = 100print 'orgin id: %s'  %id(u)u = u + 10print 'new id  : %s' %id(u)#输出:#orgin id: 38833856#new id  : 38833616#开始的时候u指向int值100内存地址,因为int对象是不可变的,所以后面u值改为110后其实是分配了一个新的内存地址

python可变类型:object、list、set等

#a = []print id(a)a.append('a')    a.append('b')    a.append('c')print id(a)#输出:50809480,50809480,可见a指向内存的地址是没有改变的

三、方法参数传递

python参数传递是:传引用方式

def pass_immutable_var(v):    print 'inner before id:%d, value: %d' %(id(v),v)    v = 1000    print 'inner after id:%d, value: %d' %(id(v),v)if __name__ == "__main__":    v = 100    print 'before id:%d, value: %d' %(id(v),v)    pass_immutable_var(v)    print 'after id:%d, value: %d' %(id(v),v)输出:before id:37785280, value: 100inner before id:37785280, value: 100inner after id:41170808, value: 1000after id:37785280, value: 100可见才方法里修改了参数int值是不会修改原int值的
def pass_obj_ref(v):    print 'inner before id:%d, value: %s' %(id(v),v)    v.append(999)    print 'inner after id:%d, value: %s' %(id(v),v)if __name__ == "__main__":    v = ['100']    print 'before id:%d, value: %s' %(id(v),v)    pass_obj_ref(v)    print 'after id:%d, value: %s' %(id(v),v)#输出:  before id:50203400, value: ['100']inner before id:50203400, value: ['100']inner after id:50203400, value: ['100', 999]after id:50203400, value: ['100', 999]可见在pass_obj_ref中拿到和之前一样的对象引用,是可以修改原对象的数据的。

这个示例有个值得注意的事情,如果pass_obj_ref内只将执行“v = []”,这个是不会导致原数据被修改的,因为这个操作只是使pass_obj_ref中的v指向的新的内存地址,而原对象指针仍然指向[‘100’],这里是个容易出问题的地方,需要严重注意。

0 0