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)



# # ======= 掌握 =======
# 下周:反射
 

猜你喜欢

转载自www.cnblogs.com/2722127842qq-123/p/12677747.html