python中的引用

部分引用自         http://www.cnblogs.com/yuyan/archive/2012/04/21/2461673.html

                           https://www.cnblogs.com/xinjing-jingxin/p/8620788.html

目录

一、引用简介

二、不可变数据类型的引用

2.1 字符串

2.2 浮点型

2.3 元祖

三、可变数据类型的引用

3.1 列表的引用

3.2 字典的引用

四、Copy


一、引用简介

1. python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。实际上,这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象——相当于通过“传值’来传递对象。

2. 当人们复制列表或字典时,就复制了对象列表的引用同,如果改变引用的值,则修改了原始的参数。

3. 为了简化内存管理,Python通过引用计数机制实现自动垃圾回收功能,Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被引用了多少次。每当引用一次Python对象,相应的引用计数就增1,每当消毁一次Python对象,则相应的引用就减1,只有当引用计数为零时,才真正从内存中删除Python对象。

二、不可变数据类型的引用

不可变数据类型包括字符串String、浮点型Float、整型Int、元祖Tuple。

2.1 字符串

#1.字符串引用
a='1234'
b=a
a='hello'
print('a:',a) #a:hello
print('b:',b)  #b:1234
#查看内存地址
print('a的内存地址是:',id(a))
print('a的内存地址是:',id(b))

结果是:

a: hello
b: 1234
a的内存地址是: 1651738050720
a的内存地址是: 1651737219456

分析:b的值指向a的值。python开辟了新的内存空间给b,所以a和b的内存地址不一样。

2.2 浮点型

#2.浮点型引用
x=3.14
y=x
x=9.88
print('x:',x)
print('y:',y)
print('x的内存地址是:',id(x))
print('y的内存地址是:',id(y))

结果是:

x: 9.88
y: 3.14
x的内存地址是: 2578075558248
y的内存地址是: 2578075558008

指向值的地址依然不同。

整型就略去了。

2.3 元祖

元祖虽然是序列,且包含多个元素,但是不支持原处修改,如tuple[1]=1是非法的。

#3.元祖引用
t1=(1,2,3,4,5)
t2=t1
t1=('tuple','hello')
print('t1:',t1)
print('t2:',t2)
print('t1的内存地址是:',id(t1))
print('t2的内存地址是:',id(t2))

结果是:

t1: ('tuple', 'hello')
t2: (1, 2, 3, 4, 5)
t1的内存地址是: 1599025348360
t2的内存地址是: 1599023460776

但是元祖虽然是不可变数据类型,但是有一点必须注意就是元祖中的每个元素都不可变,才可以,如下例子:

# 元祖不可变
t=(1,2,3,['A','a','B','b'])
t[3][0]='x'
t[3][2]='D'
print('t修改后为:',t)

结果是:

t修改后为: (1, 2, 3, ['x', 'a', 'D', 'b'])

分析:因为元祖中的第4个元素是列表,列表本身是可变数据类型。元祖所谓的不变,是内容的地址指向不变, 上面的这个例子中第四个元素又指向了列表,列表是可变的。所以,要创建一个内容不可变的元祖,必须保证元祖的每个元素不可变。

三、可变数据类型的引用

可变数据类别包括列表、字典

3.1 列表的引用

#4 列表的可变引用
list1=[1,2,3,4,5]
list2=list1
list1[3]='list'
print('list1=====%s'%list1)
print('list2=====%s'%list2)
print('list1的内存地址是:',id(list1))
print('list2的内存地址是:',id(list2))

结果是:

list1=====[1, 2, 3, 'list', 5]
list2=====[1, 2, 3, 'list', 5]
list1的内存地址是: 2769992249864
list2的内存地址是: 2769992249864

  函数的传递引用

def eggs(someParameter):
    someParameter.append('hello list')

spam=[1,2,3,4]
eggs(spam)
print(spam)

结果是:

[1, 2, 3, 4, 'hello list']

分析:当函数eggs被调用时,它没有使用返回值来为spam赋新值,而是直接修改了列表spam。尽管 spam 和 someParameter 包含了不同的引用, 但它们都指向相同的列表。这就是为什么函数内的 append('Hello')方法调用在函数调用返回后, 仍然会对该列表产生影响。

列表的引用指向的列表的地址,而不是内容,这样会修改原来列表本身,而不想修改原来的列表,需要使用copy方法,见后面。

3.2 字典的引用

#5 字典的引用
a={'name':'Cathy','age':'27','job':'coder'}
b=a
a['age']='30'
b['name']='Bob'
print('a======%s'%a)
print('b======%s'%b)
print('a的内存地址是:', id(a))
print('b的内存地址是:', id(b))

结果是:

a======{'name': 'Bob', 'age': '30', 'job': 'coder'}
b======{'name': 'Bob', 'age': '30', 'job': 'coder'}
a的内存地址是: 2510825602792
b的内存地址是: 2510825602792

四、Copy

部分摘自 https://blog.csdn.net/u011630575/article/details/78604226

在python2中需要import copy模块,python3中可以直接使用copy(),但是deepcopy()方法还需要导入模块。

copy()方法称为浅复制,

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值