zoukankan      html  css  js  c++  java
  • mixins机制.md_super_多态_绑定_内置方法

    一:Python多继承的正确打开方式:mixins机制

    Mixins核心:在多继承背景下,尽可能地提升多继承的可读性

    ps:让多继承满足人的思维习惯 ==> 什么 是 什么

    # PI = 3.1415926

    二:例子

    class Vehicle:  # 交通工具
        def fly(self):
            print("I am flying")
    
    
    class CivilAircraft(Vehicle):  # 民航飞机
        pass
    
    
    class Helicopter(Vehicle):  # 直升飞机
        pass
    
    
    class Car(Vehicle):  # 汽车并不会飞,但按照上述继承关系,汽车也能飞了
        pass
    class Vehicle:  # 交通工具
        pass
    
    
    class Flyable:    # 新建一个类Flyable,只当做可飞行交通工具的父类
        def fly(self):
            print("I am flying")
    
    
    class CivilAircraft(Vehicle, Flyable):  # 民航飞机
        pass
    
    
    class Helicopter(Vehicle, Flyable):  # 直升飞机
        pass
    
    
    class Car(Vehicle):
        pass
      Python语言可没有接口功能,但是它可以多重继承。那Python是不是就该用多重继承来实现呢?是,也不是。说是,因为从语法上看,的确是通过多重继承实现的。说不是,因为它的继承依然遵守”is-a”关系,从含义上看依然遵循单继承的原则。
    
    class Vehicle:  # 交通工具
        pass
    
    
    class FlyableMixin:        # 加一个Mixin结尾,可以当做一个假父类混入区中
        def fly(self):
            print("I am flying")
    
    
    class CivilAircraft(Vehicle, FlyableMixin):  # 民航飞机
        pass
    
    
    class Helicopter(Vehicle, FlyableMixin):  # 直升飞机
        pass
    
    
    class Car(Vehicle):  # 汽车并不会飞,但按照上述继承关系,汽车也能飞了
        pass
    这里可以看到,CivilAircraft和Helicopter都继承了Vehicle,还有FlyableMixin,但是FlyableMixin,表示混入(mix-in),它告诉别人,这个类是作为功能添加到子类中,而不是作为父类,它的作用同Java中的接口。
    使用Mixin类实现多重继承要非常小心
        1.首先它必须表示某一种功能,而不是某个物品,如同Java中的Runnable,Callable等
        2.其次它必须责任单一,如果有多个功能,那就写多个Mixin类
        3.然后,它不依赖于子类的实现
        4.最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。

    在子类派生的新方法super()

    一:方式1

    指名道姓调用某一个类下的函数 ==> 不依赖于继承关系

    class OldboyPeople:
        school = 'OldBoy'
    
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def f1(self):
            print(f'{self.name} say hello')
    
    
    class Student(OldboyPeople):
        def choose_course(self):
            print('学生%s 正在选课' % self.name)
    
    
    class Teacher(OldboyPeople):
        #           老师的空对象,'egon',18,'male',3000,10
        def __init__(self, name, age, sex, salary, level):
            # 方式1:# 指名道姓地跟父类OldboyPeople去要__init__
            # OldboyPeople.__init__(self, name, age, sex)
            self.salary = salary
            self.level = level
    
        def score(self):
            print('老师 %s 正在给学生打分' % self.name)
    
    
    print(Teacher.mro())  # [<class '__main__.Teacher'>, <class '__main__.OldboyPeople'>, <class 'object'>]

    二:方式2

    super()调用父类提供给自己的方法 ==> 严格依赖继承关系

    class OldboyPeople:
        school = 'OldBoy'
    
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def f1(self):
            print(f'{self.name} say hello')
    
    
    class Student(OldboyPeople):
        def choose_course(self):
            print('学生%s 正在选课' % self.name)
    
    
    class Teacher(OldboyPeople):
        #           老师的空对象,'egon',18,'male',3000,10
        def __init__(self, name, age, sex, salary, level):
            # 方式2:# 调用super()会得到一个特殊的对象,该对象会参照当前类的mro,去当前类的父类里找属性
            super().__init__(name, age, sex)  # 调用的是方法,自动传入对象
            self.salary = salary
            self.level = level
    
        def score(self):
            print('老师 %s 正在给学生打分' % self.name)
    
    
    print(Teacher.mro())  # [<class '__main__.Teacher'>, <class '__main__.OldboyPeople'>, <class 'object'>]
    class A:
        def test(self):
            super().test()
    
    
    class B:
        def test(self):
            print('from B')
    
    
    class C(A, B):
        pass
    
    
    print(A.mro())  # [<class '__main__.A'>, <class 'object'>]
    print(B.mro())  # [<class '__main__.B'>, <class 'object'>]
    print(C.mro())  # 在代码层面A并不是B的子类,但从MRO列表来看,属性查找时,就是按照顺序C->A->B->object,B就相当于A的“父类”
    # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>,<class ‘object'>]
    
    obj = C()
    obj.test()  # 属性查找的发起者是类C的对象obj,所以中途发生的属性查找都是参照C.mro()
    # from B
    class A:
        def test(self):
            print('from A')
            super().test1()
    
    
    class B:
        def test1(self):
            print('from B')
    
    
    class C(A, B):
        def test1(self):
            print('from C')
    
    
    print(C.mro())  # 在代码层面A并不是B的子类,但从MRO列表来看,属性查找时,就是按照顺序C->A->B->object,B就相当于A的“父类”
    # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>,<class ‘object'>]
    
    obj = C()
    obj.test()  # 属性查找的发起者是类C的对象obj,所以中途发生的属性查找都是参照C.mro()

    三:使用须知

    super()和之前的方法不能混用,只能用其中一种

     

     

    多态

    一:什么是多态

    同一事物有多种形态

    二:为何要有多态 ==> 多态会带来什么样的特性,多态性

    多态性指的是:可以在不考虑对象的具体类型情况下 直接使用对象

    class Animal:
        def say(self):
            print('动物基本的发声...', end='')
    
    
    class People(Animal):
        def say(self):
            super().say()
            print('卧槽')
    
    
    class Dog(Animal):
        def say(self):
            super().say()
            print('汪汪汪')
    
    
    class Pig(Animal):
        def say(self):
            super().say()
            print('吼吼吼')
    
    
    obj1 = People()
    obj2 = Dog()
    obj3 = Pig()
    
    
    # obj1.say()  # 动物基本的发声...卧槽
    # obj2.say()  # 动物基本的发声...汪汪汪
    # obj3.say()  # 动物基本的发声...吼吼吼
    
    
    # 定义统一的接口,接收传入的动物对象
    def animal_say(animal):
        animal.say()
    
    
    animal_say(obj1)
    animal_say(obj2)
    animal_say(obj3)

    Python中len的精妙之处

    # len('hello')
    # len([1, 2, 3])
    # len({'name': 'xxq', 'age': 18})
    
    # print('hello'.__len__())
    # print([1, 2, 3].__len__())
    # print({'name': 'xxq', 'age': 18}.__len__())
    
    
    def my_len(val):
        return val.__len__()
    
    
    print(my_len('hello'))
    print(my_len([1, 2, 3]))
    print(my_len({'name': 'xxq', 'age': 18}))

    三:鸭子类型

    # Python推崇的是鸭子类型
    
    class Cpu:
        def read(self):
            print('cpu read')
    
        def write(self):
            print('cpu write')
    
    
    class 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()
    obj2.read()
    obj3.read()

    四:了解知识点

    import abc
    
    # 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
    class Animal(metaclass=abc.ABCMeta):  # 统一所有子类的方法
        @abc.abstractmethod     # 该装饰器限制子类必须定义有一个名为talk的方法
        def say(self):
            print('动物基本的发声...', end='')
    
    
    class People(Animal):   # 但凡继承Animal的子类都必须遵循Animal规定的标准
        pass
    
    
    class Dog(Animal):
        pass
    
    
    class Pig(Animal):
        pass
    
    
    obj1 = People()
    obj2 = Dog()
    obj3 = Pig()
    
    obj1.say()  # 动物基本的发声...卧槽
    obj2.say()  # 动物基本的发声...汪汪汪
    obj3.say()  # 动物基本的发声...吼吼吼
    
    # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化
    # TypeError: Can't instantiate abstract class People with abstract methods say
    
    class Animal(metaclass=abc.ABCMeta):  # 统一所有子类的方法
        @abc.abstractmethod
        def say(self):
            print('动物基本的发声...', end='')
    
    
    class People(Animal):
        def say(self):
            super().say()
            print('卧槽')
    
    
    class Dog(Animal):
        def say(self):
            super().say()
            print('汪汪汪')
    
    
    class Pig(Animal):
        def say(self):
            super().say()
            print('吼吼吼')
    
    
    obj1 = People()
    obj2 = Dog()
    obj3 = Pig()
    
    obj1.say()  # 动物基本的发声...卧槽
    obj2.say()  # 动物基本的发声...汪汪汪
    obj3.say()  # 动物基本的发声...吼吼吼



    绑定

    一:绑定方法:特殊之处在于 将调用者本身当做第一个参数 自动传入

    1.绑定给对象的方法:调用者是 对象,自动传入的是 对象

    class Mysql:
        def __init__(self, ip, port):
            self.ip = ip
            self.port = port
    
        def func(self):
            print(f'{self.ip} {self.port}')
    
    
    obj = Mysql('127.0.0.1', 3306)
    obj.func()      # 127.0.0.1 3306

    2.绑定给类的方法:调用者是 类,自动传入的是 类

    新的方法:

    setting.py

    IP = '127.0.0.1'
    PORT = 3306
    import settings
    
    
    class Mysql:
        def __init__(self, ip, port):
            self.nid = self.create_id()
            self.ip = ip
            self.port = port
    
        def func(self):
            print(f'{self.ip} {self.port}')
    
        @classmethod    # 绑定给类的方法
        def form_conf(cls):
            print(cls)
            return cls(settings.IP, settings.PORT)
    
        @staticmethod  # 将下述函数 装饰成一个静态方法
        def create_id():
            import uuid
            return uuid.uuid4()
    
        @classmethod
        def f1(cls):
            pass
    
        def f2(self):
            pass
    
    obj2 = Mysql.form_conf()    # <class '__main__.Mysql'>
    print(obj2.__dict__)        # {'nid': UUID('fb7015fb-8e6c-4c1e-9a24-241a7c3aff10'), 'ip': '127.0.0.1', 'port': 3306}

    二:非绑定方法

    没有绑定给任何人:调用者可以是类、对象,没有自动传参的效果

    class Mysql:
        def __init__(self, ip, port):
            self.ip = ip
            self.port = port
    
        @staticmethod  # 将下述函数 装饰成一个静态方法
        def create_id():
            import uuid
            return uuid.uuid4()
    
    
    obj1 = Mysql('1.1.1.1', 2208)
    
    # print(Mysql.create_id)  # <function Mysql.create_id at 0x037083D0>
    # print(obj1.create_id)   # <function Mysql.create_id at 0x037083D0>
    
    Mysql.create_id()
    obj1.create_id()
     
    内置方法
    # print(abs(-1))                 # 返回绝对值  # 1
    #
    # print(all([1, 2, 3, '']))      # 返回可迭代对象,有一个为0,None,空就是假的 # False
    # print(all([1, 2, 3, ]))        # 返回可迭代对象    # True
    #
    # print(any([]))                 # False
    #
    # print(bin(111))                # 0b1101111
    # print(oct(111))                # 0o157
    # print(hex(111))                # 0x6f
    #
    # print(bool(''))                # False
    
    # def func():
    #     pass
    
    
    # class Foo:
    #     pass
    
    
    # print(callable(Foo))            # True
    
    
    # print(chr(65))                    # A
    # print(ord('A'))                   # 65
    
    
    # # ======= 掌握 =======
    # class Foo:
    #     pass
    # obj = Foo()
    # obj.xxx = 111
    
    # print(dir(Foo))     # 可以查看可以.出来哪些属性     #['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
    
    # print(dir(obj))     # 可以查看可以.出来哪些属性     #['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'xxx']
    
    # print(divmod(1000,4))         #总数据量,每一页的数据量
    # 返回值:总页数,剩余数据       # (250, 0)
    
    # # ======= 掌握 =======
    # for i, v in enumerate(['a', 'b', 'c']):
    #     print(i, v)
    #
    # #  0 a
    # #  1 b
    # #  2 c
    
    # # ======= 掌握 =======
    # res = eval('1+2')       # eval就是执行字符串中的表达式
    # print(res)
    
    # # ======= 掌握 =======
    # 不可变集合
    # s = frozenset({1, 2, 3})
    # print(s)    # frozenset({1, 2, 3})
    
    # hash(不可变类型)
    
    # # ======= 掌握 =======
    # isinstance判断一个对象是不是一个类的实例
    # class Foo:
    #     pass
    #
    # obj = Foo()
    # print(isinstance(obj, Foo))     # True
    # print(isinstance([], list))     # True  # 推荐
    # print(type([]) is list)         # True  # 不推荐
    
    # # 10 ** 2 % 3
    # print(pow(10, 2, 3))        # 1
    
    # # 了解
    # print('aaa'.__repr__())  # 'aaa'
    
    # # round 四舍五入
    # print(round(1.545))    #  2
    # print(round(1.445))    #  1
    
    # # 切片
    # s = slice(1, 4, 2)  # 不常用
    # l1 = [1, 2, 3, 4]
    # l2 = [3, 2, 5, 9, 6, 7]
    #
    # print(l1[1:4:2])  # [2, 4]
    # print(l2[1:4:2])  # [2, 9]
    # print(l1[s])    # [2, 4]
    # print(l2[s])    #[2, 4]
    
    
    # # ======= 掌握 =======
    # # zip拉链函数 一个对一个,没有对应的就报错
    # v1 = 'hello'
    # v2 = [111, 222, 333, 444, 555]
    # res = zip(v1, v2)
    # print(list(res))    # [('h', 111), ('e', 222), ('l', 333), ('l', 444), ('o', 555)]
    
    
    # # ======= 掌握 =======
    # __import__()
    import time
    # import 'time'   # 报错
    # 变量名 = __import__('time')
    # x = __import__('time')
    # x.sleep(3)
    
    
    
    # # ======= 掌握 =======
    # 下周:反射
     
  • 相关阅读:
    Java容器学习之ArrayList
    Java容器学习之List
    个人感悟
    python_批量修改密码综评
    修改的一段递归文件代码
    showtimu
    20190321xlVBA_明细信息表汇总成数据表
    20190320xlVBA_考场座位设置
    RG
    wdVBA_替换删除选择题括号中的选项
  • 原文地址:https://www.cnblogs.com/2722127842qq-123/p/12677747.html
Copyright © 2011-2022 走看看