有的资料将这一章内容命名为“面向对象”,虽然没有错误,但这并不很 Pythonic ,因为 Python 中的函数是第一类对象,在前一章中已经开始“面向对象”了。其实不仅仅是第7章,本书从一开始,就在“面向对象”。那么,本章的类与对象有什么关系?为什么很多自学者会在学到本章的时候遇到困难?如何跨过这个难关?请读者满怀信心地认真学习本章和第9章,严格地执行各项学习建议。“漫卷诗书喜欲狂”的成功愉悦就在不远的将来。
在第2章2.4节曾初步了解过“对象”的概念,并且通过前面各章节的学习,读者已经对 Python 中的对象,比如内置对象和作为第一类对象的函数有了初步基本认识。从现在开始,将要在原有基础上,更深入地理解对象。
“对象”虽然是计算机科学中的专业术语,但不同的资料对其表述略有不同,例如《维基百科》中关于“对象”的词条内容是“对象(Object),台湾译作物件,是面向对象(Object Oriented)中的术语,既表示客观世界问题空间中的某个具体的事物,又表示软件系统解空间中的基本元素。”
计算机科学家 Grandy Booch(被业界尊为“面向对象”领域中的大师)所定义的“对象”包括以下要点:
将上述要点可以概括为:对象应该具有属性(即“状态”)、方法(即“行为”)和标识。Python 中对象的标识即在创建对象的时候自动在内存空间提供存储地址,所以,平时编写程序主要关注的是属性和方法。在第2章2.4节曾通俗地说明了 Python 语言对象的属性和方法的含义:
再来看“面向对象”是什么意思,这是现在编程的主流思潮。还是引用《维基百科》中词条内容:
面向对象程序设计(Object-oriented Programming,OOP)是一种程序设计范式,同时也是一种程序开发的方法。对象指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。
在此,对“面向对象”的理解姑且局限于这个表述。既然它是一种编程方法,就必须在编程实践中才能理解其真谛——实践出真知。所以,在后续的内容中,我们所学习和练习的,都是以“面向对象”为基本思想和方法——其实前面的学习和练习也如此,只是没有特别强调罢了。
编程语言中所说的“类”,其英文是“class”,“类”是中文翻译名称。对于初学者而言,听到这个名词会感觉怪怪的,因为不是很符合现代汉语的习惯。在汉语中,常说“鸟类”、“人类”等词语。当然,作为专门术语,不是不行,只是不太习惯罢了。诚然,在计算机科学中,类似的翻译还有不少,造成这种现象的原因很多,建议读者以“英汉结合”的方式来理解。
在目前流行的高级编程语言中,类是必须的。借用《维基百科》的定义:“在面向对象程序设计中,类(class)是一种面向对象计算机编程语言的构造,是创建对象的蓝图,描述了所创建的对象共同的属性和方法。”
据此定义,重点理解:
图8-1-1 类与蓝图的对比
“工厂中汽车的设计”绝对不是白纸一张,其中规定很多关于未来要造出来的“汽车对象”的“属性”和“方法”,比如车的颜色、车的性能等。如果抽象来看“类”,也是如此,要在类中规定好将来“造出来”的“实例们”所共有的属性和方法。
例如,把江湖上的一等一的大侠高手们的特点总结一下,发现他们有很多共同之处(以下皆为杜撰,若有雷同,纯属巧合,请勿对号入座):
假设达到这个标准——“蓝图”——就是大侠,那么在写小说的时候,给某个人物赋予上述各项内容——创建实例,就塑造出来了一位大侠。
为了让生产“大侠”的过程更“数学”化,需要在表述上精准,所以把上述大侠的各项特征写到“类”里面——设计“蓝图”。用类似 Python语言的代码可以这样写:
class 大侠:
性别 = 男
是否单身 = 否
中毒 = 百毒不侵
是否阴狠 = 否
九阴真经()
在这个名为“大侠”的类中,有属性——描述大侠的特征,即“是什么”,如:性别 = 男
。“性别”是属性,“男”是此属性的值。还有“方法”——描述大侠会什么功夫,即“做什么”,用形如“九阴真功()”的方式表示,类似前面学习过的函数,表示它可以被调用——功夫当然是要用来执行的。
接下来就可以用所定义的类“生产”大侠——不是文学作品中塑造大侠,而是用编程语言创建大侠“实例”。
laoqi = 大侠()
我们所使用的符号体系与上一章中函数雷同,大侠
也是名称——类的名称——后面紧跟一对圆括号 ()
,表示要执行这个名称所引用的对象,即“执行类”,可以形象地理解为让“工厂的生产线按照蓝图运行起来”,结果就应该是生产出产品了。于是由 大侠()
可得到“一个具体的大侠”——实例,并将该实例对象用变量 laoqi
引用,也可以简单说成实例 laoqi
。
如此,在程序中创建了一个符合“大侠类”中设计规范的“真实的大侠”实例——laoqi
。那么这个大侠的属性怎么访问?先想想以前学过的内置对象属性怎么访问?基本格式是“对象.属性”(注意中间的英文状态的符号),然后得到它的值。对实例 laoqi
也是如此,例如:
>>> laoqi.中毒 # (1)
百毒不侵
注释(1)表示请求属性“中毒”的值,所返回的“百毒不侵”即是类中规定的此属性的值。任何用这个类所创建的大侠,其“中毒”的属性默认值都是“百毒不侵”。
还可以使用大侠具有的武功:
>>> laoqi.九阴真经()
上述只是“伪装成”代码来演示。真正在 Python 中定义类,自有其严格规定。