Python核心编程--学习笔记--4--Python对象

  现在开始学习Python语言的核心部分。首先了解什么是Python对象,然后讨论最常用的内建类型,接下来讨论标准类型运算符和内建函数,之后给出对标准类型的不同分类方式,最后提一提Python目前还不支持的类型(这对那些有其他高级语言经验的人会有所帮助)。

 

1 Python对象

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

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

  • 身份:对象的唯一标识,可以用内建函数id()来得到。它与该对象的内存地址相关,程序中极少会用到。
  • 类型:对象的类型决定了该对象可以保存什么类型的值,进行什么样的操作,以及遵循什么样的规则。可以用内建函数type()查看对象的类型。因为在Python中类型也是对象,所以type()返回的是对象而不是简单的字符串。
  • 值: 对象表示的数据项。 

  对象属性:最常用的是函数和方法,也有 数据属性(类、类实例、模块、复数、文件等对象有)。

2 标准类型

  也称为基本数据类型:

 1 数字(分为几个子类型,其中有三个是整型)
 2 整型
 3 布尔型
 4 长整型
 5 浮点型
 6 复数型
 7 字符串
 8 列表
 9 元组
10 字典

3 其他内建类型

3.1 类型对象和type类型对象

  由于对象的固有行为和特性,其类型不能简单的用字符串来表示,这些信息也不应该和数据放在一起,所以将类型定义成对象。

  内建函数type()可以查看对象的类型:

>>> type(42)
<type 'int'>    #这实质上是一个类型对象,它输出这行字串,表明42是int类型
>>> type(type(42))
<type 'type'>   #类型对象是type类型,它是所有Python类型的根和所有Python标准类的默认元类(metaclass)

3.2 None,Python的Null对象

  None类型只有一个值,就是None(类似C语言中void类型和NULL值)。None的布尔值为False。

  每个对象天生具有布尔True或False值,具有False值的对象有:

 1 None
 2 False (布尔类型)
 3 所有的值为零的数:
 4     0   (整型)
 5     0.0  (浮点型)
 6     0L   (长整型)
 7     0.0+0.0j (复数)
 8 "" (空字符串)
 9 [] (空列表)
10 () (空元组)
11 {} (空字典)
12 用户创建的类实例如果定义了nonzero(__nonzero__())或length(__len__())且值为0

  除此之外任何对象的布尔值都为True。

4 内部类型

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

4.1 代码对象

  代码对象是编译过的Python源代码片段,是可执行对象。通过调用内建函数compile()可以得到代码对象。代码对象可以被exec命令或eval()内建函数来执行。
  代码对象本身不包含任何执行环境信息,它是用户自定义函数的核心,在被执行时动态获得上下文。(事实上代码对象是函数的一个属性)一个函数除了有代码对象属性以外,还有一些其它函数必须的属性:函数名,文档字符串,默认参数,全局命名空间等。

4.2 帧对象  

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

4.3 跟踪记录对象  

  当异常发生时被创建,它包含针对异常的栈跟踪信息。如果一个异常有自己的处理程序,处理程序就可以访问这个跟踪记录对象。

4.4 切片对象

  当使用Python扩展的切片语法,或使用内建函数slice()时,就会创建切片对象。

  扩展的切片语法包括:

  • 多维切片:sequence[start1 : end1, start2 : end2]
  • 省略切片:sequence[..., start1 : end1] 
  • 步进切片:sequence[起始索引 : 结束索引 : 步进值]
>>> foostr = 'abcde'
>>> foostr[::-1]    #步进值为-1,逆序输出
'edcba'
>>> foostr[::-2]
'eca'
>>> foolist = [123, 'xba', 342.23, 'abc']
>>> foolist[::-1]
['abc', 342.23, 'xba', 123]

4.5 省略对象

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

4.6 XRange对象  

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

5 标准类型运算符

5.1 对象值的比较

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

>>> 2.46 <= 8.33     #数字按值比较
True 
>>> 5+4j >= 2-3j 
True 
>>> 'abc' > 'xyz'     #字符串按字符序列值比较
False                            
>>> [3, 'abc'] == ['abc', 3] 
False 
>>> [3, 'abc'] == [3, 'abc'] 
True

  多个比较操作可以在同一行上进行,求值顺序为从左到右。

>>> 4 > 3 == 3    #之前也提到过,等同于 4>3 and 3==3
True

5.2 对象身份比较

   即对象的内存地址比较:

>>> a=b=4.3    #一个值为4.3的数字对象被创建,这个对象的引用被赋值给变量a和b
>>> id(a) == id(b)
True
>>> a=4.3    #一个值为4.3的数字对象被创建,这个对象的引用被赋值给变量a
>>> b=a     #Pyhon是通过传递引用来处理对象的,所以b也指向a指向的对象
>>> id(a) == id(b)
True
>>> a=4.3    #分别创建了两个数字对象
>>> b=4.3
>>> id(a) == id(b)
False

  Python中的变量名只是一个符号,可以看成对象的一个链接,所以上面的比较,实质都是变量名指向的对象之间的比较。

  关键字 is和 not:

>>> a=[1,2,'abc']
>>> b=[2,1,'abc']
>>> a is b  #等同于id(a) == id(b),a指向的对象就是b指向的对象
False
>>> a is not b
True

  特例:对于简单的整数和字符串,Python会很高效的缓存它们,所以有时候该创建对象的时候却没有创建:

>>> a=12    #简单整数,缓存
>>> b=12
>>> a is b
True
>>> a='abc'  #简单字符串,缓存
>>> b='abc'
>>> a is b
True
>>> a='abcdefghijklmnopqrstuvwxyz,.;'    #复杂字符串,不缓存
>>> b='abcdefghijklmnopqrstuvwxyz,.;'
>>> a is b
False

5.3 逻辑运算符

  按照优先级,not > and > or

>>> not True and False      #not > and
False
>>> True or True and False  #and > or
True

6 标准类型内建函数

6.1 type()

type(object) #接受一个对象为参数,返回对象的类型。返回值是一个类型对象。
>>> type(4)     #int类型
<type 'int'> 
>>> type('Hello World!') #string类型 
<type 'string'> 
>>> type(type(4)) #type类型
<type 'type'>

  type()的输出用 <> 包裹,这表明它是一个对象。每个对象都可以实现一个可打印的字符串表示。对那些不容易显示的对象来说,Python以一个相对标准的格式表示这个对象:<object_something_or_another>,其中通常会提供对象类别、对象id或位置、 或者其它合适的信息。

>>> import sys
>>> sys
<module 'sys' (built-in)>    #内建,模块对象
>>> type(sys)
<type 'module'>

6.2 cmp()

cmp(obj1, obj2) #比较对象大小,如果obj1 < obj2,返回-1;obj1 == obj2,返回0;obj1 > obj2,返回1
>>> a, b = 2, -3
>>> cmp(a,b)
1
>>> cmp(b,a)
-1
>>> cmp('abc', 'abc')
0

  标准类型对象和用户自定义类对象都可以进行比较,对于用户自定义类对象,cmp()会调用该类的特殊方法__cmp__()。(在第13章会详细介绍类的特殊方法)

6.3 str()和repr(),及``运算符

str(obj)    repr(obj)    `obj`  #都是以字符串方式获取对象的内容、类型、数值属性等信息(最后一个符号是反引号,键盘上数字1左边的键)
>>> str(4.53-2j)       #str
'(4.53-2j)' 
>>> str(2e10) 
'20000000000.0' 
>>> repr([0, 5, 9, 9]) #repr
'[0, 5, 9, 9]' 
>>> `[0, 5, 9, 9]`     #反引号``
'[0, 5, 9, 9]'

  区别:str()的返回可读性好;repr()和反引号``的返回对Python比较友好,而且通常可以通过内建函数eval()重新得到该对象:

>>> a='abc\n'
>>> str(a)
'abc\n'
>>> repr(a)    #' '字符串被进一步包装成" ' ' ",字符串内的换行符也被取消转义
"'abc\\n'"
>>> `a`     #反引号等同于repr
"'abc\\n'"
>>> print str(a)    #输出换行符
abc

>>> print repr(a)
'abc\n'

  插一句:raw_input()函数,就是将输入的内容送进repr()再返回其字符串形式的。

  repr()和反引号``的关系,就类似于pow()和**都是求幂一样,有的地方适合函数调用,有的地方适合运算符。现在已经不鼓励使用反引号``。

6.4 type()和isinstance()

isinstance(object, class-or-type-or-tuple) #对象object是否是 类class/类型type/元组元素 的对象

  type()不仅仅可以返回标准类型,它可以返回任意python对象的类型:

>>> class Foo: pass
... 
>>> foo=Foo()
>>> class Bar(object): pass
... 
>>> bar=Bar()
>>>
>>> type(Foo) <type 'classobj'>  #类对象 >>> type(foo) <type 'instance'>  #类实例 >>> type(Bar) <type 'type'>     #类型 >>> type(bar) <class '__main__.Bar'>

  下面是一个改进的过程:判断一个对象是否属于某个类型:

if type(num) == type(0):  #判断num是否整型对象。缺点:两次函数调用
    ...
↓
import types
if type(num) == types.IntType: #比较对象值。缺点:Python中一切皆对象,对于type(8)、type(-100)、types.IntType都是同一个对象<type 'int'>
    ...
↓
if type(num) is types.IntType: #直接比较对象身份。缺点:要从模块types中查询IntType
    ...
↓
from types import IntType
if type(num) is IntType:    #减少查询次数
    ...
↓
isinstance(num, (int, str)) #同时查询多个

6.5 Python类型运算符和内建函数总结

  按照优先级从高到低:

7 工厂函数

  Python2.2统一了类型和类,所有的内建类型现在也都是类,在这基础之上,原来的所谓内建转换函数象int()、type()、list()等等,现在都成了工厂函数。

  工厂函数:看上去象函数,实质上是类。调用它们时,实际上生成了该类型的一个实例,就象工厂生产货物一样。

  一些老版本里的内建函数,现在的工厂函数:

1 int(), long(), float(), complex() 
2 str(), unicode(), basestring() 
3 list(), tuple() 
4 type() 

  新的工厂函数: 

1 dict() 
2 bool() 
3 set(), frozenset() 
4 object() 
5 classmethod() 
6 staticmethod() 
7 super() 
8 property() 
9 file()

8 标准类型的分类

  分类有助于了解某类型应有的行为,帮助程序使用恰当的类型。

8.1 存储模型  

  • 原子/标量存储:能保存单个字面对象的类型。 包括 数值类型、字符串(虽然它“包含”字符,但是Python中并没有字符类型,所以字符串是一个自包含的文字类型)
  • 容器存储:可容纳多个对象的类型,且Python容器对象可容纳不同类型的对象。 包括 列表、元组、字典。

8.2 更新模型

  • 可变类型:对象被创建后,它的值可以更新。 包括 列表、字典。(更改内容之后可通过查看id()返回值来辨认对象是否已改变)
  • 不可变类型:对象被创建后,它的值不可以改变。 包括 数字、字符串、元组。

8.3 访问模型

  • 直接访问:非容器类的都可以。 包括 数字。
  • 顺序访问:按照从0开始的索引顺序访问,一次可以访问一个或多个元素。包括 字符串、列表、元组。
  • 映射访问:通过无序存放的key访问,即哈希表。 包括 字典。

9 不支持的类型

  • char/byte:Python没有这种保存单一字符或8比特整数的类型,可以使用长度为1的字符串来表示。 
  • 指针:Python自己管理内存,因此没有必要访问指针。其实在Python中,一切都是指针,指向对象。 
  • int/short/long:Python的整数实现等同于C语言的长整数,但是表达范围更广。
  • float/double:Python的浮点类型实际上是C语言的double类型。浮点数总是不精确的,Python有一种十进制浮点数类型Decimal,需要导入decimal模块才可以使用,它拥有任意的精度。在处理金钱这类确定的值时,Decimal类型就很有用。在处理重量、长度或其它度量单位的场合,float足够用了。
posted @ 2013-11-26 23:02  阿杰的专栏  阅读(222)  评论(0编辑  收藏  举报