08-04 多态与鸭子类型

一. 多态与多态性

"""
什么是多态?
    多态指的是同一种事物有多种形态. 比如动物的多种形态有:猫、狗、猪.  
"""
# 多态: 同一种事物有多种形
class Animal:
    pass

class People(Animal):
    pass

class Dog(Animal):
    pass

class Pig(Animal):
    pass

二. 由多态带来的特性 => 多态性

"""
什么是多态性?
    多态性指的是可以在不用考虑对象具体类型的情况下直接使用对象. 这就需要在设计时, 把对象调用绑定方法时的使用形式统一成一种.    
多态性的好处:
    由多态性的关系, 对象的调用方式可以更进一步, 可以定义一个统一的接口来使用. 从而增强了程序的灵活性和可扩展性.  
"""
class Animal:  # 统一所有子类的方法
    def say(self):
        print("动物的基本发声频率: ", end='')

class People(Animal):
    def say(self):
        super().say()
        print("呼呼呼哈哈哈")

class Pig(Animal):
    def say(self):
        super(Pig, self).say()
        print("哼哼哼哈哈哈")

class Dog(Animal):
    def say(self):
        super(Dog, self).say()
        print("汪汪汪哈哈哈")

obj1 = People()
obj2 = Pig()
obj3 = Dog()

# obj1.say()
# obj2.say()
# obj3.say()


# 定义统一的接口, 接受传入的都属于动物的对象
def animal_say(obj):
    obj.say()

animal_say(obj1)
animal_say(obj2)
animal_say(obj3)
  • 列举python中含有这种多态性的思想的实例
"""
1. 字符串, 列表, 元组, 字典, 集合等等都可以直接使用len()函数, 完美的展现了多态性的思想. 它们虽然都不是同一类型, 但是它们都是多个值的类型. 所以我们都可以不考虑它们的对象的具体类型直接使用对象.
2. python中的len()函数, 内部就是对__len__()的调用的封装. 
"""
str1 = 'hello'
list1 = [1, 2, 3]
tuple1 = (1, 2, 3)
dict1 = {'name': 'egon', 'age': 81}
set1 = {'a', 'b', 'c'}
# 基于多态性可以不考虑对象的类型直接使用对象
print(str1.__len__())
print(list1.__len__())
print(tuple1.__len__())
print(dict1.__len__())
print(set1.__len__())

# 使用提供好的统一的接口
print(len(str1))
print(len(list1))
print(len(tuple1))
print(len(dict1))
print(len(set1))

# 自定义接口
def my_len(obj):
    return obj.__len__()

print(my_len(str1))
print(my_len(list1))
print(my_len(tuple1))
print(my_len(dict1))
print(my_len(set1))

三. 鸭子类型

"""
什么是鸭子类型?
    其实我们完全可以不依赖于继承,只需要制造出外观和行为相同对象,同样可以实现不考虑对象类型而使用对象,这正是Python崇尚的“鸭子类型”(duck typing):“如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子”。比起继承的方式,鸭子类型在某种程度上实现了程序的松耦合度
"""
class Cpu:
    def read(self):
        print("Cpu read")

    def write(self):
        print("Cpu write")

class Mem:  # Mem 显示随机存取存贮器的分配信息
    def read(self):
        print("Mem read")
        
    def write(self):
        print("Mem write")

class Txt:
    def read(self):
        print("Txt read")

    def write(self):
        print("Txt write")
        
obj1 = Cpu()
obj2 = Mem()
obj3 = Txt()

# 制造出外观和行为相同对象,同样可以实现不考虑对象类型而使用对象
obj1.read()
obj1.write()

obj2.read()
obj2.write()

obj3.read()
obj3.write()

四. 通过在父类引入抽象类的概念来硬性限制子类必须有某些方法名

"""
多态性的本质在于不同的类中定义有相同的方法名, 这样我们就可以不考虑类而统一用一种方式去适用对象, 基于这种前提下, 我们还可以进一步使用限制性的思想来提升这种高度. 因此我们可以通过在父类中引入抽象类的概念来硬性限制子类必须有某些方法名
"""
import abc

class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def say(self):  # 注意1: 引入抽象类概念的类只需要定义一个标准,不写代码硬性规定继承它的子类必须遵循它的标准
        pass

# obj = Animal()  # 注意2: 不能实例化引入抽象类概念的类. 抛出异常: TypeError: Can't instantiate abstract class Animal with abstract methods say

class People(Animal):
    def say(self):
        pass

class Dog(Animal):
    def say(self):
        pass

class Pig(Animal):
    def say(self):
        pass

# 注意3: 继承引入抽象类概念的类, 其子类必须含有定义抽象类中的方法, 才能正常的实例化.
obj1 = People()
obj2 = Dog()
obj3 = Pig()
posted @ 2020-04-10 22:47  给你加马桶唱疏通  阅读(148)  评论(0编辑  收藏  举报