深度学习:卷积神经网络技术与实践
上QQ阅读APP看书,第一时间看更新

2.8 面向对象编程

面向对象编程是最有效的软件编写方法之一。在面向对象编程中,首先编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。在编写类时,往往要定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。

根据类来创建对象被称为实例化,实例化是面向对象编程不可或缺的一部分。在本节中,将会编写一些类并创建其实例。理解面向对象编程有助于我们像程序员那样看世界,还可以帮助我们真正明白自己编写的代码。了解类背后的概念可培养逻辑思维,让我们能够通过编写程序来解决遇到的几乎任何问题。

2.8.1 类与对象

类是一种广义的数据,这种数据类型的元素既包含数据,也包含操作数据的函数。

1.类的创建

在Python中,我们通过class关键字来创建类。类的格式一般如下:


class 类名:
      类体

类一般由类头和类体两部分组成。类头由关键字class开头,后面紧跟着类名,类体包括所有细节,向右缩进对齐。

下面来编写一个表示小狗的简单类Dog。它表示的不是特定的小狗,而是任何小狗。对于小狗来说,它们都有名字和年龄;我们还知道,大多数小狗还会蹲下和打滚。由于大多数小狗都具备上述两项信息和两种行为,Dog类将包含它们。编写这个类后,我们将使用它来创建表示特定小狗的实例。

【例2-18】Dog类创建。


class Dog():
      def __init__(self, name, age):            # 初始化Dog类
          self.name = name
          self.age = age
      def sit(self):                            # 定义类方法
          print(self.name.title() + " is now sitting.")
      def roll_over(self):                      # 定义类方法
          print(self.name.title() + " rolled over!")

根据Dog类创建的每个实例都将存储狗的名字和年龄。我们赋予了每条小狗蹲下sit()和打滚roll_over()的能力。

类中的函数称为方法,之前或今后学过的方法都适用于它。__init__()是一个特殊的方法,每当根据Dog类创建新实例时,Python都会自动运行它。

2.类的使用(实例化)

我们可将类视为有关如何创建实例的说明。例如:Dog类是一系列说明,让Python知道如何创建表示特定小狗的实例。下面我们根据Dog类创建一个实例。

紧接着例2-18,建立Dog类的实例化。


my_dog = Dog('wangcai', 6)
print("My dog's name is " + my_dog.name.title())
print("My dog is " + str(my_dog.age) + " years old.")

程序运行结果如图2-26所示。

图2-26 Dog类实例化显示结果

3.属性和方法的访问

要访问实例的属性和方法,可使用句点表示法。例如:


my_dog.name
my_dog.age

这两句代码可以访问Dog类中定义的name和age属性。

根据Dog类创建实例后,就可以使用句点表示法来调用Dog类中定义的任何方法。例如:


my_dog = Dog('wangcai', 6)
my_dog.sit()
my_dog.roll_over()

后两句代码可以访问Dog类中定义的sit和roll_over方法。

2.8.2 继承与多态

继承与多态是类的特点之一。我们在前一节简单介绍了类的创建和简单使用,下面继续介绍类的继承与多态。

1.继承

如果我们要编写的类是另一个现成类的特殊版本,可使用继承的方法。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法。原有的类称为父类,新创建的类称为子类。子类除了继承父类的属性和方法以外,也有自己的属性和方法。

在Python中定义继承的一般格式为:


class 子类名(父类名):
    类体

【例2-19】类的继承实例演示。

以学校成员为例,定义一个父类SchoolMember,然后定义子类Teacher和Student继承SchoolMember。

程序代码如下:


class SchoolMember(object):            # 定义一个父类
    '''学校成员父类'''
    member = 0                         # 定义一个变量记录成员的数目
    def __init__(self, name, age, sex):# 初始化父类的属性
        self.name = name
        self.age = age
        self.sex = sex
        self.enroll()
    def enroll(self):   # 定义一个父类方法,用于注册成员
        '注册成员信息'
        print('just enrolled a new school member [%s].' % self.name)
        SchoolMember.member += 1
    def tell(self):     # 定义一个父类方法,用于输出新增成员的基本信息
        print('----%s----' % self.name)
        for k, v in self.__dict__.items(): # 使用字典保存信息
            print(k, v)
        print('----end-----')    # 分隔线
    def __del__(self):           # 删除成员
        print('开除了[%s]' % self.name)
        SchoolMember.member -= 1
class Teacher(SchoolMember):     # 定义一个子类,继承SchoolMember类
    '教师信息'
    def __init__(self, name, age, sex, salary, course):
        SchoolMember.__init__(self, name, age, sex)# 继承父类的属性
        self.salary = salary
        self.course = course     # 定义子类自身的属性
    def teaching(self):          # 定义子类的方法
        print('Teacher [%s] is teaching [%s]' % (self.name, self.course))
class Student(SchoolMember):     # 定义一个子类,继承SchoolMember类
    '学生信息'
    def __init__(self, name, age, sex, course, tuition):
        SchoolMember.__init__(self, name, age, sex)# 继承父类的属性
        self.course = course         # 定义子类自身的属性
        self.tuition = tuition
        self.amount = 0
    def pay_tuition(self, amount):   # 定义子类的方法
        print('student [%s] has just paied [%s]' % (self.name, amount))
        self.amount += amount
# 实例化对象
t1 = Teacher('Mike', 48, 'M', 8000, 'python')
t1.tell()
s1 = Student('Joe', 18, 'M', 'python', 5000)
s1.tell()
s2 = Student('LiHua', 16, 'M', 'python', 5000)
print(SchoolMember.member)   # 输出此时父类中的成员数目
del s2                       # 删除对象
print(SchoolMember.member)   # 输出此时父类中的成员数目

程序的输出结果如图2-27所示。

图2-27 类的继承显示结果

2.多态

多态是指不同的对象收到同一种消息时产生的不同的行为。在Python中,消息就是指函数的调用,不同的行为是指执行不同的函数。

【例2-20】多态程序实例。


class Animal(object):          # 定义一个父类Animal
    def __init__(self, name):  # 初始化父类属性
        self.name = name
    def talk(self):            # 定义父类方法,抽象方法,由具体而定
        pass
class Cat(Animal):             # 定义一个子类,继承父类Animal
    def talk(self):            # 继承重构类方法
        print('%s: 喵!喵!喵!' % self.name)
class Dog(Animal):   # 定义一个子类,继承父类Animal
    def talk(self):  # 继承重构类方法
        print('%s: 汪!汪!汪!' % self.name)
def func(obj):       # 一个接口,多种形态
    obj.talk()
# 实例化对象
c1 = Cat('Tom')
d1 = Dog('wangcai')
func(c1)
func(d1)

程序运算结果如图2-28所示。

图2-28 多态显示结果

在上面的程序中,Animal类和两个子类中都有talk()方法,虽然同名,但是在每个类中所调用的函数是不一样的。当调用该方法时,所得结果取决于不同的对象。同样的信息在不同的对象下所得的结果不同,这就是多态的体现。