面向对象三大特性之多态

面向对象三大特性的多态

一、多态

  • 概念
'''
1、什么是多态?
    多态指的是同一种类型的实物,不同的形态

    - 父类:动物
        - 吃: eat
        - 叫: speak

    - 子类:
        - 猪:
            吃:eat
                吧唧吧唧
            叫:speak
                哼哼哼
            技能:
                飞

        - 狗:
            吃:tian chi
                舔 ji 舔 ji
            叫:tell
                汪汪汪
            游泳

        - 猫:
            吃:chi
                咬 ji 咬 ji
            叫:jaio
                喵喵喵


    - 笔
        铅笔:
            写:def write():
                写完可以擦掉

        钢笔:

            写:def xie():
                写完可以用胶布粘掉

        毛笔:
            写:def xie_zi():
                写完可以手撕,无法从写

2、多态的目的:
        “多态”也被称之为“多态性”,目的是为了 在不知道对象具体类型的情况下,统一对象调用方法的规范(比如:名字)

        多态的表现“形式之一”就是继承:
            - 先抽象,再继承

            父类:定制一套统一的规范(比如:方法名统一)
            子类:遵循父类的统一的规范(比如:子类继承父类方法名的统一)

        注意:在python中不会强制限制子类必须遵循父类的规范,所以出现了抽象类
'''
  • 代码
# # 正面教材
# #动物类
# class Animal:
#
#     #方法吃
#     def eat(self):
#         pass
#
#     #方法叫
#     def speak(self):
#         pass
#
# #猪类
# class Pig(Animal):
#     def eat(self):
#         print('吧唧....')
#
#     def speak(self):
#         print('哼哼哼....')
#
# #猫类
# class Cat(Animal):
#     def eat(self):
#         print('咬 ji 咬 ji ')
#
#     def speak(self):
#         print('喵喵喵...')
#
# #狗类
# class Dog(Animal):
#     def eat(self):
#         print('舔ji 舔ji')
#
#     def speak(self):
#         print('汪汪汪...')
#
#
# animal1 = Dog()
# animal2 = Cat()
# animal3 = Pig()
#
# #让动物们叫起来
# animal1.speak()
# animal2.speak()
# animal3.speak()


#反面教材
#动物类
class Animal:

    #方法吃
    def eat(self):
        pass

    #方法叫
    def speak(self):
        pass

#猪类
class Pig(Animal):
    def eat(self):
        print('吧唧')

    def speak(self):
        print('哼哼哼')

#猫类
class Cat(Animal):
    def chi(self):
        print('咬ji 咬ji')

    def jaio(self):
        print('喵喵喵')

#狗类
class Dog(Animal):
    def tian_chi(self):
        print('舔 ji 舔 ji')

    def wangwang_jiao(self):
        print('汪汪汪')

animal1 = Dog()
animal2 = Pig()
animal3 = Cat()

#让动物们叫起来
animal1.speak()
animal2.speak()
animal3.speak()

二、抽象类

  • 夺命三问
'''
1、什么是抽象类?
    在python中内置的abc模块中,有一个抽象类

2、抽象类的作用:
    让子类必须遵循父类的编写规范

3、如何实现抽象类?
    - 父类需要继承abc模块中,metaclass=abc.ABCMeta
    - 在父类的方法中,需要装饰上 abc.abstractmethod

注意:在python中不推荐使用抽象类(耦合度极高,程序可扩展性极地)

注意:子类必须按照父类的方法编写规范,缺一不可(只要父类中有几个抽象方法,子类就必须要定义几个)

'''
  • 代码
import abc
#父类
class Animal(metaclass=abc.ABCMeta):

    #方法:吃
    @abc.abstractmethod
    def eat(self):
        pass

    #方法:叫
    @abc.abstractmethod
    def speak(self):
        pass

#子类
#猪类
class Pig(Animal):

    def eat(self):
        print('吧唧吧唧')

    def speak(self):
        print('哼哼哼')

    def run(self):
        pass

pig_obj = Pig()
print(pig_obj.speak())  #哼哼哼

三、鸭子类型

  • 夺命三问
'''
1、什么是鸭子类型?
    不同的对象,只要长得像鸭子,动作行为像鸭子,那他就是鸭子

    鸭子类型也是多态的一种表现形式

2、为什么要有鸭子类型?
    不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范
    所有的类,在定义时都按照统一的规范进行编写

    - 多态的三种表现形式:
        - 继续父类:
            -耦合度高,程序可扩展性低

        - 继承抽象类:
            - 耦合度极高,程序的可扩展性极地

        - 鸭子类型:
            - 耦合度低,程序的可扩展性高
    注意:因为鸭子类型的耦合性低,可扩展性高,所以在python中强烈推荐鸭子类型

'''

  • 代码
#猪类
class Pig:
    def eat(self):
        print('吧唧吧唧')

    def speak(self):
        print('哼哼哼')

#猫类
class Cat:
    def eat(self):
        print('咬ji咬ji ')

    def speak(self):
        print('喵喵喵')

#狗类
class Dog:
    def eat(self):
        print('舔 ji 舔 ji')

    def speak(self):
        print('汪汪汪')

四、多态之炫技

  • 实例
#多态之炫技:了解,面试时装逼用的

#猪类
class Pig:
    def eat(self):
        print('吧唧吧唧')

    def speak(self):
        print('哼哼哼')

#猫类
class Cat:
    def eat(self):
        print('咬 ji 咬 ji')

    def speak(self):
        print('喵喵喵')

#狗类
class Dog:
    def eat(self):
        print('舔 ji 舔 ji')

    def speak(self):
        print('汪汪汪')

dog = Dog()
pig = Pig()
cat = Cat()

# dog.speak()
# pig.speak()
# cat.speak()

#多态之炫技
# def SPEAK(animal):
#     animal.speak()
#
# SPEAK(dog)
# SPEAK(cat)
# SPEAK(pig)

str1 = 'yafeng is very handsome!!!'
list1 = ['yafeng', 'is', 'very', 'handsome!!!']

print(str1.__len__())  #26
print(list1.__len__())  #4

#自定义统计长度函数
def LEN(obj):
    return obj.__len__()

print(LEN(str1))  #26
print(LEN(list1))  #4

print(len(str1))  #26
print(len(list1))  #4

五、isinstance 与 issubclass

  • 理论基础
'''
isinstance 与 issubclass 是python的内置模块:
    - isinstance: 判断一个对象是否是另一个类的实例(isinstance还可以判断一个对象是否是一个已知的类型,类似type)
        - 如果是:True
        - 如果不是:False

    - issubclass: 判断一个类是否是另一个类的子类
        - 如果是:True
        - 如果不是:False
'''

  • 实例
#isinstance:
class Foo:
    pass

class Boo:
    pass

foo_obj = Foo()
boo_obj = Boo()

print(isinstance(foo_obj, Foo))  #True

print(isinstance(boo_obj, Foo))  #False


#issubclass
class Father:
    pass

class Sub(Father):
    pass

class Foo:
    pass

print(issubclass(Sub, Father))  #True

print(issubclass(Foo, Father))  #False

六、classmethod 与 staticmethod

  • 理论基础
'''
1、classmethod 与 staticmethod都是python解释器内置的装饰器

classmethod:
    是一个装饰器,给在类内部定义的方法装饰,将类内部的方法变为“类的绑定方法”。

staticmethod:
    翻译:静态方法
    是一个装饰器,给在类内部定义的方法装饰,将类内部的方法变为“非绑定方法”

- 对象的绑定方法:
    - 由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入。

- 类的绑定方法:
    - 由类来调用,由谁来调用,会将谁(类)当做第一个参数传入。

- 非绑定方法:
    - 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个

'''

  • 实例
# #classmethod
# class DB:
#     __data = 'yafeng is very handsome!!!'
#
#     def __init__(self, user, pwd, role):
#         self.user = user
#         self.pwd = pwd
#         self.role = role
#
#     #查看数据方法
#     @classmethod
#     def check_db(cls, user, pwd, role):  #cls--->指的是类
#
#         #在类方法内部定义调用类产生一个实例---->对象
#         obj = cls(user, pwd, role)
#
#         #1、查看数据前,必须要通过校验
#         if obj.user == 'yafeng' and obj.pwd == '666' and obj.role == 'admin':
#             print('校验通过')
#             print(cls.__data)
#             return cls.__data
#
# DB.check_db('yafeng', '666', 'admin')
# #校验通过
# # yafeng is very handsome!!!


# #staticmethod
# import uuid  #用于产生随机字符串的模块
#
# print(uuid.uuid4())  #bf30df87-0071-4c8e-bd7d-cfb3cea7c260


class Foo:
    @staticmethod
    def func(res):
        print(res)

obj = Foo()

#对象调用非绑定方法(此时需传参)
obj.func(666)   #666

#类调用非绑定方法
Foo.func(123)   #123

七、反射

  • 理论知识
'''
反射:
    反射指的是通过“字符串”对 对象的属性进行操作

    - hasattr:通过“字符串”判断对象的属性或方法是否存在

    - getattr:通过“字符串”获取对象的属性或方法

    - setattr:通过“字符串”设置对象的属性或方法

    - delattr:通过“字符串”删除对象的属性或方法

    注意:反射的四个方法是python内置的
'''
  • 举例
# class Foo:
#     def __init__(self, x, y):
#         self.x = x
#         self.y = y
#
#
# foo_obj = Foo(10, 20)
#
# #hasattr
# #通过字符串x 判断对象中是否有x属性
# print(hasattr(foo_obj, 'x'))  #True
# print(hasattr(foo_obj, 'y'))  #True
# print(hasattr(foo_obj, 'z'))  #False
#
#
# #getattr
# res = getattr(foo_obj, 'x')
# print(res)  #10
#
# #若属性不存在,也可以自定义返回的默认值
# res = getattr(foo_obj, 'z', '默认值')
# print(res)  #默认值
#
# #setattr
# #为foo_obj 设置一个属性z, 值为30
# # res = setattr(foo_obj, 'z', 30)
# # print(res)   #*****不可以这么玩None
#
# setattr(foo_obj, 'z', 30)
# print(hasattr(foo_obj, 'z'))  #True
# res = getattr(foo_obj, 'z')
# print(res)   #30
#
# #delattr
# delattr(foo_obj, 'x')
# print(hasattr(foo_obj, 'x'))  #False

  • 反射应用
#反射应用
class File_control:
    def run(self):
        while True:
            #让用户输入上传或下载功能的命令:
            user_input = input('请输入 上传(upload)或 下载(download) 的功能:').strip()

            #通过用户输入的字符串判断方法是否存在,然后调用相应的方法
            if hasattr(self, user_input):  #  if  True:
                func = getattr(self, user_input)   #拿到内容

                func()

            else:
                print('输入有误...')

    def upload(self):
        print('文件正在上传...')

    def download(self):
        print('文件正在下载...')

file_obj = File_control()
file_obj.run()
'''
请输入 上传(upload)或 下载(download) 的功能:upload
文件正在上传...
请输入 上传(upload)或 下载(download) 的功能:download
文件正在下载...
请输入 上传(upload)或 下载(download) 的功能:
'''
原文地址:https://www.cnblogs.com/yafeng666/p/11950982.html