zoukankan      html  css  js  c++  java
  • python中的接口和依赖注入

      首先,我们必须明确的一点是:python里无接口类型,定义接口只是一个人为规定,在编程过程自我约束

    • python的类是可以写任意个方法的

    • 定义一个接口对继承类进行约束,接口里有什么方法,继承类就必须有什么方法,接口中不能任何功能代码

    class Interface:
        
        def f1(self):
            '''
            to do something
            :return: 
            '''
    
    class Something(Interface):
        
        def f1(self):
            print('to do something...')
        
        def f2(self):
            print('to do other..')
    

      在其他的语言里,比如Java,继承类没有重写接口方法是会报错的,而在python里不会,就是因为python没这个类型,所以只是在我们编程过程的一个规定,以I开头的类视为接口

    class IOrderRepository:
    
        def fetch_one_by(self,nid):
            raise Exception('子类中必须实现该方法')
    
    class Something(IOrderRepository):
    
        def fet_one_by(self,nid):
            print('查查查数据....')
    

    抽象类,抽象方法

    • 抽象类,可以说是类和接口的混合体,既可以定义常规方法,也可以约束子类的方法(抽象方法)

    import abc
    
    #抽象类
    class Foo(metaclass=abc.ABCMeta):
    
        def f1(self):
            print('f1')
    
        #抽象方法
        @abc.abstractmethod
        def f2(self):
            '''
            打印f2
            '''
    
    class Bar(Foo):
    
        def f2(self):
            print('f2')
    
        def f3(self):
            print('f3')
    
    b = Bar()
    b.f1()
    b.f2()
    b.f3()
    

    依赖注入

    首先我们先看一个普通的类:

    class Foo:
        def __init__(self):
            self.name = 'alex'
        
        def f1(self):
            print(self.name)
    
    •  首先要明确的是,在python里,一切事物皆为对象

    • 而所有的类都是对象,默认是由type创建

    创建类的执行流程:

    • 遇到class关键词,执行type的__init__方法,创建Foo类这个对象

    • 遇实例化对象(obj=Foo()),执行type里的__call__方法

    1. 在call方法里调用Foo类的__new__方法(负责创建对象)
    2. 执行Foo类的__init__方法(初始化)

    了解其中的原理,我们就可以在__call__里面大做文章啦

    class MyType(type):
    
        def __call__(cls,*args,**kwargs):
            obj = cls.__new__(cls,*args,**kwargs)
            print('在这里面..')
            print('==========================')
            print('来咬我呀')
            obj.__init__(*args,**kwargs)
            return obj
    
    
    class Foo(metaclass=MyType):
    
        def __init__(self):
            self.name = 'alex'
    
    f = Foo()
    print(f.name)
    

       如果要熟练应用依赖注入,我还要弄懂一个概念,那就是组合:组合的目的就是解耦,减少依赖性,原来以某个具体的值或对象传入到内部改成以参数的形式传入

      比如:在实例Bar对象时,封装Foo对象,实例Foo对象封装Head对象,就用参数的形式传入到构造方法里

    class Mapper:
    
        #在字典里定义依赖注入关系
        __mapper_relation = {}
    
        #类直接调用注册关系
        @staticmethod
        def register(cls,value):
            Mapper.__mapper_relation[cls] = value
    
        @staticmethod
        def exist(cls):
            if cls in Mapper.__mapper_relation:
                return True
            return False
    
        @staticmethod
        def get_value(cls):
            return Mapper.__mapper_relation[cls]
    
    class MyType(type):
        def __call__(cls,*args,**kwargs):
            obj = cls.__new__(cls,*args,**kwargs)
            arg_list = list(args)
            if Mapper.exist(cls):
                value = Mapper.get_value(cls)
                arg_list.append(value)
            obj.__init__(*arg_list,**kwargs)
            return obj
    
    class Head:
    
        def __init__(self):
            self.name = 'alex'
    
    class Foo(metaclass=MyType):
    
        def __init__(self,h):
            self.h = h
    
        def f1(self):
            print(self.h)
    
    class Bar(metaclass=MyType):
    
        def __init__(self,f):
            self.f = f
    
        def f2(self):
            print(self.f)
    
    Mapper.register(Foo,Head())
    Mapper.register(Bar,Foo())
    
    
    b = Bar()
    print(b.f)
    
  • 相关阅读:
    聚合查询2.0
    分词器2.0
    搜索和查询2.0
    Mapping2.0
    索引的CRUD2.0
    微信小程序:一则iOS下用video播放mp4文件问题排查
    flutter——android报错Manifest merger failed : Attribute application@allowBackup value=(false)
    HTML-meta
    HTML-实体
    html-vscode-liveServer
  • 原文地址:https://www.cnblogs.com/xinsiwei18/p/5937952.html
Copyright © 2011-2022 走看看