Python中对象

Python对象操作

对象 (Objections) 是 python 中数据的抽象,python 中所有的数据均可以用对象或者是对象之间的关系来表示。每个对象均有标识符( identity)、类型 (type)、值 (value)

  1. 标识符:对象一旦创建,那么它的标识符就不会改变,可以把标识符看作对象在内存中的地址。 is 操作可以用来比较两个对象的标识符,函数 id() 用来返回对象标识符。
  2. 类型:对象的类型也是不可变的,对象的类型决定了该对象支持的操作,另外也决定了该对象可能的值。 type() 函数返回一个对象的类型。
  3. :一些对象的值可以改变,我们叫它可变对象;值不可改变的对象我们叫它不可变对象。

对象的操作包括:

  1. 构造操作:这类操作主要是基于一些已知信息,产生这个类的实例对象;
  2. 解析操作:这类操作是获取对象的一些有用信息,其结果反应了对象的一些特征,但返回的不是对象本身。
  3. 变化操作 :这类操作是修改对象内部的信息和状态。

如果一个类型,具只具有1和2两种操作,也就说只具有构造和解析操作,那么这个类型就是不可变类型,这个类型的对象就是不可变对象。
如果一个类型,具有1、2、3三种操作,这个类型就是可变类型,这个类型的对象就是可变对象

显然可变对象和不可变对象的区别在于 3 变化操作。

不可变对象

python 中的不可变对象有整型 (int),浮点型 (float),字符串型 (str), 元组 (tuple)

赋值

首先看一下整型,浮点型,字符串型和元组的赋值操作:

i1 = 205464113
i2 = 205464113
i3 = i1
print(id(i1))
print(id(i2))
print(id(i3))
print(i1 is i2)
print(i1 is i3)
print('**********')

f1 = 1.574
f2 = 1.574
f3 = f1
print(id(f1))
print(id(f2))
print(id(f3))
print(f1 is f2)
print(f1 is f3)
print('**********')

str1 = 'james'
str2 = 'james'
str3 = str1
print(id(str1))
print(id(str2))
print(id(str3))
print(str1 is str2)
print(str1 is str3)
print('**********')

t1 = (1, 2, 3)
t2 = (1, 2, 3)
t3 = t1
print(id(t1))
print(id(t2))
print(id(t3))
print(t1 is t2)
print(t1 is t3)
print('**********')

得到的结果: 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fhJ9BN3j-1584025809616)(https://img-blg.csdnimg.cn/20200312221427319.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNzU4OTU3NQ==,size_16,color_FFFFFF,t_70)]

 

  1. 整型,浮点型,字符串型行为一致:只要变量的类型和数值相同,他们 id 相同,是同一对象,指向内存同一地址。
  2. 元组行为有些差异:如果是直接用相同值赋值两个元组,他们的 id 不同,是不同对象,但是如果赋值一个元组,再用这个元组赋值另一个元组,则是同一对象,指向内存同一地址。

修改 

i = 1
print(id(i))
i = 2
print(id(i))
print('*********************')

f = 1.738
print(id(f))
f = 2.738
print(id(f))
print('*********************')

str = 'abc'
print(id(str))
str = 'xyz'
print(id(str))
print('*********************')

t = (1, 2, 3)
print(id(t))
t = (4, 5, 6)
print(id(t))
print('*********************')

得到的结果
在这里插入图片描述

可以看到四种数据类型行为一致:对不可变对象进行修改的时候,由于对象不可变,需要新建内存和对象,将修改的值赋值给新的对象,原对象不变,不过这种情况由于没有变量引用此对象,所以 python 的垃圾回收机制可能会回收原对象。
再看一种情况: 

i1 = 1
i2 = i1
print(id(i1))
print(id(i2))
i1 = 2
print(id(i1))
print(id(i2))
print('*************')

f1 = 1.7
f2 = f1
print(id(f1))
print(id(f2))
f1 = 2.9
print(id(f1))
print(id(f2))
print('*************')

s1 = 'abc'
s2 = s1
print(id(s1))
print(id(s2))
s1 = 'xyz'
print(id(s1))
print(id(s2))
print('*************')

t1 = (1, 2, 3)
t2 = t1
print(id(t1))
print(id(t2))
t1 = (4, 5, 6)
print(id(t1))
print(id(t2))
print('*************')

得到的结果如下:

在这里插入图片描述

以整型为例: 

i1 = 1
i2 = i1
print(id(i1))
print(id(i2)

这一段和赋值一样,然后对 i1 进行修改:

i1 = 2
print(id(i1))
print(id(i2))

 这个时候,由于是不可变对象,所以需要新建内存和对象并赋值 2,然后变量 i1 就是这个新对象的实例,但是 i2 没有任何变化。

可变对象

python 中的可变对象有列表 (list),集合 (set), 字典 (dict)

赋值

首先看一下列表,集合和字典 的赋值操作:

l1 = [1, 2, 3]
l2 = [1, 2, 3]
l3 = l1
print(id(l1))
print(id(l2))
print(id(l3))
print(l1 is l2)
print(l1 is l3)
print('**************')

s1 = {1, 2, 3}
s2 = {1, 2, 3}
s3 = s1
print(id(s1))
print(id(s2))
print(id(s3))
print(s1 is s2)
print(s1 is s3)
print('**************')

d1 = {'key1': 1, 'key2': 2}
d2 = {'key1': 1, 'key2': 2}
d3 = d1
print(id(d1))
print(id(d2))
print(id(d3))
print(d1 is d2)
print(d1 is d3)
print('**************')

 得到的结果:

 在这里插入图片描述

这里三种数据类型的行为和元组 (tuple) 是一致的,用相同的值直接赋值,所得到的两个变量 id 是不同的,因此不是同一对象,但是用复制的方法赋值,得到的就是同一对象。 

修改 

l = [1]
print(l)
print(id(l))
l.append(2)
print(l)
print(id(l))
print('*********')

s = {1}
print(s)
print(id(s))
s.add(2)
print(s)
print(id(s))
print('*********')

d = {'key1': 1}
print(d)
print(id(d))
d['key2'] = 2
print(d)
print(id(d))
print('*********')

 得到的结果:

在这里插入图片描述 

由于是可变对象,可以对对象进行修改,所以修改之后的对象指向的内存地址是不变的。(这是和可变对象的本质区别) 

 第二种情况:

l1 = [1]
l2 = l1
print(l1)
print(l2)
print(id(l1))
print(id(l2))
l1.append(2)
print(l1)
print(l2)
print(id(l1))
print(id(l2))
print('*************')

s1 = {1}
s2 = s1
print(s1)
print(s2)
print(id(s1))
print(id(s2))
s1.add(2)
print(s1)
print(s2)
print(id(s1))
print(id(s2))
print('*************')

d1 = {'key1': 1}
d2 = d1
print(d1)
print(d2)
print(id(d1))
print(id(d2))
d1['key2'] = 2
print(d1)
print(d2)
print(id(d1))
print(id(d2))
print('*************')

 得到的结果:

在这里插入图片描述 

显然和第一种情况是一样的。 

总结

可变对象和不可变对象的本质差异在于对象是否可以修改。如果可以修改,则是可变对象。如果两个变量指向同一可变对象,修改其中一个变量,会导致另一变量的改变。如果不可以修改,则是不可变对象。如果两个变量指向同一对象,修改其中一个可变变量,不会导致另一可变变量的改变。(因为会新建一个对象,原对象不变)

另外元组 tuple 有点特殊,按照本质确实应该是也就是属于不可变对象,但是在赋值的时候有一点差异,如果复制赋值和其他不可变对象一致,但是相同值赋值的行为和可变对象一致。
不过总而言之,按照修改行为,确实是不可变对象。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值