面向对象之多态

余生长醉 提交于 2019-12-05 23:32:14

今日学习总结:

一、多态:

01.什么是多态?

多态指的是同一种类型的事物,不同的形态。

-动物

      猪

      狗

      猫

-笔

    铅笔

    钢笔

    毛笔

02.多态的目的?

多态 也称之为 多态性,目的是为了 在不知道对象具体的类型的情况下,统一对象调用方法的规范。

多态的表现 形式之一 就是继承:

先抽象,再继承

父类:定制一套统一的规范。

子类:遵循父类的统一的规范。

注意:在python中,不会强制限制子类必须遵循父类的规范,所以出现了抽象类。

03.多态的实现?

例子:1.继承父类

# 动物类
class Animal:
    def eat(self):
        pass

    def speak(self):
        pass
# 猪类
class Pig(Animal):
    def eat(self):
        print('bia唧...')

    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 = Pig()
animal3 = Cat()

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

 

二、抽象类

01.什么是抽象类?

在python内置的abc模块中,有一个抽象类

02.为什么使用抽象类?

让子类必须遵循父类的编写规范。

03.如何实现抽象类?

父类需要继承abc模块中的 metaclass=abc.ABCMeta

在父类的方法之上,需要装饰上 abc.abstractmethod

注意:在python中,不推荐使用抽象类

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

例子:2.继承抽象类

import abc
# 父类
class Animal(metaclass=abc.ABCMeta):
    # 方法 吃
    @abc.abstractmethod
    def eat(self):
        pass
    # 方法 叫
    @abc.abstractmethod
    def speak(self):
        pass

# 猪类
#这样会出错,因为没有遵循父类,加上metaclass=abc.ABCMeta     @abc.abstractmethod会强制子类要去遵循父类,否则会报错
# class Pig(Animal):
#
#     def run(self):
#         pass
#
#     def chi(self):
#         print('bia唧...')
#
#     def tell(self):
#         print('哼哼哼...')
# 猪类
class Pig(Animal):

    def run(self):
        pass

    def eat(self):
        print('bia唧...')

    def speak(self):
        print('哼哼哼...')
pig_obj = Pig()
pig_obj.eat()

 

三、鸭子类

01.什么是鸭子类型?

不同的对象,只要长得像鸭子,动作行为像鸭子,那他就是鸭子。

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

02.为什么要有鸭子类型?

不同的对象,先抽象出相同的类型的方法,给他们定制一套统一的规范。

所有的类,在定义时都按照统一的规范进行编写。

注意:在python中,强烈推荐使用鸭子类型。

03.如何实现鸭子类型?

例子:3.鸭子类型

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

    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('汪汪汪...')
              
animal1 = Dog()
animal2 = Pig()
animal3 = Cat()

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

 

 

总结:

多态的三种表现形式:

1.继承父类:耦合度高,程序的可扩展性低

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

3.鸭子类型:耦合度低,程序的可扩展性高

四、classmethod与staticmethod

01、python中 默认是:对象的绑定方法。

02、classmethod :是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为‘类的绑定方法’

03、staticmethod:是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为‘非绑定方法’

例子:01

要求:输出__data的值
方法一:这是通过 对象去调用方法和属性 去实现要求
class DB:
    __data='tank is very handsome!'
    def __init__(self,user,pwd,role):
        self.user=user
        self.pwd=pwd
        self.role=role


    def chenck_db(self):
        if self.user=='tank' and self.pwd==123 and self.role=='管理员':
            print('通过验证。。。')
            print(self.__data)     #这是通过 对象去调用方法和属性 去实现要求
            #return self.__data    #这里写不写都行。

db_obj=DB('tank',123,'管理员')
db_obj.chenck_db()


要求输出__data的值
方法二:  这是通过 类去调用方法和属性 去实现要求
class DB:
    __data='tank is very handsome!'
    def __init__(self,user,pwd,role):
        self.user=user
        self.pwd=pwd
        self.role=role


    def chenck_db(self):
        if self.user=='tank' and self.pwd==123 and self.role=='管理员':
            print('通过验证。。。')
            print(self.__class__.__data)     #这是通过 类去调用方法和属性 去实现要求。因为self是db_obj,
                                             #self.__class__ 是类自己
            print(self.__class__)            #<class '__main__.DB'>
            #return self.__class__.__data    #这里写不写都行
db_obj=DB('tank',123,'管理员')
db_obj.chenck_db()

例子:02

#04要求输出__data的值
class DB:
    __data='tank is very handsome!'
    def __init__(self,user,pwd,role):
        self.user=user
        self.pwd=pwd
        self.role=role

    @classmethod                          #这是用classmethod 装饰器,来绑定类的,可以用类名来调用函数。
    def chenck_db(cls,user,pwd,role):
        obj=cls(user,pwd,role)            #这是在类内部产生一个实例
        if obj.user=='tank' and obj.pwd==123 and obj.role=='管理员':
            print('通过验证。。。')
            print(cls.__data)             #这是通过 类去调用方法和属性 去实现要求。因为cls是类自己
DB.chenck_db('tank',123,'管理员')

例子:03

class Foo:
    @staticmethod     #这是用staticmethod 装饰器,是非绑定的,可以用类名或者对象名来调用函数
    def func(res):
        print(res)
obj = Foo()
obj.func(123)         # 对象调用非绑定方法
Foo.func(1234)        # 类调用非绑定方法

 

五、isinstance与issubclass

      是python的内置模块

01、isinstance: 判断一个对象是否是另一个类的实例。
      - 如果是: True
     - 如果不是: False
02、issubclass: 判断一个类是否是另一个类的子类。
      - 如果是: True
     - 如果不是: False

例子:01

#isinstance:
class Foo:
    pass
class Boo:
    pass
foo_obj = Foo()
boo_obj = Boo()

print(isinstance(foo_obj, Foo)) # True   #判断foo_obj (对象)是不是 Foo(类) 的对象
print(isinstance(boo_obj, Foo)) # False  #判断 boo_obj (对象) 是不是 Foo(类) 的对象

例子:02

# issubclass
class Father:
    pass
class Sub(Father):
    pass
class Foo:
    pass
print(issubclass(Sub, Father)) # True   判断 Sub(类) 是不是在 Father(父类)中
print(issubclass(Foo, Father)) # False  判断 Foo(类) 是不是在 Father(父类)中

 

六、反射

01.什么是反射?

反射指的是通过 字符串对 对象的属性进行操作'''

02.反射的四个方法是python内置的:

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

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

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

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

ps:普通的 查、取、改、删 属性或方法

class Foo:
    def __init__(self, x, y):
        self.x = x
        self.y = y
obj=Foo()
obj.x = 10         
print(obj.x)           #查看属性的值
obj.x = 20             #修改属性的值
del obj.x              #删除属性     

用反射 进行 查改删 属性或方法

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:设置一个属性z,值为30 。增加一个属性
setattr(foo_obj, 'z', 30)
print(hasattr(foo_obj, 'z'))  # True

#delattr:删除一个属性
delattr(foo_obj, 'x')
print(hasattr(foo_obj, 'x'))  # False

 

ps:反射的应用:

class FileControl:

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

            if hasattr(self, user_input):        # 通过用户输入的字符串判断方法是否存在
                func = getattr(self, user_input) #用getattr 来获取属性。在这里获取的是selfz这个对象
                func()                           #相当于对象加上()  表示调用.相当于 调用类。既是file_control_obj()既是 FileControl()()
            else:
                print('输入有误!')

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

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


file_control_obj = FileControl()
file_control_obj.run()

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!