Python回顾与整理2:Python对象

0.说明

        

        说对象是面向对象编程语言最重要的一部分一点也不为过,没有了“对象”,面向对象将无从谈起。Python也是如此,如果无法掌握对象,你很难有大的进步与提升。


1.Python对象

(1)对象特性

        Python使用对象模型来存储数据,构造任何类型的值都是一个对象,所有的Python对象都拥有下面的三个特性:

  • 身份:每个对象一唯一身份标识,可使用内建函数id()查看该值(可以认为这个值是该对象的内在地址)
  • 类型:对象的类型决定了对象(可以保存什么类型的值,进行什么样的操作,遵循什么样的规则),可以使用内建函数type()查看(对象的类型也是一个对象,因此type()返回的是一个对象,而不是字符串)
  • 值:对象表示的数据项

        对于身份特性,它是可读的;对于类型特性,新式类型和类可以修改,但不建议初学者这样做,另外Python有一系列的基本(内建)数据类型,可以自己定义(一般推荐通过创建和实例化类来对特定的数据进行存储);对于值,取决于该对象是否支持更新操作。

        

(2)对象属性

        Python使用句点标记法来访问属性,最常用的属性是函数和方法,当然一些Python对象也有数据属性。


2.标准类型

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

    Integer    整型

    Boolean    布尔型

    Long integer    长整型

    Floating point real number    浮点型

    Complex number    复数型

  • String    字符串
  • List            列表
  • Tuple         元组
  • Dictionary  字典

        需要注意的是,使用上面这些基本类型所构造的值都为该类型对应的对象。


3.其他内建类型

  • 类型
  • Null对象(None)
  • 文件
  • 集合/固定集合
  • 函数/方法
  • 模块
  • 下面主要说明Type和None类型,其它的后面会讨论。

(1)类型对象和type类型对象

        前面提到,对象有一系列行为和特性,而这些信息就是保存在对象的类型当中:


1

2

>>> type(42)

<type 'int'>

        type()返回的是一个类型对象,表明42是一个数字类型对象,而<type 'int'>本身也有所属于的类型,可以继续使用type()来查看:


1

2

>>> type(type(42))

<type 'type'>

        <type 'type'>表示<type 'int'>是一个type类型对象,尝试继续使用内建函数type()来作进一步操作:


1

2

>>> type(type(type(42)))

<type 'type'>

        得到的还是type类型对象,于是可以有下面的结论:

  • 所有类型对象的类型都是type,它也是所有Python类型的根和所有Python标准类的默认元类(metaclass)
  • 在Python中,类就是类型,实例是对应类型的对象(类比42的例子,42属于数字类型,它是数字类型构造值后的一个数字对象,或者说42是类int的一个实例对象,因为现在类型就是类)

(2)None:Python的Null对象

        Python有一个特殊的类型,被称为Null对象或者NoneType,它只有一个值,那就是None


1

2

3

>>> None

>>> type(None)

<type 'NoneType'>

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

(3)布尔值

        前面提及布尔值,有以下几点注意:

  • 每个对象天生具有布尔True或False值
  • 空对象 值为零的任何数字或者Null对象的布尔值都是False
  • 用户创建的类实例如果定义了nonzero(__nonzero__())或length(__len__())且值为0,那么它们的布尔值就是False

4.内部类型

  • 代码
  • 跟踪记录
  • 切片
  • 省略
  • Xrange

(1)代码对象

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

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

(2)帧对象

        帧对象表示Python的执行栈帧。帧对象包含Python解释器在运行时所需要知道的所有信息,它的属性包含下面这些信息:

  • 指向上一帧的链接
  • 正在被执行的代码对象
  • 本地及全局名称空间字典及当前指令等

        每次函数调用产生一个新的帧,每一个帧对象都会相应创建一个C栈帧,用到帧对象的一个地方是跟踪记录对象。

(3)跟踪记录对象

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

(4)切片对象

        当使用Python扩展的切片语法时,就会创建切片对象。

(5)省略对象

        省略对象用于扩展切片语法中,起记号作用。这个对象在切片语法中表示省略号。类似Null对象None,省略对象有一个唯一的名字Ellipsis:


1

2

3

4

>>> Ellipsis

Ellipsis

>>> type(Ellipsis)

<type 'ellipsis'>

        它的布尔值始终为True。

(6)Xrange对象

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


5.标准类型操作符

(1)对象值的比较

        比较操作符用来判断同类型对象的值是否相等,所有的内建类型(前面所说的标准类型和其他内建类型)均支持比较运算,比较运算结果返回布尔值True或False。

        注意:比较操作是针对对象的值进行的,就就是说比较的是对象的数值而不是对象本身。

        另外提及Python的一个特性,多个操作可以在同一行上进行,求值顺序为从左到右:


1

2

>>> 3 4 7

True

等价于:


1

2

>>> 3 4 and 4 7

True


(2)对象身份比较

        在Python中,应该将变量名看成是对象的一个链接,对对象的一个引用,它被指向这个对象,而不是直接赋值为该对象。可以使用内建函数id()或关键字is和is not来比较两个对象身份:

  • 相同值,指向相同对象

1

2

3

4

5

>>> foo1 = foo2 = 4.3

>>> a is b

True

>>> id(a) == id(b)

True

  • 值相同,指向不同对象

1

2

3

4

5

6

7

8

>>> foo1 = 4.3

>>> foo2 = 1.3 + 3.0

>>> foo1 is foo2

False

>>> id(foo1)

18024120

>>> id(foo2)

18024048

        在Python中,有一个'仅缓存简单整型'的概念,即对于一些简单的不可变对象,比如整型对象和字符串对象,Python会先将它们缓存到内存中,当需要就直接被引用,而无需创建,可以看下面的例子:


1

2

3

4

5

6

7

8

9

10

11

12

>>> a = 1

>>> id(a)

17953112

>>> b = 1

>>> id(b)

17953112

>>> c = 1.0

>>> id(c)

18024096

>>> d = 1.0

>>> id(d)

18024072

        当然,只是缓存简单整型:


1

2

3

4

5

6

>>> e = 336

>>> id(e)

18554008

>>> f = 336

>>> id(f)

18601504

        理解起来相对是比较简单的了。

(3)布尔类型

        按优先级从高到低,主要是:

  • not
  • and
  • or

6.标准类型内建函数

        即用于操作基本肉类的内建函数,如下:

  • cmp(obj1, obj2):大于返回负数,小于返回正数,等于返回0
  • repr(obj)或`obj`:返回一个对象的字符串表示
  • str(obj):返回对象适合可读性好的字符串表示
  • type(obj):得到一个对象的类型,并返回相应的类型对象(type对象,与type类型对象不同)

(1)type()

        接受一个对象作为参数,并返回它的类型,它的返回值是一个类型对象:


1

2

3

4

5

6

>>> type(4)

<type 'int'>

>>> type('Hello World!')

<type 'str'>

>>> type(type(4))

<type 'type'>

        以<>语法表示的,说明其是一个对象,每个对象都可以实现一个可打印的字符串表示。但对于那些不容易显示的对象来说,Python会以一个相对标准的格式来表示这个对象,如:<object_something_or_another>,其中提供了对象类别 对象id或位置等信息。

(2)cmp()

        例子如下:


1

2

3

4

5

6

7

8

9

10

>>> cmp(12)

-1

>>> cmp(21)

1

>>> cmp(22)

0

>>> cmp('abc''xyz')

-1

>>> cmp('abc''abc')

0

        比较是在对象之间进行的,不管是标准类型对象还是用户自定义对象,如果是用户自定义对象,cmp()会调用该类的特殊方法__cmp__()。

(3)str()和repr()(或``操作符)

        str()和repr()或``用来以字符串方式获取对象的内容 类型和数值等信息,作如下说明:

  • str()

    str()函数得到的字符串表示可读性比较好,适合用于print输出,大多数情况下都无法将该字符串表示通过eval()求值来得到原来的对象(当然,简单的就除外了)。


1

2

3

4

5

6

7

8

>>> str(1)

'1'

>>> eval(str(1))

1

>>> str([123])

'[1, 2, 3]'

>>> eval(str([123]))

[123]

  • repr()或``

    返回一个对象的“官方”字符串表示,也就是说大多数情况下,都可以将字符串通过eval()求值来得到原来的对象(当然,也有例外的情况)。


1

2

3

4

5

6

7

8

9

10

11

>>> repr([123])

'[1, 2, 3]'

>>> eval(repr([123]))

[123]

>>> eval(repr(type(42)))

Traceback (most recent call last):

  File "<stdin>", line 1in <module>

  File "<string>", line 1

    <type 'int'>

    ^

SyntaxError: invalid syntax

        总的来说,repr()输出对Python比较友好,而str()输出对用户比较友好。

(4)type()和isinstance()

  • type()

    type()用于返回一个对象的类型,它的返回值是一个类型对象,这些前面已经有所提及,再给出下面的例子:


1

2

3

4

5

6

7

8

>>> class Foo: pass

... 

>>> class foo(object): pass

... 

>>> type(Foo)

<type 'classobj'>

>>> type(foo)

<type 'type'>

        type(foo)的输出之所以会这样,是因为类就是类型。

  • isinstance()

    如果需要判断一个对象的类型,可以使用下面的方法:


1

2

3

>>> from types import IntType

>>> type(42== IntType

True

        当使用isinstance()时,就会方便很多:


1

2

3

4

5

>>> if isinstance(42, (float)):print 'OK'

... 

>>> if isinstance(42, (floatint)):print 'OK'

... 

OK

        isinstance()第一个参数为一个对象,第二个参数为一个类型对象或一个类型对象的元组(这样的话,就可以一次与多个类型对象作比较了,省去了多个if-else语句)。


7.类型工厂函数

        因为从Python2.2开始,类和类型就统一了,也就是说,所有的内建类型其实也都是类。而原来的转换函数int() type() list()等,现在都成了工厂函数,说是函数,实质上他们也是类,调用它们时,实际上就生成了该类型的一个实例,就像工厂生产货物一样(这就是工厂模式的概念,在做大型程序的开发时,该设计思想很经常会用到)。

        对于Python已给出的工厂函数(实质是类),可以查看书本P71,下面只给出作为示范:

  • int(), long(), float(), complex()
  • str(), unicode, basestring()
  • list(), tuple()
  • type()

8.标准类型的分类

        标准类型:基本内建数据对象原始类型,解释如下:

  • 基本:是因为这些类型都是Python提供的标准呀核心类型
  • 内建:是因为这些类型是Python默认就提供的
  • 数据:是因为他们用于一般数据存储
  • 对象:是因为对象是数据和功能的默认抽象
  • 原始:是因为这些类型提供的是最底层的粒度数据存储
  • 类型:是因为他们就是数据类型

        当然,我们可以对标准类型进行分类,以便于我们更好地理解这些标准类型的特性。

(1)存储模型

        分类标准:看这种类型的对象能保存多少个对象。于是会有下面两种情况:

  • 原子/标量存储:能保存单个字面对象的类型
  • 容器存储:可容纳多个对象的类型

        分类如下:

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

        其中对于容器对象(也就是列表等这些类型的一个实例对象了),它们都能容纳不同类型的对象。另外需要注意的是字符串,因为在Python中并没有“字符”类型的数据结构,所以字符串是一个自我包含的文字类型。

(2)更新模型

        分类标准:值是否可改变。于是会有下面两种情况:

  • 可变类型:对象的值可以被更新
  • 不可变类型:对象的值不可以被更改

        分类如下:

更新模型
分类 Python类型
可变类型 列表  字典
不可变类型 数字  字符串  元组

        数字或字符串是不可变类型,也许难以理解,但可以看下面的例子:


1

2

3

4

5

6

7

8

9

10

11

12

>>> a = 3

>>> id(a)

17953064

>>> a = 6

>>> id(a)

17952992

>>> x = 'abc'

>>> id(x)

140407360100672

>>> x = 'change'

>>> id(x)

140407359514784

        也就是说,表面上值是改变了,但实际上是3这个数字对象被丢弃回收,然后创建了一个新的数字对象6。而对于字符串类型,这也充分说明了在Python中是没有字符类型这一数据结构的。

        但对于可变类型,情况就不一样了:


1

2

3

4

5

6

>>> aList = [123]

>>> id(aList)

140407359478888

>>> aList.append('change')

>>> id(aList)

140407359478888

(3)访问模型

        分类标准:如何访问存储的数据。于是会有下面三种情况:

  • 直接存取:非容器类型可以直接访问(对于字符串,会有些特别,所以不会属于此类)
  • 顺序/序列:也就是可以通过使用切片(slice)的方式来进行访问
  • 映射:元素是无序存放的,但可以通过键值对的方式进行访问

        分类如下:

访问模型
分类 Python类型
直接访问 数字
顺序访问 字符串  列表  元组
映射访问 字典

        虽然字符串是非容器类型,但由于可以使用切片的方式对它进行访问,所以归类到顺序访问。

        将上面的三种分类模型和Python对应的数据结构进行总结,可如下:

标准类型分类
数据类型 存储模型 更新模型 访问模型
数字 标量 不可更改 直接访问
字符串 标量 不可更改 顺序访问
列表 容器 可更改 顺序访问
元组 容器 不可更改 顺序访问
字典 容器 可更改 映射访问

9.不支持的类型

(1)char

        在C语言中会有这种数据类型,但在Python中,则没有。

(2)指针

        Python的垃圾收集器会替我们管理这些工作,不用担心。

(3)int short long

        只需要知道,在Python中,直接使用整型就可以了,因为如果超出了范围,Python会为我们自动转换。

(4)float double

        Python的浮点类型实际是C语言的双精度浮点类型。如果需要更高的精度(处理与金钱相关的数据时),可以使用Python的十进制海战型类型Decimal,只需要导入decimal模块就可以使用。一般情况下,默认的float类型就足够用了。

        需要强调的是,对象的概念无论是在Python还是在其他的面向对象编程语言中,都是十分重要的,如果无法掌握对象,那么也就不能充分利用面向对象编程语言的特性。

时间: 2024-10-04 10:14:01

Python回顾与整理2:Python对象的相关文章

Python回顾与整理7:文件和输入输出

0.说明                  主要是下面的内容: 文件对象:内建函数.内建方法.属性 标准文件 文件系统:访问方法.文件执行 持久化存储 标准库中与文件有关的模块 1.文件对象         文件对象是用来访问文件的接口,而文件只是连续的字节序列,数据的传输经常会用到字节流,无论字节流是由单个字节还是大块数据组成. 2.文件内建函数(open()和file())         内建函数open()以及file()提供了初始化输入/输出(I/O)操作的通用接口,如果打开文件成功,

Python回顾与整理4:序列1—字符串

0.说明                  序列其实是Python的某几类数据类型的统称,如字符串,列表和元组,将它们统称为序列,是因为:它们的成员有序排列,并且可以通过下标偏移量访问到它的一个或者几个成员.         总结的思路为:先介绍适用于所有序列类型的操作符和内建函数,然后再分别对这几种序列类型进行介绍. 1.序列         序列类型都有相同的访问模式:它的每一个元素都可以通过指定一个偏移量的方式得到,多个元素通过切片操作的方式得到.而在Python序列中,偏移量的规则如下(

Python回顾与整理5:映像和集合类型

0.说明         依然是按照前面介绍的几种序列类型的思路来总结字映像类型和集合类型,即先做一个介绍,再讨论可用操作符.工厂函数.内建函数和方法. 1.映射类型:字典         映射类型被称做哈希表,而Python中的字典对象就是哈希类型,即它是按照这样的方式来存储数据:(哈希表的算法)是获取键,对键执行一个叫做哈希函数的操作,并根据计算的结果,选择在数据结构的某个地址中来存储对象的值.任何一个值存储的地址取决于它的键,正因为这种随意性,哈希表中的值是没有顺序的,所以Python中的

Python回顾与整理3:数字

0.说明               数字用的次数是否多主要是看需求,如果是做自动化运维平台开发,比如做一个自动监控的系统,那么你肯定需要收集一定量的数据,然后再对这些数据做一定的处理,那么这时候,你就一定需要用得上数字的.当然,我这里所说的要不要用数字,指的是,你是否需要对你的数据做一定的处理. 1.数字简介         数字是不可更改类型,也就是说变更数字的值会生成新的对象. (1)创建数值对象并用其赋值(数字对象) 1 2 >>>anInt = 1 >>>aC

Python回顾与整理4:序列2—列表与元组

1.列表         与字符串不同的是,列表不仅可以包含Python的标准类型,还可以包含不同类型的对象,包括用户自定义的对象.下面是一些列表的最基本的操作: 创建列表数据类型:由方括号([ ])定义,当然也可以用工厂方法list(iter)创建 访问列表的值:通过切片操作符([ ])和索引值或索引值范围访问 更新列表:可以在等号左边指定一个索引或者索引范围的方式来更新一个或几个元素,也可以用append()方法追加新元素到列表中 删除列表元素或列表本身:使用del L[index]的方法,

Python回顾与整理11:面向对象编程

0.说明         阅读一些优秀的Python源代码,会发现面向对象编程的思想无处不在,其实对于任何一门面向对象编程语言来说,面向对象编程都是极其重要的,因此,掌握好一门语言的面向对象编程,将有助于进行更高级的开发.(本文来自香飘叶子51cto博客<Python回顾与整理>系列博文专题) 1.引言 (1)类与实例 类         在Python中有新式类和经典类之分,无非就是有没有显式地继承一个父类: 1 2 3 4 5 6 7 # 新式类 class MyNewObjectType

Python回顾与整理1:Python基础

0.说明                  学习Python其实也有好一段时间了,之前也做了不少笔记,但是要真正把Python学得很扎实,没有对Python系统的了解是远远不够的,哪怕是最基础的知识点,所以决定好好地回顾整理.         当然,就以<Python核心编程>这本书为纲,希望可以把自己对Python的理解连成系统的一条线. 1.语句和语法 `#`:注释 `\`:换行,如果是闭合操作符如`( )`,`[ ]`,`{ }`等,可以不使用`\` `:`:分号将代码头和代码体分开 `

Python回顾与整理8:错误和异常

0.说明         如果想写出用户体验高的代码,那么就需要考虑到在执行自己写的这段代码中在和用户交互的过程中可能会出现的问题,也就是说,需要对可能出现的异常进行处理,只有做好这些工作,才能写出用户体验好的代码. 1.什么是异常 错误         错误是语法(导致解释器无法解释)或逻辑(也就是代码质量问题)上的,在Python中,当检测到错误时,解释器会指出当前流无法继续执行下去,于是就出现了异常. 异常         程序出现了错误而在正常控制流以外采取的行为.         根据

Python回顾与整理9:函数和函数式编程

0.说明         无论在什么编程语言中,函数都不可或缺,充分利用函数的特性,可以大大减少我们程序中的代码量. 1.什么是函数         所谓函数,英文名为function,其实就是表示为实现一定功能的一段代码,显然,如果需要多次实现某一功能时,使用函数就是把重复代码放入其中,既节省空间,又有助于保持一致性(主要是修改代码时). (1)函数vs过程         两者都是可以被调用的实体,过程是简单.没有返回值.特殊的函数.在Python中,过程就是函数,因为解释器会隐匿地返回默认