• Python-多态


    一、在子类派生的新方法中重用父类功能的方式二

    super()方法:调用super(自己的类名,self)会返回一个特殊的对象,super(自己的类名,self).属性,会参照属性发起者类的mro列表去当前所在类的父类中查找属性。

    # 在python3中,会自动帮你添加super需要的两个默认参数,可省略为super()
    
    class Student(People):
        def __init__(self,name,age,gender,stu_id,course):
            # super(Student,self).__init__(name,age,gender)
            super().__init__(name,age,gender)
            self.stu_id = stu_id
            self.course = course
    

    两个小练习,加深super的查找顺序:

    class A:
        def test(self):
            super().test()
    class B:
        def test(self):
            print('from B')
    class C(A,B):
        pass
    
    c=C()
    print(C.mro())
    c.test()
    --------------------
    '''
    问:是否会报错?
    答案:不会报错,因为属性的查找发起者是C不是A,C的mro列表中,查找顺序为C-A-B,所以A中没有会去B中找,能找到。
    虽然A与B没有继承关系,但是因为发起者是C,虽然在A中才使用super方法,但依然会去B中找
    '''
    
    class A:
        def test(self):
            print('A---->test')
            super().aaa()
    class B:
        def test(self):
            print('B---->test')
    
        def aaa(self):
            print('B---->aaa')
    
    class C(A,B):
        def aaa(self):
            print('C----->aaa')
    
    c=C()
    print(C.mro())
    c.test()
    ------------------------
    '''
    问:结果是什么?
    答案:
    A---->test
    B---->aaa
    查找顺序是按照查找发起者的mro列表,但是在super查找时,会从当前类的下一个类中找,在本题中,supper在A中,根据mro列表,查找顺序为C-A-B-Object,所以去B中找到了
    '''
    

    练习三,加深super()所传对象理解,我们知道super()自动帮我们传了super(自己的类名,self)

    class A: 
    	def x(self):
    		print('run A.x')
    		super().x()
    		print(self)
    
    class B:
    	def x(self):
    		print('run B.x')
    		print(self)
    		
    class C(A,B):
    	def x(self):
    		print('run C.x')
    		super().x()
    		print(self)
    
    C().x()
    

    二、组合(表达了什么有什么的关系)

    组合:把另外一个类的对象赋值给当前对象的属性

    class Teacher:
        def __init__(self, name, age, gender, level):
            self.name = name
            self.age = age
            self.gender = gender
            self.level = level
    
        def tell(self):
            print("%s:%s" % (self.name, self.age))
    
    
    class Student:
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
    
    
    class Course:
        def __init__(self, name, price, period):
            self.name = name
            self.price = price
            self.period = period
    
        def tell(self):
            print('<%s:%s:%s>' % (self.name, self.price, self.period))
    
    
    tea1 = Teacher("egon", 18, "male", 10)
    stu1 = Student("xxx", 19, "male")
    
    python = Course("python开放", 30000, "3mons")
    linux = Course("linux课程", 30000, "3mons")
    
    tea1.courses = [python,linux]
    stu1.course = python
    

    三、多态

    多态:同一种事物有多种形态
    例如:动物就有多种形态,如人,猫,狗等
    特性,我们可以在不考虑某一个对象的具体类型情况下直接使用对象
    举例:事物有多个形态

    利用abc模块下的abstractmethod,可以强制继承了本类的子类必须实现本类的方法。可以只写一个pass,但必须要写这个方法

    import abc
    class File(metaclass=abc.ABCMeta): #同一类事物:文件
        @abc.abstractmethod
        def click(self):
            pass
    
    class Text(File): #文件的形态之一:文本文件
        def click(self):
            print('open file')
    
    class ExeFile(File): #文件的形态之二:可执行文件
        def click(self):
            print('execute file')
    

    应用:

    # 假设我们已经定义了People,Dog,Pig三个类
    
    peo=People()
    dog=Dog()
    pig=Pig()
    
    #peo、dog、pig都是动物,只要是动物肯定有talk方法
    #于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
    peo.talk()
    dog.talk()
    pig.talk()
    
    #更进一步,我们可以定义一个统一的接口来使用
    def func(obj):
        obj.talk()
    

    若想通过父类控制子类:

    '''
    通过abc模块,我们可以控制子类必须实现父类的方法,若无父类的方法就会报错。
    '''
    # 父类有的功能,子类一定有
    import abc
    
    class Animal(metaclass=abc.ABCMeta):
        @abc.abstractmethod
        def speak(self):
            pass
    
        @abc.abstractmethod
        def run(self):
            pass
    
    # Animal()  # Animal的作用是用来制定标准的
    
    class People(Animal):
        def speak(self):
            print("啊啊啊啊")
    
        def run(self):
            print("咻咻咻...")
    
    class Dog(Animal):
        def giao(self):
            print("汪汪汪")
    
    class Pig(Animal):
        def heheng(self):
            print("哼哼哼")
    
    peo1=People()
    d1=Dog()
    p1=Pig()
    
    peo1.jiao()
    d1.giao()
    p1.heheng()
    

    此时的Animal类是无法实例化的,此时的作用仅仅是为了制定标准。虽然我们通过父类对子类施加了编写限制,但是此时Animal类仅仅只是为了制定标准而存在,我们付出了继承一个类的代价,然而我们完全可以自己私下约定好,每个类中必须有的标准,同样能够实现这个效果,所以更推荐私下约定,因为继承越多,程序的耦合就越重。
    自己私下约定好,减少耦合,就是鸭子类型

    四、python一切皆对象

    python当中使用的所有方法,都是实例化出来的方法,也就是对象,我们在pycharm中使用方法时,代码提示会有一个self的参数,其实就是对象,从我们学习python开始,就在使用对象。对于python一切皆对象的文章有很多,也有很多的例子,长篇大论容易使人搞懵。其实在我们了解了对象之后,就可以理解我们之前使用的python内置方法的原理了。

    五、面向对象高级(就是一堆内置方法)

    可前往该博客查看常用的方法:
    https://www.cnblogs.com/linhaifeng/articles/6204014.html

    六:反射

    反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

    对于任意一个类,都可以知道这个类的所有属性和方法;
    对于任意一个对象,都能够调用他的任意方法和属性。
    这种动态获取程序信息以及动态调用对象的功能称为反射机制。

    在python中实现反射非常简单,在程序运行过程中,如果我们获取一个不知道存有何种属性的对象,若想操作其内部属性,可以先通过内置函数dir来获取任意一个类或者对象的属性列表,列表中全为字符串格式

    class People:
        def __init__(self,name,age,gender):
            self.name=name
            self.age=age
            self.gender=gender
    
    obj=People('egon',18,'male')
    dir(obj) # 列表中查看到的属性全为字符串
    ------------------
    [......,'age', 'gender', 'name']
    

    接下来就是想办法通过字符串来操作对象的属性了,这就涉及到内置函数hasattr、getattr、setattr、delattr的使用了(Python中一切皆对象,类和对象都可以被这四个函数操作,用法一样)

    lass Teacher:
        def __init__(self,full_name):
            self.full_name =full_name
    
    t=Teacher('Egon')
    
    # hasattr(object,'name')
    hasattr(t,'full_name') # 按字符串'full_name'判断有无属性t.full_name
    
    # getattr(object, 'name', default=None)
    getattr(t,'full_name',None) # 等同于t.full_name,不存在该属性则返回默认值None
    
    # setattr(x, 'y', v)
    setattr(t,'age',18) # 等同于t.age=18
    
    # delattr(x, 'y')
    delattr(t,'age') # 等同于del t.age
    
  • 相关阅读:
    Redis自定义动态字符串(sds)模块(二)
    Redis自定义动态字符串(sds)模块(一)
    HTML入门1—HTML基础学习
    selenium安装及官方文档
    selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH. 错误处理方法
    python--requests库 安装及简单使用
    AttributeError: module 'requests' has no attribute 'get' 遇到了这个错误,是因为我把python关键字做了包名。。。
    python 笔记2:python语法基础
    Fiddler-3 Fiddler抓包-手机端配置
    Fiddler-2 Fiddler抓包原理
  • 原文地址:https://www.cnblogs.com/chiyun/p/14066300.html
Copyright © 2020-2023  润新知