dodo

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

python基础——重访类型分类

  • 对象根据分类来共享操作:例如,字符串、列表和元组都共享诸如合并、长度和索引等序列操作。
  • 只有可变对象(列表、字典和集合)可以原处修改;我们不能原处修改数字,字符串、元组。
  • 文件导出的方法,可变性并不真的适用于他们——当处理文件的时候,它们的状态可能会修改,但是,这与Python的核心类型可变性限制不完全相同。
  • “数字”包含了所有数字类型:整数、浮点数、复数、小数和分数。
  • 字符串包括str、以及bytes和Unicode;3.0+的bytearray字符串类型是可变的。
  • 集合类似于一个无值的字典的键,但是它们不能映射为值,并且没有顺序,因此,集合不是一个映射类型或一个序列类型,frozenset是集合的一个不可变的版本。
  • 除了类型分类操作,所有的类型都有可调用的方法,这些方法通常特定于他们的类型。

对象分类

对象类型 分类 是否可变
数字 数值
字符串 序列
列表 序列
字典 映射
元组 序列
文件 扩展 N/A
sets 集合
frozenset 集合
bytearray 序列

对象的灵活性

一般来说:

  • 列表、字典和元组可以包含任何种类的对象。
  • 裂变、字典和元组可以任意嵌套。
  • 列表和字典可以动态地扩大和缩小。

字典的值可以是列表,这一列表可能包含元组,而元组可能包含了字典。

如下为L = [‘abc’,[(1,2),([3],4)],5]嵌套的偏移值:

image

从语法上说,嵌套对象在内部被表示为对不同内存区域的引用(也就是指针),如下可知,不管是变量还是列表,都是引用内存中的值。

>>> 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

image

拷贝需要注意的是:无条件值得分片以及字典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

image

按类别组织的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', [...]]
posted on 2016-11-24 21:20  dodo‘s  阅读(846)  评论(0编辑  收藏  举报