4.1轻松看对象
1.面向对象语言的来历
要想了解面向对象,就要先来了解类(Class)和对象(Object)。类和对象同样提高了程序的可复用性。除此之外,类和对象这两种语法结构还加强了程序模拟真实世界的能力。“模拟”,正是面向对象编程的核心。
面向对象范式可以追溯到Simula语言。(此段都是历史)
Python允许程序员以纯粹的面向过程的方式来使用它,所以人们有时会忽视它那颗面向对象的心。Python的一条哲学理念是“一切皆对象”。无论是我们第3章看到的面向过程范式,还是未来会看到的函数式编程,其实都是特殊的对象模拟岀的效果。
2.类
日常生活中, 我们把相近的东西归为一类,而且给这个类起一个名字。比如说,鸟类的共同属性是有羽毛,通过产卵生育后代。任何一只特别的鸟都是建立在鸟类的原型基础上的。在这里,我们用关键字class来定义一个类,其名字是Bird,括号里有一个关键词object,也就是“东西”的意思,即某一个个体。在计算机语言中,个体称为对象。 一个类别下,可以有多个个体。
class Bird(object): feather=True reproduction="egg"
冒号和缩进说明了属于这个类的代码。在隶属于这个类别的程序块中定义了两个量,一个用于说明鸟类有羽毛(father),另一个用于说明鸟类的繁殖方式(reproduction),这两个量称为类的属性(attribute)。
除了用数据性的属性来分辨类别外,有时也会根据这类东西能做什么事情来区分。比如说,鸟会移动。这样,鸟就和房屋的类别就区分开了。这些动作会带来一定的结果,比如移动导致位置的变化。这样的一些"行为”属性称为方法(method)。Python中,一般通过在类的内部定义函数来说明方法。
class Bird(object): feather=True reproduction="egg" def chirp(self,sound): print(sound)
给鸟类新增一个方法属性,就是表示鸟叫的方法chirp()方法 chirp()看起来很像一个函数。它的第一个参数是self,是为了在方法内部引用对象自身。无论该参数是否用到,方法的第一个参数必须是用于指代对象自身的self。剩下的参数 sound代表了鸟叫的内容。方法chirp() 会把sound打印出来。
3 .对象
通过调用类可以创造出这个类下面的一个对象——小鸡,叫summer。 它是个对象,且属于鸟类。使用前面已经定义好的鸟类,产生这个对象:
summer = Bird()
通过这一句创建对象,并说明summer是属于鸟类的一个对象。就可以使用鸟类中已经写好的代码了。
作为对象的summer将拥有鸟类的属性和方法。对属性的引用是通过对象.属性(object.attribute)的形式实现的。比如说:
print(summer.reproduction)
用上面的方式得到summer所属类的繁殖方式。
此外还可以调用方法,让summer执行鸟类允许的动作。比如:
summer.chirp("jijiji")
尽管在定义类的方法时必须加上这个self参数,但self只用能在类定义的内部,所以在调用方法时不需要对self传入数据。通过调用chirp()方法,summer就可以叫了。
到现在为止,描述对象的数据都存储于类的属性中。
对于一个类下的全部个体来说,某些属性可能存在个体差异。比如summer是黄色的,但并非所有的鸟儿都是黄色的。
因此,为了完整描述个体,除了共性的类属性外还需要用说明个性的对象属性。在类中,我们可以通过self来操作对象的属性。
拓展Bird类:
class Bird(object): def chirp(self,sound): print(sound) def set_color(self,color): self.color = color summer = Bird() summer.set_color("yellow") print (summer.color)
在方法set_color()中,通过self参数设定了对象的属性color。和类属性一样,通过对象•属性的方式来操作对象属性。由于对象属性依赖于self,所以必须在某个方法内部才能操作类属性。因此,对象属性没办法像类属性一样,在类下方直接赋初值。
但Python还是提供了初始化对象属性的办法。Python定义了一系列特殊方法,又被称为魔法方法(Magic Method)。特殊方法前后有两个下画线,比如__init__()、__add__()、__dict__() 等。程序员可以在类定义中设定特殊方法。Python会以特定的方式来处理各个特殊方法。对于类的__init__()方法,Python会在每次创建对象时自动调用。因此,我们可以在__init__()方法内部来初始化对象属性:
class Bird(object): def __init__(self,sound): self.sound = sound print("my sound is:", sound) def chirp(self): print(self.sound) summer = Bird("ji") summer.chirp()
在上面的类定义中,通过__init__()方法说明了这个类的初始化方式。每当对象建立时,比如创建summer对象时,__init__()方法就会被调用。它会设定sound这个对象属性。在后面的chirp()方法中,就可以通过self调用这一对象属性。除了设定对象属性外还可以在__init__() 中加入其他指令。这些指令会在创建对象时执行。
在调用类时,类的面可以跟一个参数列表。这里放入的数据将传给__init__()的参数。通过 __init__()方法可以在创建对象时就初始化对象属性。
除了操作对象属性外,self参数还能在一个方法内部调用同一类的其他方法,比如:
class Bird(object): def chirp(self,sound): print(sound) def chirp_repeat(self,sound,n): for i in range(n): self.chirp(sound) summer = Bird() summer.chirp_repeat('ji',10)
在方法chirp_repeat()中,通过self调用了类中的另一个方法 chirp() 。