python基础——重访类型分类
- 对象根据分类来共享操作:例如,字符串、列表和元组都共享诸如合并、长度和索引等序列操作。
- 只有可变对象(列表、字典和集合)可以原处修改;我们不能原处修改数字,字符串、元组。
- 文件导出的方法,可变性并不真的适用于他们——当处理文件的时候,它们的状态可能会修改,但是,这与Python的核心类型可变性限制不完全相同。
- “数字”包含了所有数字类型:整数、浮点数、复数、小数和分数。
- 字符串包括str、以及bytes和Unicode;3.0+的bytearray字符串类型是可变的。
- 集合类似于一个无值的字典的键,但是它们不能映射为值,并且没有顺序,因此,集合不是一个映射类型或一个序列类型,frozenset是集合的一个不可变的版本。
- 除了类型分类操作,所有的类型都有可调用的方法,这些方法通常特定于他们的类型。
对象分类
对象类型 | 分类 | 是否可变 |
数字 | 数值 | 否 |
字符串 | 序列 | 否 |
列表 | 序列 | 是 |
字典 | 映射 | 是 |
元组 | 序列 | 否 |
文件 | 扩展 | N/A |
sets | 集合 | 是 |
frozenset | 集合 | 否 |
bytearray | 序列 | 是 |
对象的灵活性
一般来说:
- 列表、字典和元组可以包含任何种类的对象。
- 裂变、字典和元组可以任意嵌套。
- 列表和字典可以动态地扩大和缩小。
字典的值可以是列表,这一列表可能包含元组,而元组可能包含了字典。
如下为L = [‘abc’,[(1,2),([3],4)],5]嵌套的偏移值:
从语法上说,嵌套对象在内部被表示为对不同内存区域的引用(也就是指针),如下可知,不管是变量还是列表,都是引用内存中的值。
>>> a = 1 >>> b = 2 >>> c = 3 >>> d = 4 >>> e = 5 >>> L = ['abc',[(1,2),([3],4)],5] >>> id(1) 2008373520 >>> id(a) 2008373520 >>> id(L[1][0][0]) 2008373520 >>> id(2) 2008373536 >>> id(b) 2008373536 >>> id(L[1][0][1]) 2008373536 >>> id(3) 2008373552 >>> id(c) 2008373552 >>> id(L[1][1][0][0]) 2008373552 >>> id(4) 2008373568 >>> id(L[1][1][1]) 2008373568 >>> id(d) 2008373568 >>> id(5) 2008373584 >>> id(e) 2008373584 >>> id(L[2]) 2008373584
拷贝需要注意的是:无条件值得分片以及字典copy方法只能做顶层赋值。也就是说,不能够赋值嵌套的数据结构(如果有的话)。如果需要一个深层嵌套的数据结构的完整的、完全独立的拷贝,那么就要使用标准的copy模块——包括import copy语句,并编辑 x = copy.deepcopy(y)对任意嵌套对象y做完整的复制。这一语句能够递归地遍历对象来复制他们所有的组成部分。然而这时相当罕见的情况(这也是为什么这么做比较费劲的原因所在)。
比较、相等性和真值
所有的Python对象也可以支持比较操作——测试相等性、相对大小等。Python的比较总是检查复合对象的所有部分,直到可以得出结果为止。事实上,当嵌套对象存在时,Python能够自动遍历数据结构,并从左到右递归应用比较,要多深就走多深。过程中首次发现的差值将决定比较的结果。
>>> L1 = [1,('a',3)] >>> L2 = [1,('a',3)] >>> L1 == L2,L1 is L2 (True, False) >>> id(L1),id(L2) (5788816, 7391072)
- “==”操作符测试值得相等性。Python运行相等测试,递归比较所有内嵌对象。
- “is”表达式测试对象的一致性。Python测试二者是否是同一个对象(也就是说同一内存地址中)。
>>> s1 = 'spam' >>> s2 = 'spam' >>> s1 == s2,s1 is s2 (True, True) >>> id(s1),id(s2) (5800128, 5800128)
由于字符串不可变的,对象缓存机制和程序代码无关——无论有多少变量与它们有关,字符串是无法在原处修改的。
一般来说,python中不同的类型的比较方法如下:
- 数字通过相对大小进行比较
- 字符串是按照ASCII字典顺序,一个字符接一个字符地对比进行比较(‘abc’<’ac’)
- 列表和元组从左到右对每部分的内容进行比较。
- 字典通过排序之后的(键、值)列表进行比较。字典的相对大小比较在3.0+不支持。
- 数字混合类型比较(例如:1<’spam’)在python3.0+是错误的。
字典在3.0+的比较
>>> d1 = {'a':1,'b':2} >>> d2 = {'a':1,'b':3} >>> d1 == d2 False >>> d1 < d2 #直接比较将会报错 TypeError: unorderable types: dict() < dict() >>> list(d1.items()) [('b', 2), ('a', 1)] >>> sorted(d1.items()) [('a', 1), ('b', 2)] >>> sorted(d1.items()) < sorted(d2.items()) True >>> sorted(d1.items()) > sorted(d2.items()) False >>> d3 = d1 >>> d3 == d1,d3 is d1 (True, True) >>> d4 = d1.copy() #浅copy >>> d4 == d1,d4 is d1 (True, False)
python中真和假的含义
在Python中,与大多数程序设计语言一样,整数0代表假,整数1代表真。除此之外,python也把任意的空数据结构视为假,把任何非空数据结构视为真。更一般地,真和假的概念是python中每个对象的固有属性,每个对象不是真就是假。
- 数字如果非零,则为真。
- 其他对象如果非空,则为真。
- Python特殊对象None,总被认为是假。(同C语言的NULL指针类似)
对象真值的例子
对象 | 值 |
‘spam’ | True |
“” | False |
[] | False |
{} | False |
1 | True |
0.0 | False |
None | False |
>>> L = [None] * 100
>>> L
[None, None, None, None, None,...]
记住,None不是意味着“未定义”。也就是说None是某些内容,而不是没有内容——它是一个真正的对象,并且由一块内存,由python给定一个内置的名称。
bool类型
python的布尔类型bool只不过是扩展了Python中真、假的概念。
- 当明确地用在真值测试时,True和False这些文字就变成了1和0,但他们使得程序员的意图更明确。
- 交互模式下运行的布尔测试的结果打印成True和False的字样,而不是1和0,以使得程序的结果更明确。
像if这样逻辑语句中,没必要只用布尔类型。所有的对象本质上依然是真或假,即使使用其他类型,所有的布尔概念依然是可用的。python提供了一个内置函数bool,它可以用来测试一个对象的布尔值(它是否为True,也就是说非零或非空):
>>> bool(1) True >>> bool('spam') True >>> bool({}) False
Type对象
事实上,即使是类型本身在Python中也是对象类型。
严格地说,对内置函数type(x)能够返回对象x的类型对象。类型对象可以用if语句来进行手动类型比较。有关类型的名称:dict、list、str、tuple、int、float、complex、byte、type、set和file(在2.0+中file也是类型名称,是open的同义词,但在3.0+中并非如此)。
#测试类型 >>> type([1]) == type([]) True >>> type([1]) == list True >>> isinstance([1],list) True >>> import types >>> def f():pass ... >>> type(f) == types.FunctionType True
按类别组织的Python的主要内置对象类型,Python中所有的一切都是某种类型的对象,即便是某个对象的类型。任何对象的类型都是类型为“type”的对象。3.0+中,一个类实例的类型就是该实例产生自哪个类。
Python中的其他类型
赋值生成引用,而不是拷贝
>>> L = [1,2,3] >>> M = ['x',L,'y'] >>> M ['x', [1, 2, 3], 'y'] >>> L[1] = 0 >>> M ['x', [1, 0, 3], 'y'] >>> M = ['x',L[:],'y'] #拷贝后 >>> M ['x', [1, 2, 3], 'y'] >>> L[1] = 0 >>> L [1, 0, 3] >>> M ['x', [1, 2, 3], 'y']
重复能够增加层次深度
序列重复就好像是多次将一个序列加到自己身上,多次重复实际上是多次引用。
>>> L = [4,5,6] >>> X = L * 4 >>> Y = [L] * 4 >>> X [4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6] >>> Y [[4, 5, 6], [4, 5, 6], [4, 5, 6], [4, 5, 6]] >>> L[1] = 0 >>> X [4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6] >>> Y [[4, 0, 6], [4, 0, 6], [4, 0, 6], [4, 0, 6]]
留意循环数据结构
如果遇到一个复合对象包含指向自身的引用,称之为循环对象。无论何时Python在对象中检测到循环,都会打印成[…]循环之处,而不会陷入无限循环
>>> L = ['grail'] >>> L.append(L) >>> L ['grail', [...]]
作者:dodo 出处:http://www.cnblogs.com/dodoye/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。