8.1 多态
多态是面向对象编程(OOP)的一个基本概念,它允许不同类的对象使用相同的接口。
在Python中,多态是通过动态类型和继承实现的。多态的一个重要方面是方法重载和子类对基类方法的替换。
多态的核心概念:
不同对象的统一接口:
多态允许为不同类的对象使用同一个接口,这些对象可以有不同的方法实现。
动态类型:
在Python中,变量的类型是在运行时确定的,这允许函数处理任何支持所需接口的类的对象。
继承:
允许创建类的层次结构,其中子类继承基类的属性和方法,但可以为其特定功能重新定义它们。
多态的例子:
一个简单的多态例子:所有三个类都有一个名为move()
的方法。这意味着我们可以编写一个同时可以使用这些对象的代码。
class Car:
def move(self):
pass
class Human:
def move(self):
pass
class Bird:
def move(self):
print("卡!")
car = Car()
human = Human()
bird = Bird()
for it in [car, human, bird]:
it.move()
在这种情况下,“共同接口”是方法的名称,或者说是方法的签名(如果方法有参数的话)。
8.2 方法重写
多态常与继承一起使用,以创建一个类层次结构,其中基类定义了一个通用接口,而子类实现了具体细节。
class Employee:
def get_salary(self):
return 1000
class FullTimeEmployee(Employee):
def get_salary(self):
return 5000
class PartTimeEmployee(Employee):
def get_salary(self):
return 3000
class Intern(Employee):
pass
def print_salary(employee):
print(employee.get_salary())
employees = [FullTimeEmployee(), PartTimeEmployee(), Intern()]
for employee in employees:
print_salary(employee)
这个例子类似于前一个,但有一个重要区别——我们的类不需要自己有get_salary
方法,因为它在基类中总是存在。现在所有类的“共同接口”不仅仅是get_salary()
方法,而是包含其所有方法和属性的Employee
类。
8.3 调用子类方法
仔细看看下面的代码:
我们调用的方法print_salary()
只在基类Employee中定义,而它又从基类中调用另一个方法——get_salary()
。那么屏幕上会显示什么样的薪水呢?
class Employee:
def print_salary(self):
salary = self.get_salary()
print(salary)
def get_salary(self):
return 1000
class FullTimeEmployee(Employee):
def get_salary(self):
return 5000
class PartTimeEmployee(Employee):
def get_salary(self):
return 3000
class Intern(Employee):
pass
employees = [FullTimeEmployee(), PartTimeEmployee(), Intern()]
for employee in employees:
employee.print_salary()
重要!
请阅读以下内容——这很重要。
如果我们在FullTimeEmployee
类中调用方法print_salary()
,那么将调用基类的方法,因为在此类中没有定义该方法。
但是这个方法print_salary()
将会调用self
对象的get_salary()
方法,而self
的类型是FullTimeEmployee
,而不是Employee
。所以,调用的正是FullTimeEmployee
类中的get_salary()
方法。
更进一步,类FullTimeEmployee
可以调用基类的方法get_salary()
来满足自己的需求。例如,我们想要根据基本工资计算百分比工资:
class FullTimeEmployee(Employee):
def get_salary(self):
base_salary = super().get_salary()
return base_salary * 5 # 500%
class PartTimeEmployee(Employee):
def get_salary(self):
base_salary = super().get_salary()
return base_salary * 3 # 300%
8.4 方法重载
在Python中,方法重载(method overloading)是指创建多个具有相同名称但参数不同的方法的能力。然而,Python不像其他语言(例如C++或Java)那样直接支持这种方法重载。
在Python中,可以通过使用默认参数、*args
和**kwargs
来模拟方法重载。
方法重载的例子
我们可以实现一个函数,该函数根据传递的参数数量具有不同的行为。可以通过多种方式实现它,例如这样:
class Example:
def display(self, a=None, b=None):
if a is not None and b is not None:
print(a, b)
elif a is not None:
print(a)
else:
print("没有参数")
obj = Example()
obj.display(1, 2) # Output: 1 2
obj.display(1) # Output: 1
obj.display() # Output: No arguments
也可以考虑传递数据的类型——只需进行类型检查即可:
class Example:
def mod(self, a, b):
if type(a) == int and type(b) == int:
print(a % b)
elif type(a) == float or type(b) == float:
print(round(a / b))
else:
print("帮助说明: a和b应为int或float")
obj = Example()
obj.mod(5, 2) # Output: 1
obj.mod(5.0, 2) # Output: 2
obj.mod("5", 2) # Output: Help instruction: a and b should be int or float
如果传递的数据类型不正确,可以输出说明或甚至是在网上的文档链接——这也是一种很流行的解决方案。
GO TO FULL VERSION