📜  面向对象的Python教程(1)

📅  最后修改于: 2023-12-03 15:28:53.204000             🧑  作者: Mango

面向对象的Python教程

Python是一门富有表现力,功能强大的编程语言,它支持多编程模式,其中最重要的就是面向对象编程(Object-Oriented Programming,OOP)。通过OOP,我们可以创建对象,将数据和操作封装在对象内部,便于代码的复用和扩展。在这篇文章中,我们将对Python中的OOP进行介绍,包括面向对象编程的基本概念和实践技巧。

面向对象编程基础
类和对象

在OOP中,类是一种抽象数据类型,用来描述具有相同特征和行为的一批对象,它可以看做是一种对象工厂。我们可以通过定义属性和方法来描述一个类,从而创建满足特定需求的对象。例如,我们可以定义一个人类的类,其中属性包括姓名、性别和年龄,方法包括吃饭和睡觉等行为。

# 定义一个人类
class Person:
    def __init__(self, name, gender, age):
        self.name = name
        self.gender = gender
        self.age = age

    def eat(self):
        print('{} is eating.'.format(self.name))

    def sleep(self):
        print('{} is sleeping.'.format(self.name))

在上述代码中,我们使用了class关键字定义了一个名为Person的类。其中,__init__方法是类的构造函数,用于初始化对象属性;eatsleep方法是类的行为,用于描述人类的吃饭和睡觉等行为。在类的内部,我们使用self关键字来表示对象本身,通过这样的方式,我们可以在方法中访问对象的属性和调用类的行为。

要创建一个对象,我们需要使用类的构造函数,并为每个属性传递适当的值。例如:

# 创建一个对象
p = Person('Tom', 'male', 18)

在上述代码中,我们使用Person类的构造函数创建了一个对象p,并为name、gender和age属性分别传递了'Tom'、'male'和18这三个值。现在,我们可以通过以下方式访问对象的属性和行为。

# 访问对象的属性和行为
print(p.name)
# output: Tom

print(p.gender)
# output: male

p.eat()
# output: Tom is eating.

p.sleep()
# output: Tom is sleeping.

在上述代码中,我们访问了对象p的属性和行为,例如,我们可以通过p.name访问对象p的姓名属性,p.eat()调用对象p的吃饭方法。这展示了面向对象编程的基本思想:用类描述对象特征和行为,用对象来完成具体的任务。

继承和多态

继承和多态是面向对象编程中的两个重要概念。继承是一种子类从父类继承行为和属性的机制,在子类中可以重写父类的方法并添加新的方法,从而实现代码的复用和扩展。多态则指相同的方法可以在不同的对象上产生不同的效果。

下面是一个继承的例子,我们创建一个学生类,并让它继承自Person类。学生类和Person类拥有相同的属性和方法,同时学生类还拥有自己的学号属性和学习方法。

# 定义一个学生类
class Student(Person):
    def __init__(self, name, gender, age, student_id):
        super().__init__(name, gender, age)
        self.student_id = student_id

    def study(self):
        print('{} is studying.'.format(self.name))

在上述代码中,我们使用class关键字定义了一个名为Student的类,并使用super().__init__方法调用父类的构造函数,以初始化对象属性。注意,在子类中我们需要传递除了self以外的其他参数。

要创建一个学生对象,我们可以使用如下代码:

# 创建一个学生对象
s = Student('Alice', 'female', 20, '1001')

在上述代码中,我们创建了名为s的学生对象,同时为它传递了一个学号属性'1001'。

现在,我们可以通过以下方式访问学生对象的属性和调用学生对象的行为:

# 访问学生对象的属性和调用学生对象的行为
print(s.name)
# output: Alice

print(s.student_id)
# output: 1001

s.study()
# output: Alice is studying.

在上述代码中,我们访问了学生对象的属性和调用学生对象的行为,例如,我们可以通过s.name访问学生对象的姓名属性,s.study()调用学生对象的学习方法。同时,需要注意的是,学生对象继承了Person类的所有属性和方法,例如,学生对象也可以通过s.eat()来调用Person类的吃饭方法。

下面是一个多态的例子,我们创建一个Teacher类,它和Person类拥有相同的属性和方法,并且实现了自己的行为。

# 定义一个教师类
class Teacher(Person):
    def __init__(self, name, gender, age, teacher_id):
        super().__init__(name, gender, age)
        self.teacher_id = teacher_id

    def teach(self):
        print('{} is teaching.'.format(self.name))

# 创建一个教师对象
t = Teacher('Bob', 'male', 30, '2001')

# 调用teach方法
t.teach()
# output: Bob is teaching.

# 多态的应用,可以将学生对象和教师对象放在同一个列表中
people = [s, t]

# 循环遍历列表,可以看到相同的方法会产生不同的效果
for person in people:
    person.eat()

# output: Alice is eating.
# output: Bob is eating.

在上述代码中,我们创建了一个Teacher对象t,并调用了它的teach方法。同时,我们还将学生对象s和教师对象t放在同一个列表中,并循环遍历这个列表,以调用所有对象的eat方法。可以看到,相同的方法会产生不同的效果,即对象s和对象t都会输出自己的姓名和行为。

面向对象编程实践
封装和访问控制

封装是一种将数据和方法包装在一起的机制,使得外部无法直接访问对象的内部数据,从而提高了代码的安全性和可维护性。在Python中,我们可以通过属性和方法的特性来实现封装。

访问控制则是一种机制,用于控制外部程序对封装数据的访问的方式,Python中提供了属性特性来实现访问控制。属性特性包括读写、只读和只写等,可以根据需要设置不同的特性。

下面是一个封装和访问控制的例子,我们创建一个银行账户类Account,并为它定义一些属性和方法,同时设置一些属性的特性来实现访问控制。

# 定义一个银行账户类
class Account:
    def __init__(self, id, account_type, balance):
        self.__id = id          # 私有属性,无法在类的外部直接访问
        self.__type = account_type  # 私有属性,无法在类的外部直接访问
        self.__balance = balance    # 私有属性,无法在类的外部直接访问

    # 获取账户信息的方法
    def get_account_info(self):
        return {'id': self.__id, 'type': self.__type, 'balance': self.__balance}

    # 存款方法,改变账户余额
    def deposit(self, amount):
        self.__balance += amount

    # 取款方法,改变账户余额
    def withdraw(self, amount):
        self.__balance -= amount

    # 属性特性,只允许读取balance属性,不允许修改
    @property
    def balance(self):
        return self.__balance

    # 属性特性,允许读取和修改id属性
    @property
    def id(self):
        return self.__id

    @id.setter
    def id(self, value):
        self.__id = value

    # 属性特性,允许读取和修改type属性
    @property
    def type(self):
        return self.__type

    @type.setter
    def type(self, value):
        self.__type = value

在上述代码中,我们使用class关键字定义了一个名为Account的类,并使用__将id、type和balance属性设置为私有属性,从而实现了封装。同时,我们为账户类定义了一些方法,包括获取账户信息、存款和取款等。

接下来,我们通过属性特性来实现访问控制,其中@property表示读取属性的特性,@property.setter表示设置属性的特性。在Account类中,我们将id属性设置为可读可写的,type属性和balance属性设置为只读的。

通过这样的方式,我们可以实现访问控制,确保账户属性只能通过类的方法来修改,并且始终保持合法。例如,我们可以创建一个Account对象,并使用属性特性来访问它的属性:

# 创建一个账户对象
a = Account('1001', 'saving', 1000)

# 访问账户属性
print(a.get_account_info())
# output: {'id': '1001', 'type': 'saving', 'balance': 1000}

print(a.id)
# output: 1001

a.withdraw(500)
print(a.balance)
# output: 500

a.id = '1002'
print(a.get_account_info())
# output: {'id': '1002', 'type': 'saving', 'balance': 500}

a.type = 'checking'
# output: AttributeError: can't set attribute

在上述代码中,我们创建了一个名为a的账户对象,并使用a.get_account_info()方法访问它的属性。同时,我们使用a.ida.balance属性特性来访问它的id和balance属性,访问时会自动调用特性来实现访问控制。具体来说,当我们访问id属性时,会调用@property特性来读取属性,而当我们给id属性赋值时,会调用@property.setter特性来设置属性。而当我们试图修改type属性时,由于它是只读属性,会抛出AttributeError异常。

多重继承和Mixin技巧

多重继承是一种从多个类中继承行为和属性的机制,在Python中非常灵活。Mixin技巧是一种多重继承的技巧,通过将不同的类组合在一起,来实现特定功能的复用。Mixin类通常只包含方法,用于增强主类的功能。

下面是一个多重继承和Mixin技巧的例子,我们创建一个动物类Animal、一个鸟类Bird和一个哺乳动物类Mammal,通过多重继承和Mixin技巧,来实现特定功能的复用。

# 定义一个动物类
class Animal:
    def __init__(self, name):
        self.name = name

    def eat(self):
        print('{} is eating.'.format(self.name))

# 定义一个鸟类
class Bird:
    def fly(self):
        print('{} is flying.'.format(self.name))

# 定义一个哺乳动物类
class Mammal:
    def run(self):
        print('{} is running.'.format(self.name))

# 使用多重继承和Mixin技巧来增强主类的功能
class Bat(Bird, Mammal):
    def __init__(self, name):
        super().__init__(name)

    def fly(self):
        print('{} is flying like a bat.'.format(self.name))

# 创建一个蝙蝠对象
b = Bat('Batman')

# 调用蝙蝠对象的方法
b.fly()
# output: Batman is flying like a bat.

b.run()
# output: Batman is running.

在上述代码中,我们定义了一个Animal类、一个Bird类和一个Mammal类,并通过多重继承的方式来继承这些类的功能。因为Bird类和Mammal类中都有run方法,所以我们可以在Bat类中重写这个方法,从而实现特定功能的复用。

接下来,我们定义了一个Bat类,并使用super().__init__()方法来调用父类的构造函数。同时,我们在Bat类中重写了fly方法,使得它的飞行方式与普通鸟类不同。现在,我们创建了一个名为b的蝙蝠对象,并提供它的名字'Batman'。可以看到,我们成功地增强了主类的功能,并实现了特定功能的复用。

总结

在本文中,我们对Python中面向对象编程的基本概念和实践技巧进行了介绍。通过这些技巧,我们可以创建对象,将数据和操作封装在对象内部,实现代码的复用和扩展,并且可以提高代码的安全性和可维护性。在具体实践中,我们可以使用继承和多态机制、封装和访问控制、多重继承和Mixin技巧等,来实现特定功能的复用,并且可以根据需要进行灵活地组合和应用。