【学习笔记】Python中的类、继承和多态

1. 什么是 Python 中的类和方法

2. Python 中的继承和多态

3. 在 Python 中使用继承和多态计算图形的面积

4. 使用继承和多态实现员工管理系统

1. 什么是 Python 中的类和方法

在 Python 中,“类”是指用于创建对象的模板。它定义了一个类的对象将具有的属性(数据)和行为(方法)。

例如,你可能会定义一个带有属性(如 namebreedage)和方法(如 barkfetch)的类 Dog

“方法”是作为类的一部分定义的函数。它对类的对象的数据(属性)进行操作,使用点符号调用,例如,object.method()

例如,你可能会为类 Dog 定义一个调用时使狗对象叫的方法 bark,如下所示:

class Dog:
    def __init__(self, name, breed, age):
        self.name = name
        self.breed = breed
        self.age = age
    
    def bark(self):
        print("汪汪!")

# create a dog object
dog = Dog("Fido", "Labrador", 3)

# make the dog bark
dog.bark()  # output: "汪汪!"

2. Python 中的继承和多态

在 Python 中,“继承”指的是一个类(子类)可以从另一个类(超类、父类)中继承属性和方法。这使得子类能够继承超类的所有功能,并可以在此基础上添加新的功能。

多态”指的是同一个方法名可以在不同的对象上调用,并产生不同的结果。这使得你可以对不同的对象使用相同的方法名,而不用考虑它们的具体类型。

在 Python 中使用继承而不是试图在一个类中定义所有方法的几个原因

  1. 代码重用:继承允许在子类中重用父类中的代码,这可以为您节省很多时间和精力。这对于大量只在一些细节上不同的相似类特别有用。

  2. 模块化:通过将代码分成较小的、更集中的类,您可以使其更易于理解和维护。继承允许在父类中定义常见行为,然后在子类中将其专化,这可以使您的代码更模块化并更易于使用。

  3. 可扩展性:继承使得很容易向代码中添加新功能。例如,如果您有一个具有一组基本方法的父类,并想要向一个子类中添加一些新功能,则可以简单地在子类中定义一个新方法并按需覆盖父类方法。

  4. 多态:继承允许将子类与父类使用相同的方式,这在希望编写灵活且适用于各种不同对象的代码时非常有用。

下面是一个继承和多态的例子。

在这个例子中,我们定义了一个 Animal 类,其中包含一个带有 namespecies 输入的 __init__ 方法和一个引发 NotImplementedErrormake_sound 方法。这是一个抽象基类,用作具体子类的模板。

然后我们定义了 Animal 的两个子类,分别是 DogCat,每个类都有自己的 __init__ 方法,该方法调用超类的 __init__ 方法并设置子类特定的附加属性(breed)。make_sound 方法也在每个子类中被重写,以返回不同的字符串。

我们使用 Dog 类和 Cat 类分别创建了两个对象,dog1cat1。这些对象继承了 Animal 类的属性和方法,并且还具有自己特定的属性和行为。

这个例子演示了继承,即子类“继承”了超类的属性和方法,以及多态,即同一个方法名(make_sound)可以在不同的对象上调用并产生不同的结果。

class Animal:
    def __init__(self, name, species):
        self.name = name
        self.species = species

    def make_sound(self):
        raise NotImplementedError("子类必须实现此方法")

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name, species="狗")
        self.breed = breed

    def make_sound(self):
        return "汪汪!"

class Cat(Animal):
    def __init__(self, name, breed):
        super().__init__(name, species="猫")
        self.breed = breed

    def make_sound(self):
        return "喵喵!"

dog1 = Dog("Fido", "Labrador")
cat1 = Cat("Fluffy", "Siamese")

print(dog1.name)  # 输出: "Fido"
print(dog1.species)  # 输出: "狗"
print(dog1.breed)  # 输出: "Labrador"
print(dog1.make_sound())  # 输出: "汪汪!"

print(cat1.name)  # 输出: "Fluffy"
print(cat1.species)  # 输出: "猫"
print(cat1.breed)  # 输出: "Siamese"
print(cat1.make_sound())  # 输出: "喵喵!"

在 Python 中,类是一种对象模板。我们可以使用类来定义特定类型的对象,并为这些对象定义属性和方法。

在上面的代码中,我们定义了一个名为 Animal 的类。这个类有一个 __init__ 方法和一个 make_sound 方法。

__init__ 方法是一种特殊的方法,在 Python 中称为构造函数。当我们使用类创建新对象时,构造函数被自动调用。它的作用是初始化新创建的对象。

在这个例子中,__init__ 方法有两个参数:namespecies。这些参数用于初始化新创建的对象的 namespecies 属性。

make_sound 方法是一个普通的方法,但是它并没有返回任何值。相反,它引发了一个 NotImplementedError。这是因为这个类是一个抽象基类,它无法直接创建对象,只能用作其他类的模板。

然后我们定义了 Animal 类的两个子类:DogCat。每个子类都有自己的 __init__ 方法和 make_sound 方法,这些方法分别用于初始化狗和猫的对象,并让它们发出声音。

在最后一部分的代码中,我们使用了点符号来访问对象的属性和方法。例如,我们访问了 dog1 对象的 name 属性和 make_sound 方法。我们也访问了 cat1 对象的 name 属性和 make_sound 方法。

这些对象继承了 Animal 类的属性和方法,以及它们各自的子类(DogCat)中定义的特定属性和行为。这就是继承和多态的概念。

当我们调用 dog1.make_sound() 时,Python 会搜索 dog1 对象的方法,如果找不到,就会搜索 Dog 类中的方法,如果还是找不到,就会搜索 Animal 类中的方法。这就是多态的概念。

这种方法的搜索顺序叫做方法解析顺序,它是 Python 的面向对象编程机制之一。它使得我们可以在类之间创建继承关系,并在不同的对象上调用相同的方法名,而不用考虑它们的具体类型。

3. 在 Python 中使用继承和多态计算图形的面积

from math import pi

class Shape:
    def area(self):
        raise NotImplementedError

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
        
    def area(self):
        return self.width * self.height
    
class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
        
    def area(self):
        return pi * self.radius**2
    
rect = Rectangle(10, 20)
print(rect.area())  # 200

circ = Circle(10)
print(circ.area())  # 314.1592653589793

在这个例子中,我们使用了 Python 的面向对象编程功能来计算图形的面积。

首先,我们定义了一个抽象基类 Shape。这个类中有一个 area 方法,它会引发 NotImplementedError。这个类无法直接创建对象,只能用作其他类的模板。

然后我们定义了两个 Shape 类的子类:RectangleCircle。每个类都有自己的 __init__ 方法,用于初始化对象的特定属性。它们还有自己的 area 方法,用于计算并返回图形的面积。

具体来说,在 Rectangle 类中,我们使用了 __init__ 方法来设置对象的宽度和高度。在 area 方法中,我们使用了这两个属性计算矩形的面积,并将结果返回。

同样,在 Circle 类中,我们使用了 __init__ 方法来设置对象的半径。在 area 方法中,我们使用了这个属性和圆的面积公式($\pi r^2$)计算圆的面积,并将结果返回。

最后,我们使用这两个类分别创建了两个对象:rectcirc。我们使用点符号来调用这两个对象的 area 方法,计算了矩形和圆的面积。这些对象继承了 Shape 类的方法,以及它们自己的子类(RectangleCircle)中定义的特定行为。这就是继承和多态的概念。

当我们调用 rect.area() 时,Python 会搜索 rect 对象的方法,如果找不到,就会搜索 Rectangle 类中的方法,如果还是找不到,就会搜索 Shape 类中的方法。这就是多态的概念。

同样,当我们调用 circ.area() 时,Python 会搜索 circ 对象的方法,如果找不到,就会搜索 Circle 类中的方法,如果还是找不到,就会搜索 Shape 类中的方法。这就是多态的概念。

这种方法的搜索顺序叫做方法解析顺序,它是 Python 的面向对象编程机制之一。它使得我们可以在类之间创建继承关系,并在不同的对象上调用相同的方法名,而不用考虑它们的具体类型。

在以下情况下,子类可能不需要使用 super() 函数来调用父类的 __init__ 方法:

  • 如果父类的 __init__ 方法不需要任何参数,则子类可以直接调用父类的 __init__ 方法,而无需使用 super() 函数。例如:
class Parent:
    def __init__(self):
        self.value = 5

class Child(Parent):
    def __init__(self):
        Parent.__init__(self)

child = Child()
print(child.value)  # prints 5
  • 如果子类不需要初始化任何新的属性,则可以省略子类的 __init__ 方法。在这种情况下,子类就可以直接使用父类的 __init__ 方法,而无需使用 super() 函数。例如:
class Parent:
    def __init__(self, value):
        self.value = value

class Child(Parent):
    pass

child = Child(5)
print(child.value)  # prints 5

4. 使用继承和多态实现员工管理系统

class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        
    def get_name(self):
        return self.name
    
    def get_salary(self):
        return self.salary
    
    def raise_salary(self, amount):
        self.salary += amount
        
    def __str__(self):
        return f'Employee({self.name}, {self.salary})'


class Manager(Employee):
    def __init__(self, name, salary, subordinates):
        super().__init__(name, salary)
        self.subordinates = subordinates
        
    def get_subordinates(self):
        return self.subordinates
    
    def __str__(self):
        return f'Manager({self.name}, {self.salary}, {self.subordinates})'


m1 = Manager('Jane', 20000, ['Tom', 'Jerry'])
print(m1)
print(m1.get_name())
print(m1.get_salary())
print(m1.get_subordinates())

# 调用多态方法
def print_employee_info(e):
    print(e)
    print(f'Name: {e.get_name()}')
    print(f'Salary: {e.get_salary()}')
    if isinstance(e, Manager):
        print(f'Subordinates: {e.get_subordinates()}')

print_employee_info(m1)

这段代码实现了一个简单的员工管理系统,其中包含了两个类:EmployeeManager

  • Employee 类是基类,表示员工的基本信息(名字和工资)。
  • Manager 类继承自 Employee 类,并增加了一个属性 subordinates,表示经理的下属。

我们定义了一个经理(m1),并调用了几个方法来查看这个经理的信息。最后,我们调用了一个多态方法 print_employee_info(),用来输出员工的信息。因为这个方法是多态的,所以它可以输出所有员工的信息,包括经理的信息。

总的来说,继承是用来支持代码复用的,而多态则是用来支持方法或属性的动态行为的。

继承是面向对象编程中的一个概念,表示一个类(子类)可以继承另一个类(父类)的属性和方法。这意味着子类可以直接使用父类中定义的所有属性和方法,并且可以在不改变父类代码的情况下对其进行扩展。

多态是另一个面向对象编程的概念,它指的是在运行时,同一个方法或属性可以有不同的行为。这意味着在继承体系中,子类可以对父类中的方法或属性进行重写,从而具有不同的行为。

参考资料:

猜你喜欢

转载自blog.csdn.net/qq_45659165/article/details/128593052