山地人

Python 面向对象编程

山地人
山地人
2021-07-19

什么是面向对象

Python是一种支持多范式的编程语言,啥是多范式说白了就是支持多种编程方式。Python既支持过程式编程,又支持面向对象编程。

和过程式编程的思考方式不同,过程式编程在解决一个问题时会先把问题分解成几个步骤,为每个步骤定义函数依次解决这些步骤,最后问题也就解决了。而面向对象编程在思考如何解决问题时,会先找出问题里涉及的几个对象,然后找出每个对象应该包含哪些数据和方法,通过调用不同对象的方法,最终解决问题。

面向对象的基本要素

面向对象编程里的最基本的元素就是对象。比如一个学生管理系统,如果用面向对象编程的方式去开发,里面有这些主要对象学生老师课程成绩班级等等。这些都是对象。

但是光有对象其实是不够的,比如学生这个对象,一个学校有几百到上万名学生,那么在这个学生管理系统里的每个学生都是一个学生对象,如果一个一个构建学生对象似乎有些麻烦。于是就被发明出来了。用一个学生类作为构建学生对象的模板。这样用学生类来创建学生对象就方便多了。这个类在大部分编程语言中通常使用class做为语言的关键词。Python也不例外。

对于每个学生,都会有一些基本的属性,比如:姓名、出生年月、身高、体重。另外学生也会有各种行为:学习、吃饭、睡觉、运动。于是在面向对象的编程思想中,把这些学生共有的基本属性抽取到学生类中成为类的属性,把学生的行为也放到了学生类中成为类的成员方法

class Student {
# 学生类的属性
name = ""
age = 0
# 实例初始化方法
def __init__(self, name, age):
self.name = name
self.age = age
def study(self):
print(r"{self.name}正在学习")
def eat(self):
print(r"{self.name}正在吃饭")
}

定义好上面的类,就可以创建对象了。这个过程叫实例化

zhang = Student("张三", 18)

上面的代码就是用Student实例化一个学生实例zhang。这里的括号内的"张三", 18会被传递到Student类中的def __init__(self, name, age):方法的参数部分,用于初始化。

之后就可以通过zhang.eat()调用成员方法了。

点击运行,查看类的运行情况。

面向对象的三大特征

对于任何一门完全支持面向对象的编程语言,都会支持面向对象的三大特性:封装、继承和多态。下面我们看看这三大特性都是什么意思。

封装性

面向对象编程通过封装,将数据和对数据的处理过程这些具体的细节都隐藏到了类内部。然后通过创建出的实例来对外进行交互。比如上面的zhang.sayHi()在内部就做了好几件事,首先读取自身的nameage属性,然后格式化,最后用print语句输出。这些琐碎的细节都被隐藏在类中。使用的时候只需要创建实例,调用实例方法。通过这种方式让外部使用变得简单。这也就是封装带来的好处和价值。另外封装让维护和扩展都变得容易。信息和具体的操作都被隔离在类内部,只要对外的接口,比如函数和函数参数不变化。内部的调整并不会影响外部的使用。有很好的隔离性和可维护性。

继承性

继承性是通过类之间的继承关系,让子类获得父类的属性和方法,并在此基础上进行扩展。那前面的学生类举例

我们可以让Student类去继承一个Person类。这样就可以把原来在学生类中的很大一部分属性和方法抽取到Person类中。这样学生类中只需要保留一些和Person类不同的属性和方法就可以了。

此时的Student被称为Person的子类。Person被称为Student父类或者叫基类

class Person:
name = ""
age = 1
def __init__(self, name, age):
self.name = name
self.age = age
def sayHi(self):
print(f"大家好,我是{self.name},今年{self.age}岁。")
def eat(self):
print(f"{self.name}在吃饭")

通过把更多通用属性搬移到父类后,子类就得到了简化,再看看现在的子类Student:

class Student(Person):
def __init__(self, name, age):
super().__init__(name, age)
def study(self):
print(f"{self.name}在学习。")

同样的功能,代码行数明显比之少了许多。另外要在创建其他和Person有关联的类时,也可以通过这种继承关系去创建,比如老师类Teacher。和Student类不同之处,Teacher类有一个teach教书的方法,这个学生类是没有的。这种特有的属性和方法留在了子类中实现。

class Teacher(Person):
def __init__(self, name, age):
super().__init__(name, age)
def teach(self):
print(f"{self.name}老师正在教书。")

多态性

有了继承的基础,多态性也可以建立起来了。原本父类中的方法,在子类中可以重新实现。这样不同的子类的实例在调用相同的父类方法时,就可以获得个性化的效果。

下面,我们还是围绕着老师和学生类来说多态问题。

前面的TeacherStudent类都有sayHi这个打招呼的方法。但是老师和学生打招呼的方式是一样的,有些无味。现在我们希望这两个类都能有一些更符合自己身份特征的个性化的打招呼方式,于是我们重新在子类中对sayHi方法进行定义。这种在子类中重新实现父类中方法的做法被称为重写 Overriding

class Teacher(Person):
...
def sayHi(self):
print(f"同学们你们好,我是{self.name}老师。")
class Student(Person):
...
def sayHi(self):
print(f"大家好,我是{self.name}。")

点击运行,看看老师和学生各自是怎么打招呼的。

总结

  • 面向对象编程是一种解决复杂问题的编程思想。
  • 通过将业务问题转换成一个个鲜活的对象,将数据和处理方法封装到类内部。让代码维护性和扩展性得到提高。
  • 继承,把重复的代码通过继承的方式让代码的复用性提高。
  • 多态,让继承后的代码在需要多样性的时候依然可以实现,同时让不同的对象可以使用同一的接口变得可能。

至此,本篇教程也到了该和你说再见的时候了,我们下期再见。

学完本篇互动教程,如果你觉得体验不错,可以把网页链接发送给你的小伙伴,让他/她也来感受一下。当然,你也可以继续看看网站上其他的的互动教程,希望`idev365`能够给你带来收获。

学习教程的过程中碰到了问题,或者对idev365有什么改进意见和想法,欢迎加入idev365微信内测群,和山地人交流你的想法。