第十四章 对象
在Python中,对象(object)是什么?我们先看前两个概念:
(1)列表——收集变量(也就是数据)
(2)函数——收集功能(也就是代码)
而我们今天学的对象,则将是将这种收集思想再进一步——收集列表和函数本身。
等等,收集了又怎样?我们可以不用了解那么深入,只需要知道Python是面向对象(object oriented)的编程语言,有很多对象可以帮我们实现很多功能,我们不用自己写出来,只要写个代码调用它就好了。
14.1 真实世界中的对象
在真实世界中,对象相当于一个东西,它有自己的属性(attribute)或特性(property),如大小、颜色等;也有动作,如捡球、抛球等。
14.2 Python中的对象
在Python中,一个对象的特征就是属性;动作则称为方法(method)。
如果在Python中定义一个“球”,我们可以给他建立如下定义:
什么是属性?
属性就是一些信息(数字、字符串等),其实也是变量的一种,只不过它包含在对象中。属性可以:
(1)显示:print ball.size
(2)赋值给自己:ball.color = 'green'
(3)赋值给其他变量:myColor = ball.color
(4)赋值给其他对象的属性:myBall.color = yourBall.color
什么是方法?
方法其实就是包含在对象中的函数。
14.3 对象=属性+方法
利用对象,可以将一个东西的属性和方法(也就是你知道的事情和希望可以做的事情)收集到一起。属性是信息,方法是动作。
14.4 这个点是什么
前面我们看到:
(1)object.attribute
(2)object.method()
这两种用法。中间的点,是Python使用对象属性和方法的一种记法,称为“点记法”。
14.5 创建对象
Python创建对象一共有两步:
(1)第一步是创建对象类(class),用来放入对象的描述或蓝图。
(2)第二部是创建对象的实例(instance)。
具体请看下面的例子:
初始化对象:__int__()方法
有时候,除了创建类和实例本身,我们还需要第三步——初始化(initializing)。
初始化可以使用一个特定的方法实现:
假如现在print myBall,得到的会是这样的结果:
要改变这个信息,需要用到一个__str__()方法,它是一个“类方法”:
改变类型:__str__()方法
就像init方法一样,str方法是Python创建类时自动包含的“魔法方法”,也叫特殊方法(special method)。
__str__()方法在这里的含义是,告诉Python打印一个对象时,具体要显示什么内容,默认会显示下面的内容:
(1)实例在哪里定义(默认为__main__)
(2)类名(Ball)
(3)存储实例的具体空间(这里是0x109577dd0)
下面的例子使用了__str__()改变了打印的对象:
什么是self
我们前面多次用到了“self”,如下面这个例子:
def bounce(self):
这个self是什么意思呢?我们先看Ball类创造的两个实例:
catersBall = Ball("red", "small", "down")
warrensBall = Ball("green", "medium", "up")
这样,我们调用其中一个实例时(以warrens为例),可以直接用warrensBall.bounce来实现:
(1)首先,bounce是一个方法;
(2)方法必须知道是哪个实例调用了它:是caters,还是warrens或其他?
(3)因此,前面的def bounce(self)方法中的self参数,就会告诉bounce方法,是warrens调用了这个方法。以上成为实例引用(instance reference)。
附:我花了好长时间也没弄明白这个self方法,另外这一章也感觉比之前难懂很多,那么就先放放,等上手了例题再回来补充吧~
14.6 一个示例类——HotDog
之前我们做过了热狗的排列组合练习,现在我们来给热狗们设置一些属性和方法,让这个程序更加智能些。
首先给热狗设置一些属性:
(1)cooked_level:代表热狗的生熟程度,0~3为生,5表示烤好,8以上已经烤焦了!
(2)cooked_string:描述热狗生熟程度的字符串。
(3)condiments:热狗上的配料列表,如番茄酱、芥末酱等。
然后是热狗的一些方法:
(1)cook():烤热狗。
(2)add_condiment():给热狗加上配料。
(3)__init__():创建实例并设置默认属性。
(4)__str__():让print的结果好看点。
下面是步骤:
(1)首先需要定义热狗这个类:使用__init__方法
(2)建立一个烤热狗的方法:cook(),其中的time是用来增加烤制级别的。
(3)创建热狗的一个实例,并检查它的属性。
(4)把以上内容都放到一个程序中,并运行:
(5)现在来测试cook方法:
(6)增加其他的功能:显示、加配料等
14.7 隐藏数据
如果限制对对象的数据访问,使得它只能通过方法来获取数据、修改数据,这就叫做数据隐藏(data hiding)。
14.8 多态和继承
接下来我们学习对象最重要的两个方面:多态(polymorphism)和继承(inheritance)。这两个词有点深奥,但正因为有这两方面,才让对象如此有用。
(1)多态——同一个方法,不同的行为
多态简单来说就是:同名的方法,在不同的类中,可以实现不同的行为。
例如,假设我们要建立一个程序做几何题,分别计算不同形状(如正方形和三角形)的面积,这时候我们可以建立两个类,然后按下面的来操作:
以上两个形状,都用了getArea的方法,但每个形状的方法做的工作不同,这就是多态的一个例子。
(2)继承——向父母学习
在真实的(非编程的)世界中,人们可以从他们的父母或其他家人处继承一些东西,如财物、身体特征等。而在面向对象编程中,类可以从其他类那里继承属性和方法,这样的类称为一个“家族”,“家族”中的每个类共享相同的属性和方法。这样一来,给“家族”新增成员的时候,新的类就不用从头开始写起。
从其他类继承属性或方法的类,我们成为派生类(derived class)或子类(subclass)。我们看一下下面的例子:
假如我们要建立一个游戏,玩家一路上可以捡起不同的东西,如食物、钱或衣服。我们建立一个类,叫GameObject。它有一些属性如name、coin、apple和hat等;它还有些方法,如pickUp()等。所有的游戏对象都有共同的方法和属性。
另外我们还有Coin这个子类,从GameObject派生。它需要继承GameObject的name属性和pickUp等方法,并需要一个value属性和一个spend()方法。
下面是这些类的代码:
14.9 未雨绸缪
上面的代码看似没有什么实质内容,但它有助于我们提前思考、组织想法,并给其他人解释我们要做什么。这种“未雨绸缪”的方法,我们也可以“空函数”或代码桩(code stub)实现。
要建立代码桩,可以使用pass关键字作为占位符,如:
你学到了什么
(1)什么是对象、属性和方法
(2)什么是类,以及如何创建类的实例
(3)特殊方法:__init__()和__str__()
(4)多态、继承和代码桩
练习题
记在前面,先区分一下类、对象和实例,感觉现在还没弄明白。书上说的是,“类”只是对象的定义或蓝图,从这个蓝图建立对象时得到的就是实例。这里放一个讨论的连接,下面是另一种比喻,日后继续加深印象~
(1)为BankAccount建立一个类定义。它的属性包括账户名(字符串)、账号(字符串或整数)和余额(浮点数),另外还需要有一些方法用来显示余额、存钱和取钱。
(2)建立一个可以挣利息的类,叫InterestAccount。它继承BankAccount的属性和方法,并且有一个对应的利息率的属性,另外还要有一个方法计算及更新余额(年利息)。
先回顾一下子类的建立方法:
class 子类名(父类名):
小结
这一章学的挺不痛快,原因一是没之前那么简单,涉及到类、对象和实例的关系比较抽象,不能一下子明白;第二是不太自信,碰到比较难、比较陌生的题,会畏惧、会害怕。
这一章也是目前我参考网上其他学习笔记最多的一章,总的来说付出跟收获是成比例的,继续加油吧~