Python Duck类型(或自动接口)

现在,我全职使用python ,对它的工作方式(或某些人的python禅)有更深入的了解。 每当我发现自己的日常传奇时,都会让我大吃一惊的是鸭子打字。 老实说,它不是python独有的功能,因为几乎每种动态语言都具有这种行为。 但是,很好,我喜欢Python。

如果某些读者不知道它是什么,鸭子类型是类型系统的功能,其中类的语义由其对某种消息(方法或属性)的响应能力决定。 典型的例子(以及名称背后的原因)是鸭子测试如果它看起来像鸭子,像鸭子一样游泳,像鸭子一样嘎嘎叫,那可能就是鸭子。

class Duck:
def quack():
print('Quack!')
class Goose:
def quack():
print('Quack')
Goose().quack()
>> Quack!
Duck().quack()
>> Quack!

好的,但是有什么收获呢? 这里没有新内容。 是的,没有新内容。 我试图展示的是这种行为对系统体系结构的影响。 我主张这是一个很好的暗示。 让我解释。

想象一下一个名为Car的类:

class Car:
def __init__(self, engine):
self.engine = engine
   def run():
self.engine.turn_on()

这是依赖注入的经典示例。 我的汽车类接收一个引擎实例,并在run方法中使用它,在该方法中调用turn_on方法。 请注意,我的汽车不依赖于引擎的任何具体实现。 而且我不会导入任何其他类型! 仅使用响应Turn_on消息的依赖项注入实例。 我可以说我的班级Car取决于接口。 但是我不必声明它。 这是一个自动界面!

在没有鸭子类型的语言中,我可能必须声明一个名为IEngine的显式接口,实现(例如EngineV1 ),并显式定义Car参数为IEngine的实现。

interface IEngine {
void turnOn();
}
public class EngineV1 implements IEngine {
public void turnOn() {
// do something here
}
}
public class Car {
public Car(IEngine engine) {
this.engine = engine;
}
    public void run() {
this.engine.turnOn();
}
}

啊! 多少代码。

因此,您可以看到效果是相同的。 在这两种情况下,我的班级Car都取决于接口。 但是在第一种情况下,代码更少,我不需要显式实现接口。 如果定义方法turn_on,则已经实现。

弱点

我在这里看到两个问题。

  1. 胖界面

首先是鼓励膨胀 。 由于我们未明确定义API,因此这可能导致接口中包含过多的粒度方法。

2.未命名的依赖项

由于我们不知道类所依赖的接口的名称,因此我们没有自动依赖树。 因此,所有依赖项注入框架都必须以某种方式解决依赖项解析。

例如, Injector lib有义务实现Keys的概念,以允许自动解析依赖关系树。 用喷射器的术语来说,键不过是命名/标识类实现的接口的一种方法。

结论

我不认为鸭子的输入是故意设计的,以具有这种行为。 我什至根本不认为鸭子类型是故意用某种语言设计的,而是它是那些类型系统的动态特性的副作用。 但是有趣的是,它可以为系统设计和体系结构带来简洁性和低耦合性。

From: https://hackernoon.com/python-duck-typing-or-automatic-interfaces-73988ec9037f

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值