Python 中的面向接口编程

”面向接口编程“写 Java 的朋友耳朵已经可以听出干茧了吧,当然这个思想在 Java 中非常重要,甚至几乎所有的编程语言都需要,毕竟程序具有良好的扩展性、维护性谁都不能拒绝。

最近无意间看到了我刚开始写 Python 时的部分代码,当时实现的需求有个很明显的特点:

不同对象具有公共的行为能力,但具体每个对象的实现方式又各不相同。

说人话就是商户需要接入平台,接入的步骤相同,但具体实现不同。

作为一个”资深“ Javaer,需求还没看完我就洋洋洒洒的把各个实现类写好了:

当然最终也顺利实现需求,甚至把组里一个没写过 Java 的大哥唬的一愣一愣的,

不过事后也给我吐槽:

你这设计是不错,但是感觉好复杂,跟代码时要找到真正的业务逻辑(实现类)得绕几圈。

截止目前 Python 写多了,我总算是能总结他的感受:就是不够 Pythonic。

虽说 Python 没有类似 Java 这样的 Interface 特性,但作为面向对象的高级语言也是支持继承的;

在这里我们也可以利用继承的特性来实现面向接口编程:

class Car:

def run(self):

pass

class Benz(Car):

def run(self):

print("benz run")

class BMW(Car):

def run(self):

print("bwm run")

def run(car):

car.run()

if __name__ == "__main__":

benz = Benz()

bmw = BMW()

run(benz)

run(bmw)

代码非常简单,在 Python 中也没有类似于 Java 中的 extends 关键字,只需要在类声明末尾用括号包含基类即可。

这样在每个子类中就能单独实现业务逻辑,方便扩展和维护。

类型检查

由于 Python 作为一个动态类型语言,无法做到 Java 那样在编译期间校验一个类是否完全实现了某个接口的所有方法。

为此 Python 提供了解决办法,那就是 abc(Abstract Base Classes) ,当我们将基类用 abc 声明时就能近似做到:

import abcclass Car(abc.ABC):    @abc.abstractmethod

def run(self):

pass

class Benz(Car):

def run(self):

print("benz run")

class BMW(Car):

pass

def run(car):

car.run()

if __name__ == "__main__":

benz = Benz()

bmw = BMW()

run(benz)

run(bmw)

一旦有类没有实现方法时,运行期间便会抛出异常:

bmw = BMW()

TypeError: Can't instantiate abstract class BMW with abstract methods run

虽然无法做到在运行之前(毕竟不需要编译)进行校验,但有总比没有好。

鸭子类型

以上两种方式看似已经毕竟优雅的实现面向接口编程了,但实际上也不够 Pythonic。

在继续之前我们先聊聊接口的本质到底是什么?

在 Java 这类静态语言中面向接口编程是比较麻烦的,也就是我们常说的子类向父类转型,因此需要编写额外的代码。

带来的好处也是显而易见,只需要父类便可运行。

但我们也不必过于执着于接口,远程桌面它本身只是一个协议、规范,并不特指 Java 中的 Interface,甚至有些语言压根没有这个关键字。

动态语言的特性也不需要强制校验是否实现了方法。

在 Python 中我们可以利用鸭子类型来优雅的实现面向接口编程。

在这之前先了解下鸭子类型,借用维基百科的说法:

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

我用大白话翻译下就是:

即便两个完全不想干的类,如果他们都实现了相同的方法,那就可以把他们当做同一类型的类来使用。

举个简单例子:

class Order:

def create(self):

pass

class User:

def create(self):

pass

def create(obj):

obj.create()

if __name__ == "__main__":

order = Order()

user = User()

create(order)

create(user)

这里的 order 和 user 本身完全没有关系,只是他们都有相同方法,又得益于动态语言没法校验类型的特点,所以完全可以在运行的时候认为他们是同一种类型。

因此基于鸭子类型,之前的代码我们可以稍作简化:

class Car:

def run(self):

pass

class Benz:

def run(self):

print("benz run")

class BMW:

def run(self):

print("bwm run")

def run(car):

car.run()

if __name__ == "__main__":

benz = Benz()

bmw = BMW()

run(benz)

run(bmw)

因为在鸭子类型中我们在意的是它的行为,而不是他们的类型;所以完全可以不用继承便可以实现面向接口编程。

总结

我觉得平时没有接触过动态类型语言的朋友,在了解完这些之后会发现新大陆,就像是 Python 老手第一次使用 Java 时;虽然觉得语法啰嗦,但也会羡慕它的类型检查、参数验证这类特点。

(0)

相关推荐

  • 第10天:Python 类与对象

    在刚接触编程时,我们就了解到编程界有两大思想:面向过程与面向对象,Python 就是一门面向对象的语言,如果你了解过面向对象的思想,自然就知道面向对象思想包含两个基本概念:类与对象 ,下面我们就一起详 ...

  • 想要利用Python快速爬取整站图片?速进(附完整代码)

    目录 一. 爬取前的准备 二. 查看网页 三. 分析与实现 1. 先确定我们所要爬取内容的具体位置2. 存储的具体实现 (`在pipelines中处理`)3. 更新完善源码 四. 代码   快速爬取整 ...

  • Python学习—面向对象编程基础篇

    python面向对象编程已经学完了,有必要进行一下记录总结,加深一下理解,不然似懂非懂容易忘记:面向对象的知识点很多,其中面向对象的高级篇:元类,需要另外一篇博客来写,最后还要手撸一个简单版本的ORM ...

  • opencv和Python有什么不同?基础分析!

    Python不用过多的介绍,大家都比较了解它,它是一门高级的.面向对象的编程语言,那么它与opencv有什么不同呢?它们之间的区别是什么?我想很多人对它们都有所好奇吧,接下来我们一起来了解一下. 首先 ...

  • 设计模式----------工厂(Factory)模式

    作用 实现了创建者和调用者分离. 工厂模式核心/本质: 实例化对象不在使用new,而是用工厂方法代替. 将选择实现类,创建对象统一管理和控制,从而实现调用者和我们实现类解耦 工厂模式详细分类 1.简单 ...

  • 翻译:《实用的Python编程》04

    翻译:<实用的Python编程>04_01_Class 原创codists2021-03-07 14:31:34 4.1 类 本节介绍 class 语句以及创建新对象的方式. 面向对象编程 ...

  • Python与其他编程语言有什么不同?

    现在主流的编程语言有很多种,其中包含Python.Java.C++.PHP等编程语言,那么为什么这么多语言大家选择学Python呢?Python和其他流行的编程语言有什么区别呢?我们一起来看看吧. 从 ...

  • C语言实现面向接口编程

    今天更新的文章,我相信是大伙喜欢的,来聊聊面向接口编程. 不是一直都吹嘘着面向对象编程吗?怎么今天又来一个面向接口编程,很多人要说我不讲武德了. 1 面向接口是啥? 不用慌,其实面向接口编程不是什么新 ...

  • 为什么我们要面向接口编程?!

    到底面向?编程 面向过程编程(Procedure Oriented.简称PO) 和 面向对象编程(Object Oriented.简称OO) 我们一定听过,然而实际企业级开发里受用更多的一种编程思想那 ...

  • 【Python核心编程笔记】一、Python中一切皆对象

    Python中一切皆对象 本章节首先对比静态语言以及动态语言,然后介绍 python 中最底层也是面向对象最重要的几个概念-object.type和class之间的关系,以此来引出在python如何做 ...

  • 【青少年编程】Python中的分号

    今天有小朋友问我以下的选择题: 关于Python赋值语句,以下选项中不合法的是() A. x = (y=1) B. x, y = y, x C. x = y = 1 D. x = 1; y = 1 这 ...

  • Python中的函数式编程教程,学会用一行代码搞定所有内容

    https://m.toutiao.com/is/JEUURVQ/ 前言 在本文中,您将了解什么是函数范型,以及如何在Python中使用函数式编程.在Python中,函数式编程中的map和filter ...

  • Python 中的函数装饰器和闭包

    函数装饰器可以被用于增强方法的某些行为,如果想自己实现装饰器,则必须了解闭包的概念. 装饰器的基本概念 装饰器是一个可调用对象,它的参数是另一个函数,称为被装饰函数.装饰器可以修改这个函数再将其返回, ...

  • Python中tuple和list的区别?基础学习!

    想必大家都知道,Python数据类型有很多种,其中有两个对象的写法非常相似,它就是tuple元组和list列表,让人傻傻分不清楚.那么你知道Python中tuple和list有什么区别吗?我们来看看具 ...

  • Python中缩进是什么?入门分享!

    众所周知,Python是一门独特的编程语言,它语法清晰.简单易学,而且Python是通过缩进来识别代码块的,因为一般的语言都是通过{}或者end来作为代码块标记. Python中缩进是什么? 要求严格 ...

  • python中的内置函数

    前言 本人只在csdn写博客 内置函数 介绍 一. 数学运算 abs()求绝对值函数 round() 近似取值 pow()求指数 divmod()求商和余数 max()求最大值和min()求最小值 s ...