1、面向对象的理解
考虑到部分读者可能没有接触过面向对象编程,所以先介绍下面向对象的一些特征,形成一个面向对象概念的基本认知,有助于后面具体的学习Python的面向对象编程。
① 对象引入
按照普通人的认知,对象就是我们日常生活中谈论到的男女对象。见过这样的问题:
“我没有对象是不是就没办法学习面向对象编程了?”。
答案肯定不是,编程界有这样一句名言,“万物皆对象”,意思:把任何事物都看做一个对象。
所有的事物都具有两个特点:「有什么」和「能做什么」,举个例子:
老鹰有翅膀,能够飞翔。在面向对象看来,「老鹰」就是一个「对象」,「翅膀」是「属性」,「用来描述对象」,而「能飞翔」是「方法」,这就是「对象的功能」。
② 类的引入
自然界除了老鹰外,还有很多有翅膀的动物,比如燕子,天鹅等。它们都具有上面两个相似的特点,我们可以把这种「具有相同或相似性质的对象」进行抽象(抽取共性)从而形成一个类,比如这里的鸟类,可以写出这样的伪代码:
鸟类{ 属性:翅膀 = (不同的颜色,不同的形状) 方法:飞翔(能否) }
然后有个名字叫「类的实例」,类的一个个具体实现,其实就是「对象」,比如这里实例化不同的鸟的伪代码:
老鹰 = 鸟类(翅膀 = 长而宽阔,飞翔(能)) 燕子 = 鸟类(翅膀 = 俊俏轻快,飞翔(能)) 鸭子 = 鸟类(翅膀 = 较短,飞翔(否))
③ 类设计的要求和思想
- 要求:高内聚,低耦合,从而提高对象的可复用性。
- 思想:以对象为中心,先开发类,得到对象,再通过对象间的相互通信实现功能。
2、类与对象
对类与对象的概念有个大概的认知后,我们来开始学习Python中类与对象相关的语法。
① 定义类和实例
Python中使用
class关键字
来定义类
,我们来定义一个鸟类:
class Bird: """ 鸟类 """ kind = '动物' name = "鸟" def __init__(self, name, wings): self.name = name self.wings = wings def can_fly(self, can): print("%s有 %s 的翅膀,%s飞翔" % (self.name, self.wings, '能' if can else '不能')) if __name__ == '__main__': eagle = Bird("老鹰", "长而宽阔") duck = Bird("鸭子", "较短") eagle.can_fly(True) duck.can_fly(False)
运行结果如下:
老鹰有 长而宽阔 的翅膀,能飞翔 鸭子有 较短 的翅膀,不能飞翔
② __init__初始化函数
在实例化对象的时候会自动调用,给该对象属性的值初始化,要注意: 不推荐使用
类名.__init__()
这种方式去调用初始化函数,以避免引起不必要的问题。
③ new构造函数
关于这个函数就涉及到
Python经典类与新式类
的概念了,在Python 2.x中,默认是经典类,除非显式的继承object类才是新式类。而在Python 3.x中默认所有类都是新式类,不用显式继承object类。
新式类相比经典类增加了很多的内置属性,比如可以通过
__class__
获得自身类型等,还有这里的__new__()
函数。而这个函数的调用时机在init__函数之前,作用是:可以调用其他类的构造方法或者直接返回别的对象来作为本类的实例。__new__(cls, *args,**kw)
,第一个参数表示要实例化的类,该参数在实例化的时候由Python解释器自动提供。另外要注意,__new()函数,必须要有返回值,如果该函数没有成功返回cls类型的对象,是不会调用__init__()
来对对象进行初始化!!!
初学者容易把这两个弄混,还是列出来帮助区分:
- __init__():用于初始化新实例,控制初始化过程,可添加一些属性,做些额外操作,发生在类实例被创建完后,它是对象级别的函数。
- __new__():用于控制生成新实例的过程,它是类级别的函数。
④ 类属性与实例属性
类属性是类的属性,当定义了一个类属性后,这个变量虽然归类所有,但是类和实例都可以访问到,类属性是类和实例的共有数据
。当类属性和实例属性同名时,访问顺序是:实例属性 -> 类属性
,如果两个都不存在则会报错。比如下面这样的代码:
print("类访问类变量:%s" % Bird.kind) print("类访问变类量:%s" % Bird.name) print("实例访问类变量:%s" % eagle.kind) print("实例访问同名变量:%s" % duck.name)
运行结果如下:
类访问类变量:动物 类访问变类量:鸟 实例访问类变量:动物 实例访问同名变量:鸭子
实例属性则是与实例绑定的属性,可以通过 实例名.属性名
的方式调用,代表了实例的数据部分。