一. 前言

Python中的抽象类、多态和鸭子类型都是实现代码灵活性的机制,但它们之间还是有一些区别的。

二. 三者的区别

  • 抽象类: 要求子类必须实现某些方法,从而规范了子类的实现方式。
  • 多态: 同一个方法可以针对不同类型的对象进行不同的实现,提高了代码的灵活性。
  • 鸭子类型: 不关心对象的类型,只关心对象是否具有某些特定的方法或属性。

三. 概念及示例代码

1. 多态

1.1 多态的三种表现形式:

  • 继承抽象类
    • 耦合度极高,程序的可扩展性极低
  • 继承父类
    • 耦合度高,程序的可扩展性低
  • 鸭子类型
    • 耦合度低,程序的可扩展性高

1.2 多态的目的:

为了在不知道对象具体类型的情况下,统一对象调用方法的规范(名字)

父类: 定制一套统一的规范。(比如: 方法名统一)

子类: 遵循父类的统一的规范。(比如: 子类遵循父类方法名的统一)

1.3 多态的好处:

  1. 增加了程序的灵活性
    以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(people1)
  2. 增加了程序的可扩展性
    通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(people1)去调用

1.4 多态示例代码

class People(Animal): #属于动物的另外一种形态:人

    def speak(self):

        print('say hi')

def func(people): #对于使用者来说,自己的代码根本无需改动

    people.speak()

people1=People() #实例出一个人

func(people1) #甚至连调用方式也无需改变,就能调用人的talk功能

'''

这样我们新增了一个形态People,由People类产生的实例people1,使用者可以在完全不需要修改自己代码的情况下,

使用和猫、狗、猪一样的方式调用people1的speak方法,即func(people1)

'''

示例代码二

class Shape:
    def area(self):
        pass

class Square(Shape):
    def __init__(self, side):
        self.side = side
    
    def area(self):
        return self.side ** 2

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2

def print_area(shape):
    print(shape.area())

s = Square(5)
c = Circle(3)

print_area(s)   # 25
print_area(c)   # 28.26

在上述代码中,Shape类是一个基类,定义了一个方法area()SquareCircle类继承了Shape类,并分别实现了自己的area()方法。print_area()函数接受一个Shape类型的参数,不同类型的Shape对象会产生不同的行为,实现了多态。

2. 抽象类

2.1 什么是抽象类?

在python内置的abc模块中,有一个抽象类,让子类必须遵循父类的编写规范。

2.2 如何实现抽象类

  • 父类需要继承abc模块中的metaclass=abc.ABCMeta
  • 在父类的方法中,需要装饰上 abc.abstractmethod

注意:

  • 在python中不推荐使用抽象类。

  • 子类必须按照父类的方法编写规范,缺一不可。(只要父类中有几个抽象方法,子类就必须要定义几个,可以多,但不能少)

2.3 抽象类示例代码

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Square(Shape):
    def __init__(self, side):
        self.side = side
    
    def area(self):
        return self.side ** 2

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2

# 不能实例化Shape
# s = Shape()

sq = Square(5)
c = Circle(3)

print(sq.area())   # 25
print(c.area())    # 28.26

在上述代码中,Shape类是一个抽象类,定义了一个抽象方法area()SquareCircle类继承了Shape类,并分别实现了自己的area()方法。由于Shape是抽象类,不能直接实例化,只能通过子类进行实例化。

3. 鸭子类型

3.1 什么是鸭子类型

  • python崇尚鸭子类型,不同的对象,只要长得像鸭子,动作行为像鸭子,那它就是鸭子。
  • 鸭子类型是多态的一种表现形式。

3.2 为什么要有鸭子类型

不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范。所有的类,在定义时都按照统一的规范进行编写。

3.3 鸭子类型示例代码

class Duck:
    def quack(self):
        print("Quack")

class Person:
    def quack(self):
        print("I'm quacking like a duck")

def duck_test(obj):
    obj.quack()

d = Duck()
p = Person()

duck_test(d)    # Quack
duck_test(p)    # I'm quacking like a duck

在上述代码中,DuckPerson类都有一个quack()方法,duck_test()函数接受一个对象参数,只要该对象有quack()方法即可,不关心其具体类型,实现了鸭子类型。

四. 总结:

  • 抽象类是一种特殊的类,不能被实例化。它的作用是规范子类的行为。
  • 多态是一种基于继承的特性,同一个方法可以针对不同类型的对象进行不同的实现。
  • 鸭子类型是一种动态类型机制,关注对象的行为而不关注其类型,只要一个对象实现了特定的接口,就可以被当做该接口的实现对象。

以上就是关于Python -【多态,抽象类,鸭子类型】的区别及使用介绍,希望对你有所帮助!

09-16 04:17