本章的主题是“更加抽象”,主要介绍如何创建自定义对象。创建自己的对象(类或者类型)是Python的核心概念。本章还要介绍多态、封装、方法、特性、超类以及继承的概念。
观点
- 对象基本上可以看做数据(特性)以及一系列可以存取、操作这些数据的方法所组成的集合。
对象的优点
包括多态、封装、继承在内的特性。
多态
意味着可以对不同类的对象使用同样的操作。就算不知道变量所引用的对象类型是什么,还是能对它进行操作。
关键点在于不需要监测类型,只需要知道x有个count的方法,带有一个字符串作为参数,并且返回整数值就够了。如果其他人创建了的对象类也有count方法,那也无所谓——你只需要像用字符串和列表一样使用该对象就可以了。
唯一能毁掉多态的就是使用函数显示的检查类型,比如type,isinstance以及issubclass函数。
封装
对外部世界隐藏对象的工作细节。是对全局作用域中其他区域隐藏多余信息的原则。帮助处理程序组件而不用过多关心多余细节。
继承
以普通的类为基础建立专门的类对象。其他的描述都略过了。
类和类型
来看一下什么是类,以及它和类型又有什么不同
类到底是什么
这部分略过了
创建自己的类
这部分略过了
私有属性
可以在属性名字前面加上双下划线即可让类的属性变为私有。使用下面的代码:
>>> class Secretive:
... def __inaccessible(self):
... print "Bet you can't see me"
...
>>> s = Secretive()
>>> s.__inaccessible()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Secretive instance has no attribute '__inaccessible'
类的命名空间
所有位于class语句中的代码都在特殊的命名空间中执行——类命名空间。这个命名空间可由类内所有成员访问。并不是所有Python程序员都知道类的定义其实就是执行代码块。比如在类的定义区并不只限使用def语句。使用下面的代码:
>>> class C:
... print 'Class C being defined...'
...
Class C being defined...
类作用域内的变量也可以被所有实例访问。
多重继承
Python支持多重继承。如果多个超类中有相同名字的方法,先继承的类中的方法会重写后继承的类中的方法。
接口和内省
Python中不需要显式的执行对象必须包含哪些方法才能作为参数接收。可以在使用对象的时候假定它可以实现你所要求的行为。如果它不能实现的话,程序就会失败。
可以使用hasattr()函数来判定一个对象是否具有一个属性。然后可以使用callable()来判定是否可以调用。可以参考下面的示例代码:
>>> callable(getattr(tc,'talk',None))
True
在Python3中则可以使用hasattr(x,’call‘)来替代callable(x)。
一些关于面向对象设计的思考
给出一些面向对象设计的要点。
- 将属于一类的对象放在一起。如果一个函数操纵一个全局变量,那么两者最好都在类内作为特性和方法出现。
- 不要让对象过于亲密。方法应该只关心自己实例的特性。让其他实例管理自己的状态。
- 要小心继承,尤其是多重继承。
- 简单就好。让你的方法小巧。一般来说,多数方法都应能在30秒内被读完(以及理解),尽量将代码行数控制在一页或者一屏以内。
可以用下面的方法考虑需要什么类以及类需要有什么方法。
- 写下问题的描述(程序要做什么?),把所有名词、动词和形容词加下划线。
- 对于所有名词,用作可能的类。
- 对于所有动词,用作可能的方法。
- 对于所有形容词,用作可能的特性。
- 把所有方法和特性分配到类。