day30-mixins机制,派生,鸭子类型

一、mixins机制

多继承的正确打开方式:mixins机制
mixins机制核心:就是在多继承背景下尽可能地提升多继承的可读性
ps:让多继承满足人的思维习惯=》什么"是"什么

class Vehicle:
    pass

class FlyMixin:
    def fly(self):
        pass

class CivilAircraft(FlyMixin,Vehicle):  # 民航飞机
    pass

class Helicopter(FlyMixin,Vehicle):  # 直升飞机
    pass

class Car(Vehicle):  # 汽车并不会飞,但按照上述继承关系,汽车也能飞了
    pass


import socketserver
# 补充:通常Mixin结果的类放在左边

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

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

class OldboyPeople:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

    def f1(self):
        print('%s say hello' %self.name)


class Teacher(OldboyPeople):
    def __init__(self,name,age,sex,level,salary):
        OldboyPeople.__init__(self,name,age,sex)

        self.level = level
        self.salary=salary

tea_obj=Teacher('egon',18,'male',10,3000)
print(tea_obj.__dict__)

方式二:super()调用父类提供给自己的方法=》严格依赖继承关系
调用super()会得到一个特殊的对象,该对象会参照发起属性查找的那个类的mro,去当前类的父类中找属性

ps:这里强调下,是发起属性查找的类的mro云查找父类,在mro中假如b在a的后面的话,不管了是不是工的父类,都当做父类来看,去到了里去查找对应方法

class OldboyPeople:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

    def f1(self):
        print('%s say hello' %self.name)


class Teacher(OldboyPeople):
    def __init__(self,name,age,sex,level,salary):
        # super(Teacher,self).__init__(name,age,sex)
        super().__init__(name,age,sex) # 调用的是方法,自动传入对象

        self.level = level
        self.salary=salary

# print(Teacher.mro())
tea_obj=Teacher('egon',18,'male',10,3000)
print(tea_obj.__dict__)
super()案例
class A:
    def test(self):
        print('from A')
        super().test()

class B:
    def test(self):
        print('from B')

class C(A,B):
    pass


obj=C()
obj.test()

print(C.mro())
比如 在这个案例中obj的c类发起,即从c开始,查找c的mro,即
cab的顺序,a中有test所以打印  from a,再从发起查找test,
到b中查找test方法,打印from b

三、多态

1、什么多态:同一事物有多种形态

class Animal:
    pass

class People(Animal):
    pass

class Dog(Animal):
    pass

class Pig(Animal):
    pass

2、为何要有多态=》多态会带来什么样的特性,多态性
多态性指的是可以在不考虑对象具体类型的情况下而直接使用对象

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)

没有关系也可进行调用


print('hello'.__len__())
print([1,2,3].__len__())
print({'a':1,'b':2}.__len__())

def my_len(val):
return val.__len__()

print(my_len('hello'))
print(my_len([1,2,3]))
print(my_len({'a':1,'b':2}))

len('hello')
len([1,2,3])
len({'a':1,'b':2})

python自带的len方法即这样

 

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()
obj1.write()

obj2.read()
obj2.write()

obj3.read()
obj3.write()

上面这个是linux系统为例,把所有形式的东西全比做文件,都有读写两种操作,大大的提高了代码的可维护性与拓展性能,

拿到即可调用读写两种操作功能

 

# 了解:
import abc

class Animal(metaclass=abc.ABCMeta): # 统一所有子类的标准
    @abc.abstractmethod
    def say(self):
        pass

# obj=Animal() # 不能实例化抽象类自己

class People(Animal):
    def say(self):
        pass

class Dog(Animal):
    def say(self):
        pass

class Pig(Animal):
    def say(self):
        pass

#
# obj1=People()
# obj2=Dog()
# obj3=Pig()

四、绑定方法与非绑定方法

一:绑定方法:特殊之处在于将调用者本身当做第一个参数自动传入
1、绑定给对象的方法:调用者是对象,自动传入的是对象
2、绑定给类的方法:调用者类,自动传入的是类

import settings

class Mysql:
    def __init__(self,ip,port):
        self.ip=ip
        self.port=port

    def func(self):
        print('%s:%s' %(self.ip,self.port))

    @classmethod # 将下面的函数装饰成绑定给类的方法
    def from_conf(cls):
        print(cls)
        return cls(settings.IP, settings.PORT)

# obj1=Mysql('1.1.1.1',3306)

obj2=Mysql.from_conf()
print(obj2.__dict__)
*************
settings.py 
IP='127.0.0.1'
PORT=3306
*************

调用时会自动传入对应对象名或者类名

二:非绑定方法-》静态方法:
没有绑定给任何人:调用者可以是类、对象,没有自动传参的效果

class Mysql:
    def __init__(self,ip,port):
        self.nid=self.create_id()
        self.ip=ip
        self.port=port

    @staticmethod # 将下述函数装饰成一个静态方法
    def create_id():
        import uuid
        return uuid.uuid4()

    @classmethod
    def f1(cls):
        pass

    def f2(self):
        pass
obj1=Mysql('1.1.1.1',3306)
print(Mysql.create_id)
print(Mysql.f1)
print(obj1.f2)

 

posted @ 2020-04-11 12:32  学海无涯苦中作乐  阅读(164)  评论(0编辑  收藏  举报