1. 什么是 Python 中的类和方法
2. Python 中的继承和多态
3. 在 Python 中使用继承和多态计算图形的面积
4. 使用继承和多态实现员工管理系统
1. 什么是 Python 中的类和方法
在 Python 中,“类”是指用于创建对象的模板。它定义了一个类的对象将具有的属性(数据)和行为(方法)。
例如,你可能会定义一个带有属性(如 name
、breed
和 age
)和方法(如 bark
和 fetch
)的类 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 中使用继承而不是试图在一个类中定义所有方法的几个原因:
-
代码重用:继承允许在子类中重用父类中的代码,这可以为您节省很多时间和精力。这对于大量只在一些细节上不同的相似类特别有用。
-
模块化:通过将代码分成较小的、更集中的类,您可以使其更易于理解和维护。继承允许在父类中定义常见行为,然后在子类中将其专化,这可以使您的代码更模块化并更易于使用。
-
可扩展性:继承使得很容易向代码中添加新功能。例如,如果您有一个具有一组基本方法的父类,并想要向一个子类中添加一些新功能,则可以简单地在子类中定义一个新方法并按需覆盖父类方法。
-
多态:继承允许将子类与父类使用相同的方式,这在希望编写灵活且适用于各种不同对象的代码时非常有用。
下面是一个继承和多态的例子。
在这个例子中,我们定义了一个 Animal
类,其中包含一个带有 name
和 species
输入的 __init__
方法和一个引发 NotImplementedError
的 make_sound
方法。这是一个抽象基类,用作具体子类的模板。
然后我们定义了 Animal
的两个子类,分别是 Dog
和 Cat
,每个类都有自己的 __init__
方法,该方法调用超类的 __init__
方法并设置子类特定的附加属性(breed
)。make_sound
方法也在每个子类中被重写,以返回不同的字符串。
我们使用 Dog
类和 Cat
类分别创建了两个对象,dog1
和 cat1
。这些对象继承了 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__
方法有两个参数:name
和 species
。这些参数用于初始化新创建的对象的 name
和 species
属性。
make_sound
方法是一个普通的方法,但是它并没有返回任何值。相反,它引发了一个 NotImplementedError
。这是因为这个类是一个抽象基类,它无法直接创建对象,只能用作其他类的模板。
然后我们定义了 Animal
类的两个子类:Dog
和 Cat
。每个子类都有自己的 __init__
方法和 make_sound
方法,这些方法分别用于初始化狗和猫的对象,并让它们发出声音。
在最后一部分的代码中,我们使用了点符号来访问对象的属性和方法。例如,我们访问了 dog1
对象的 name
属性和 make_sound
方法。我们也访问了 cat1
对象的 name
属性和 make_sound
方法。
这些对象继承了 Animal
类的属性和方法,以及它们各自的子类(Dog
或 Cat
)中定义的特定属性和行为。这就是继承和多态的概念。
当我们调用 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
类的子类:Rectangle
和 Circle
。每个类都有自己的 __init__
方法,用于初始化对象的特定属性。它们还有自己的 area
方法,用于计算并返回图形的面积。
具体来说,在 Rectangle
类中,我们使用了 __init__
方法来设置对象的宽度和高度。在 area
方法中,我们使用了这两个属性计算矩形的面积,并将结果返回。
同样,在 Circle
类中,我们使用了 __init__
方法来设置对象的半径。在 area
方法中,我们使用了这个属性和圆的面积公式($\pi r^2$)计算圆的面积,并将结果返回。
最后,我们使用这两个类分别创建了两个对象:rect
和 circ
。我们使用点符号来调用这两个对象的 area
方法,计算了矩形和圆的面积。这些对象继承了 Shape
类的方法,以及它们自己的子类(Rectangle
或 Circle
)中定义的特定行为。这就是继承和多态的概念。
当我们调用 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)
这段代码实现了一个简单的员工管理系统,其中包含了两个类:Employee
和 Manager
。
Employee
类是基类,表示员工的基本信息(名字和工资)。Manager
类继承自Employee
类,并增加了一个属性subordinates
,表示经理的下属。
我们定义了一个经理(m1
),并调用了几个方法来查看这个经理的信息。最后,我们调用了一个多态方法 print_employee_info()
,用来输出员工的信息。因为这个方法是多态的,所以它可以输出所有员工的信息,包括经理的信息。
总的来说,继承是用来支持代码复用的,而多态则是用来支持方法或属性的动态行为的。
继承是面向对象编程中的一个概念,表示一个类(子类)可以继承另一个类(父类)的属性和方法。这意味着子类可以直接使用父类中定义的所有属性和方法,并且可以在不改变父类代码的情况下对其进行扩展。
多态是另一个面向对象编程的概念,它指的是在运行时,同一个方法或属性可以有不同的行为。这意味着在继承体系中,子类可以对父类中的方法或属性进行重写,从而具有不同的行为。
参考资料:
- Python 文档中有一个关于面向对象编程的章节,其中介绍了继承和多态的概念。你可以在这里阅读:9. Classes — Python 3.11.1 documentation
- Python 文档中还有一个关于方法解析顺序的章节,其中介绍了 MRO 的概念。你可以在这里阅读:9. Classes — Python 3.11.1 documentation