Python语言学习之Python 中的面向接口编程
小职 2021-01-19 来源 :「 crossoverJie」 阅读 554 评论 0

摘要:本文主要向大家介绍了Python语言学习之Python 中的面向接口编程,通过具体的内容向大家展现,希望对大家Python语言的学习有所帮助。

本文主要向大家介绍了Python语言学习之Python 中的面向接口编程,通过具体的内容向大家展现,希望对大家Python语言的学习有所帮助。

Python语言学习之Python 中的面向接口编程

前言

 

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

 

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

 

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

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

 

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

 Python语言学习之Python 中的面向接口编程

 

 

当然最终也顺利实现需求,甚至把组里一个没写过 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 abc

class 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 时;虽然觉得语法啰嗦,但也会羡慕它的类型检查、参数验证这类特点。

 

动静语言之争这里不做讨论了,各有各的好,鞋好不好穿只有自己知道。

 

随便提一下其实不止动态语言具备鸭子类型,有些静态语言也能玩这个骚操作,感兴趣下次再介绍。



关注“职坐标在线”(Zhizuobiao_Online)公众号,免费获取学习教程资料、技术就业咨询

Python语言学习之Python 中的面向接口编程

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程