首先,我们必须明确的一点是: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)

python中的接口和依赖注入的更多相关文章

  1. ASP.NET MVC中使用Unity进行依赖注入的三种方式

    在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...

  2. 在 mvc 4 中使用 unity 进行依赖注入

    在 mvc 4 中使用 unity 进行依赖注入 关于依赖注入的概念,这里就不再叙述了,我们用 mvc 4 结合 unity,使用构造函数来进行依 赖注入.具体步骤如下: 1. 首先建立 一个 mvc ...

  3. 我在项目中运用 IOC(依赖注入)--实战篇

    上一篇<我在项目中运用 IOC(依赖注入)--入门篇>只是简单的使用 IOC.实际项目使用 IOC 的情景复杂多了,比如说,构造函数有多个参数,有多个类继承同一个接口... Unity都有 ...

  4. IntelliJ IDEA中Mapper接口通过@Autowired注入报错的正确解决方式

    转载请注明来源:四个空格 » IntelliJ IDEA中Mapper接口通过@Autowired注入报错的正确解决方式: 环境 ideaIU-2018.3.4.win: 错误提示: Could no ...

  5. python 抽象类、抽象方法、接口、依赖注入、SOLIP

    1.程序设计原则:SOLIP SOLIP设计原则 1.单一责任原则(SRP) 一个对象对只应该为一个元素负责 2.开放封闭原则(OCP) 对扩展开放,修改封闭 3.里氏替换原则(LSP) 可以使用任何 ...

  6. 在ASP.NET MVC中使用Unity进行依赖注入的三种方式

    在ASP.NET MVC4中,为了在解开Controller和Model的耦合,我们通常需要在Controller激活系统中引入IoC,用于处理用户请求的 Controller,让Controller ...

  7. 细数Javascript技术栈中的四种依赖注入

    作为面向对象编程中实现控制反转(Inversion of Control,下文称IoC)最常见的技术手段之一,依赖注入(Dependency Injection,下文称DI)可谓在OOP编程中大行其道 ...

  8. AngularJS学习--- AngularJS中XHR(AJAX)和依赖注入(DI) step5

    前言:本文接前一篇文章,主要介绍什么是XHR,AJAX,DI,angularjs中如何使用XHR和DI. 1.切换工具目录 git checkout -f step- #切换分支 npm start ...

  9. laravel框架中所用到的依赖注入

    用Laravel开发前前后后有2个月左右了,之前一直写Java,就像找到Java和PHP之前的共同点,用Java的某些原理去理解PHP会发现还是有很多共通之处的.Java的依赖注入已经是一个很常见的概 ...

随机推荐

  1. Supervision 行为模式

    官方链接:http://erlang.org/doc/man/supervisor.html http://erlang.org/doc/design_principles/sup_princ.htm ...

  2. 如何让View一直沿z轴旋转

    #import <QuartzCore/QuartzCore.h>... CABasicAnimation *rotationAni = [CABasicAnimation animati ...

  3. Spring-更多DI的知识

    3.3.1 延迟初始化Bean 延迟初始化也叫做惰性初始化,指不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean. 配置方式很简单只需在<bean>标签上指定 “lazy-i ...

  4. UIView的背景渐变

    //绘制背景渐变 /* CGCradientCreateWithColorComponents函数需要四个参数: 色彩空间:(Color Space)这是一个色彩范围的容器,类型必须是CGColorS ...

  5. 搭建 FTP 文件服务vsftpd

    安装并启动 FTP 服务 安装 VSFTPD 使用 yum 安装 vsftpd: yum install vsftpd -y vsftpd 是在 Linux 上被广泛使用的 FTP 服务器,根据其[官 ...

  6. 如何通过phoenix中查看表的主键信息

    需求描述: 今天一个开发的同事让帮忙查看下表的主键列,在此记录下. 操作过程: 1.通过!primarykeys命令查看表的主键 !primarykeys SYNC_BUSINESS_INFO_BYD ...

  7. Java输入输出流(2)

    6. Java.IO流类库 1. io流的四个基本类 java.io包中包括了流式I/O所须要的全部类. 在java.io包中有四个基本类:InputStream.OutputStream及Reade ...

  8. MySQL<事务与存储过程>

    事务与存储过程 事务管理 事务的概念 谓的事务就是针对数据库的一组操作,它可以由一条或多条SQL语句组成,同一个事务的操作具备同步的特点,即事务中的语句要么都执行,要么都不执行. 事务的使用 开启事务 ...

  9. Linux环境下$开头的相关变量的含义

    $0 这个程式的执行名字$n 这个程式的第n个参数值,n=1..9$* 这个程式的所有参数,此选项参数可超过9个.$# 这个程式的参数个数$$ 这个程式的PID(脚本运行的当前进程ID号)$! 执行上 ...

  10. Android中的动画,选择器,样式和主题的使用

    一.动画: 1.动画的分类: 1).Tween动画:这种实现方式可以使视图组件移动.放大.缩小以及产生透明度的变化: 2).Frame动画:传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影. ...