一 标准类型的分类
1 存储模型
分类 | Python类型 |
原子/标量类型 | 数值(所有的数值类型),字符串(全部是文字) |
容器类型 | 列表、元组、字典 |
一个能保存单个字面对象的类型,我们称它为原子类型或标量存储;可以容纳多个对象的类型,我们称之为容器存储。字符串看上去是一个容器类型,因为它“包含”字符,不过由于Python并没有字符类型,所以字符串是一个自我包含的文字类型。
2 更新模型
分类 | Python类型 |
可变类型 | 列表、字典 |
不可变类型 | 字符串、数值、元组 |
注意列表的值不论怎么改变,列表的ID始终不变。
3 访问模型
分类 | Python类型 |
直接访问 | 数值 |
顺序访问 | 元组、列表、字符串 |
映射访问 | 字典 |
对非容器类型都可以直接访问,所有数值类型都可以归到这一类。
序列类型指容器内的元素按从0开始的索引顺序访问,一次可以访问一个或多个元素。
映射类型类似序列的索引属性。不过它的索引并不使用顺序的数字偏移量取值,它的元素无序存放,通过唯一的键值来访问,这就是映射类型。
4 总结
数据类型 | 存储模型 | 更新模型 | 访问模型 |
数字 | 标量 | 不可更改 | 直接访问 |
字符串 | 标量 | 不可更改 | 顺序访问 |
列表 | 容器 | 可更改 | 顺序访问 |
元组 | 容器 | 不可更改 | 顺序访问 |
字典 | 容器 | 可更改 | 映射访问 |
二 序列类型操作符
1 成员关系操作符(in、not in)
对象 【not】in 序列
判断某一对象是否在序列中
2 连接操作符 +
obj = obj1 + obj2
将两个序列连接起来
3 重复操作符 *
obj = obj * 10
将obj重复10次
4 切片操作符 ([],[:],[::])
obj = obj1[] 取obj1所有元素
obj = obj2[num1:num2] 取num1到num2-1之间1的元素
obj = obj3[num1:num2:num3] 按num3间隔从num1到num2-1取值
三 浅谈拷贝Python对象、浅拷贝和深拷贝
先来看一段赋值语句
person = ['name',['saving',100.00]]
hubby = person[:]
wifey = list(person)
son = person
[id(x) for x in [person, son, hubby, wifey]
将person通过不同的方法赋值给另一个变量,看下输出结果。
可以看出除了直接使用=赋值,其它对象的内存地址均不和person相同。
我们试着修改下不同变量中的属性。
>>> hubby[0] = 'joe'
>>> wifey[0] = 'jane'
>>> son[0] = 'vae'
>>> hubby,wifey,son
看下输出结果:
在看下面一个修改。
>>> hubby[1][1] = 50.00
>>> hubby,wifey,son
看下输出结果:
发现son和wifey中的数值也变为50了,而修改名字时其它变量的名字确没有改变。
原因在于我们做了一个浅拷贝,建立一个浅拷贝实际是新建一个类型和原来一样,其内容是对原来对象元素的引用,拷贝对象是新的,但内容是对原来对象内容的引用。因为字符串是不可变对象,在列表中第一个对象是字符串,而第二个对象是一个一个列表属于可变对象。当进行浅拷贝时,字符串被显式的拷贝,并新建了一个字符串对象。我们来看下修改后的id值:
可以看到wifey和hubby第二个对象的id值是一样,也验证是浅拷贝结果。
我们来看下一个拷贝的例子。
>>> person = ['name',['saving',100.00]]
>>> hubby = person
>>> import copy
>>> wifey = copy.deepcopy(person)
>>> [id(x) for x in [person,hubby,wifey]]
[2522917446408, 2522917446408, 2522917429960]
>>> hubby[0] = 'joe'
>>> wifey[0] = 'jane'
>>> hubby,wifey
(['joe', ['saving', 100.0]], ['jane', ['saving', 100.0]])
>>> hubby[1][1]=50.00
>>> hubby,wifey
(['joe', ['saving', 50.0]], ['jane', ['saving', 100.0]])
这样就达到了我们的目的,修改一个对象中的数值而不影响其他对象中的元素。
我们来看各个id值。
>>> [id(x) for x in hubby]
[2522917473392, 2522917446920]
>>> [id(x) for x in wifey]
[2522917473224, 2522917446344]
这样我们看到各个对象的值都是不同的。有几项需要注意:
第一 非容器对象没有拷贝说。
第二 如果元组变量只包含原子类型对象,对它的深拷贝将不会进行。
针对第二条我们来看一个示例:
>>> person = ['name',('saving',100.00)]
>>> newperson = copy.deepcopy(person)
>>> [id(x) for x in person]
[2522883812240, 2522917424520]
>>> [id(x) for x in newperson]
[2522883812240, 2522917424520]
使用元组,我们看到四个对象的id值。
我们再看使用列表的结果:
>>> person = ['name',['saving',100.00]]
>>> import copy
>>> newperson = copy.deepcopy(person)
>>> [id(x) for x in person]
[2229511777168, 2229544151112]
>>> [id(x) for x in newperson]
[2229511777168, 2229544149704]
四 参考
《Python核心编程第二版》