百度T7架构师透析Python对象你需要知道这些

1. Python对象

Python使用对象模型来存储数据。构造任何类型的值都是一个对象。


所有的Python对象都拥有三个特性:身份,类型和值。

身份:

每一个对象都有一个唯一的身份标识自己,任何对象的身份可以使用内建函数 id() 来得到。这个值可以被认为是该对象的内存地址。您极少会用到这个值,也不用关心它究竟是什么。

类型:

对象的类型决定了该对象可以保存什么类型的值,可以进行什么样的操作,以及遵循什么样的规则。你可以用内建函数 type() 来查看Python对象的类型。因为在Python中类型也是对象,所以 type() 返回的是对象而不是简单的字符串。

值:

对象表示的数据项

上面三个特性在对象创建的时候就被赋值,除了值之外,其他两个特性都是只读的。

如果对象支持更新操作,那么它的值就可以改变,否则也是只读的。对象的值是否可更改被称为对象的可改变性(mutability),只要一个还没有被销毁,这些特性就一直存在。

Python有一系列的基本(内建)数据类型,绝大多数应用程序通常使用标准类型,对特定的数据存储则通过创建和实例化类来实现。

1.1 对象属性

某些Python对象有属性、值或相关联的可执行代码,比如方法。Python用点( . )标记法来访问属性。属性包括相应对象的名字等等。最常用的属性是函数和方法,不过有一些Python类型也有数据属性。含有数据属性的对象包括(但不仅限于):类、类实例、模块、复数和文件。

2. 标准类型

数字(分为几个子类型,其中有三个是整型)

整型

长整型

浮点型

复数型

布尔型

字符串

列表

元祖

字典

3. 其他内建类型

类型

Null对象(None)

文件

集合/固定集合

函数/方法

模块

3.1 类型对象和type类型对象

对象的一系列固有行为和特性(比如支持哪些运算,具 有哪些方法)必须事先定义好。从这个角度看,虽然看上去把类型本身也当成对象有点特别,但类型正是保存这些信息的最佳位置。描述一种 类型所需要的信息不可能用一个字符串来搞定,所以类型不能是一个简单的字符串,这些信息 不能也不应该和数据保存在一起, 所以我们将类型定义成对象。


>>> type(12)

<type 'int'>

>>> type(type(12))

<type 'type'>

没错,所有类型对象的类型都是 type。

3.2 None,Python的Null对象

Python有一个特殊的类型,被称作Null对象或者NoneType,它只有一个值,那就是None。他不支持任何运算也没有任何内建方法。

None没有什么有用的属性,它的布尔值总是False。

布尔值

所有的标准对象均可用于布尔测试,同类型的对象之间可以比较大小。每个对象天生具有布尔 True 或 False 值。空对象、值为零的任何数字或者Null 对象 None的布尔值都是False。

下列对象的布尔值是False。

None

False

所有值为零的数

空字符串

空列表

空元组

空字典


4. 内部类型 

代码

跟踪记录

切片

省略

Xrange

一般的程序员通常不会直接和这些对象打交道。

4.1 代码对象

代码对象是编译过的Python源代码片段,它是可执行对象。通过调用内建函数compile() 可以得到代码对象。代码对象可以被exec命令或eval() 内建函数来执行。

代码对象本身不包含任何执行环境信息,它是用户自定义函数的核心,在被执行时动态获得上下文。一个函数除了有代码对象属性以外,还有一些其他函数必须的属性,包括函数名,文档字符串,默认参数,及全局命名空间等等。

4.2 帧对象

帧对象表示Python的执行栈帧。帧对象包含Python解释器在运行时所需要知道的所有信息。它的属性包括指向上一帧的链接,正在被执行的代码对象,本地及全局名字空间字典以及当前指令等。每次函数调用产生一个新的帧,每一个帧对象都会相应创建一个C栈帧。用到帧对象的一个地方是跟踪记录对象。

4.3 跟踪记录对象

当你的代码出错时,Python就会引发一个异常。如果异常未被捕获和处理,解释器就会退出脚本运行,并显示诊断信息。当异常发生时,一个包含针对异常的栈跟踪信息的跟踪记录对象被创建。如果一个异常有自己的处理程序,处理程序就可以访问这个跟踪记录对象。

4.4 切片对象

当使用Python扩展的切片语法时,就会创建切片对象。扩展的切片语法允许对不同的索引切片操作,切片对象也可以由内建函数slice() 来生成。步进切片允许利用第三个切片元素进行步进切片,它的语法是sequence[起始索引 :结束索引:步进值]。

4.5 省略对象

省略对象用于扩展切片语法中,起记号作用。 这个对象在切片语法中表示省略号。类似Null 对象 None, 省略对象有一个唯一的名字 Ellipsis, 它的布尔值始终为 True。

4.6 XRange 对象

         调用内建函数 xrange() 会生成一个 Xrange 对象,xrange()是内建函数 range()的兄弟版本, 用于需要节省内存使用或 range()无法完成的超大数据集场合。


5. 标准类型运算符

5.1 对象值的比较

比较运算符用来判断同类型对象是否相等,所有的内建类型均支持比较运算,比较运算返 回布尔值 True 或 False。

<

>

<=

>=

==

!=

5.2 对象身份比较

作为对值比较的补充,Python 也支持对象本身的比较。对象可以被赋值到另一个变量(通 过引用)。因为每个变量都指向同一个(共享的)数据对象,只要任何一个引用发生改变,该对象的其它引用也会随之改变。

a is b

这个表达式等价于下面的表达式 id(a) == id(b)

>>> a = [ 5, 'hat', -9.3]
>>> b = a
>>> a is b
True
>>> a is not b
False
>>>
>>> b = 2.5e-5
>>> b
2.5e-005
>>> a
[5, 'hat', -9.3]
>>> a is b
False
>>> a is not b
True

在上面的例子中,使用的是浮点数而不是整数。为什么这样?整数对象和 字符串对象是不可变对象,所以Python会很高效的缓存它们。这会造成我们认为Python应该创建新对象时,它却没有创建新对象的假象。看下面的例子:

>>> a = 1
>>> id(a)
8402824
>>> b = 1
>>> id(b)
8402824
>>>
>>> c = 1.0
>>> id(c)
8651220
>>> d = 1.0
>>> id(d)
8651204

在上面的例子中,a 和 b 指向了相同的整数对象,但是 c 和 d 并没有指向相同的浮点数 对象。


Python仅缓存简单整数,因为它认为在Python应用程序中这些小整数会经常被用到。目前Python 缓存的整数范围是(-1,256),不过这个范围是会改变的。


5.3 布尔类型

布尔逻辑运算符 and, or 和 not 都是 Python 关键字,not 运算符拥有最高优先级,只比所有比较运算符低一级。 and 和 or 运 算符则相应的再低一级。


>>> x, y = 3.1415926536, -1024
>>> x < 5.0
True
>>> not (x < 5.0) 
False
>>> (x < 5.0) or (y > 2.718281828) 
True
>>> (x < 5.0) and (y > 2.718281828) 
False
>>> not (x is y)
True
6. 标准类型内建函数
6.1 type()
type() 接受一个对象做为参数,并返回它的类型。它的返回值是一个类型对象。
>>> type(4)     # int type
<type 'int'>
>>>
>>> type('Hello World!')
<type 'string'>
# string type
>>>
>>> type(type(4))       # type type
<type 'type'>

6.2 str() 和 repr() (及 `` 运算符)

内建函数 str() 和 repr() 或反引号运算符(``) 可以方便的以字符串的方式获取对象的 内容、类型、数值属性等信息。


>>> str(4.53-2j)
'(4.53-2j)'
>>>
>>> str(1)
'1'
>>>
>>> str(2e10)
'20000000000.0'
>>>
>>> str([0, 5, 9, 9])
'[0, 5, 9, 9]'
>>>
>>> repr([0, 5, 9, 9])
'[0, 5, 9, 9]'
>>>
>>> `[0, 5, 9, 9]`
'[0, 5, 9, 9]'

repr() 输出对 Python 比较友好, 而 str()的输出对人比较友好。虽然如此, 很多情况下这三者的输出仍然都是完全一样的。


6.3  type() 和 isinstance()

type()内建函数可以帮助你确认调用的就是你想要的函数或对象。除了内建函数 type(), 还有一个有用的内建函数叫 isinstance().利用它可以确认一 个对象的类型。


7. 类型工厂函数

原来的 所谓内建转换函数象 int(), type(), list() 等等, 现在都成了工厂函数。 也就是说虽然他 们看上去有点象函数, 实质上他们是类。当你调用它们时, 实际上是生成了该类型的一个实 例, 就象工厂生产货物一样。

dict()

bool()

set() ,frozenset()

object()

classmethod()

staticmethod()

super()

property()

file()

8. 标准类型的分类

如果让我们最啰嗦的描述标准类型,我们也许会称它们是 Python 的“基本内建数据对象原 始类型”。

“基本”,是指这些类型都是Python提供的标准或核心类型。

“内建”,是由于这些类型是Python默认就提供的

“数据”,因为他们用于一般数据存储

“对象”,因为对象是数据和功能的默认抽象

“原始”,因为这些类型提供的是最底层的粒度数据存储

“类型”,因为他们就是数据类型

8.1 存储模型                                                                        

以存储模型标准的类型分类

分类  Python 类型 标量/原子类型 数值(所有的数值类型),字符串(全部是文字) 容器类型 列表、元组、字典

8.2 更新模型

以更新模型为标准的类型分类

分类

Python 类型

可变类型

列表, 字典

不可变类型

数字、字符串、元组

>>> x = 'Python numbers and strings'
>>> print id(x)
16191392
>>> x = 'are immutable?!? What gives?'
>>> print id(x)
16191232
>>> i = 0
>>> print id(i)
7749552
>>> i = i + 1
>>> print id(i)

上面的例子中,事实上是一个新对象被创建,然后它取代了旧对象。

新创建的对象被关联到原来的变量名, 旧对象被丢弃,垃圾回收器会在适当的时机回收这 些对象。你可以通过内建函数 id()来确认对象的身份在两次赋值前后发生了变化。

>>> aList = ['ammonia', 83, 85, 'lady']
>>> aList
['ammonia', 83, 85, 'lady']
>>>
>>> aList[2]
85
>>>
>>> id(aList)
135443480
>>>
>>> aList[2] = aList[2] + 1
>>> aList[3] = 'stereo'
>>> aList
['ammonia', 83, 86, 'stereo']
>>>
>>> id(aList)
135443480
>>>
>>> aList.append('gaudy')
>>> aList.append(aList[2] + 1)
>>> aList
['ammonia', 83, 86, 'stereo', 'gaudy', 87]
>>>
>>> id(aList)
135443480

注意列表的值不论怎么改变, 列表的 ID 始终保持不变。

8.3 访问类型

以访问模型为标准的类型分类

分类

Python 类型

直接访问

数字

顺序访问

字符串、列表、元组

映射访问

字典


猜你喜欢

转载自blog.51cto.com/14014179/2300037