Python 什么';是“;针对接口而不是对象”;编写代码;?
灵感来源于 “针对接口而不是对象编写代码”这句话在Python中有什么意义吗 我正在寻找类似于中的答案,但有Python片段和想法。在Python中,“针对接口而不是对象编写代码”没有字面意义,因为该语言没有接口功能。粗略的Python等价物是“使用duck typing”。如果您想查看对象是否是duck,换句话说,您应该检查它是否有Python 什么';是“;针对接口而不是对象”;编写代码;?,python,oop,interface,inversion-of-control,Python,Oop,Interface,Inversion Of Control,灵感来源于 “针对接口而不是对象编写代码”这句话在Python中有什么意义吗 我正在寻找类似于中的答案,但有Python片段和想法。在Python中,“针对接口而不是对象编写代码”没有字面意义,因为该语言没有接口功能。粗略的Python等价物是“使用duck typing”。如果您想查看对象是否是duck,换句话说,您应该检查它是否有quack()方法,或者最好尝试quack()并提供适当的错误处理,而不是测试它是否是duck的实例 Python中常见的duck类型有文件(实际上是类似文件的对象
quack()
方法,或者最好尝试quack()
并提供适当的错误处理,而不是测试它是否是duck
的实例
Python中常见的duck类型有文件(实际上是类似文件的对象)、映射(类似dict的对象)、可调用(类似函数的对象)、序列(类似列表的对象)和可重用(可以迭代的对象,可以是容器或生成器)
例如,想要一个文件的Python特性通常会乐于接受一个实现它所需要的file
方法的对象;它不需要从文件
类派生。例如,要将对象用作标准输出,它需要的主要内容是write()
方法(以及flush()
和close()
,它们实际上不需要做任何事情)。类似地,可调用的对象是具有\uuu call\uuu()
方法的任何对象;它不需要从函数类型派生(实际上,您不能从函数类型派生)
你应该采取类似的方法。检查要对对象执行的操作所需的方法和属性。更好的是,记录您的期望,并假设调用代码的人不是一个十足的傻瓜。(如果他们给你一个你不能使用的对象,他们肯定会很快从错误中找出答案。)只在必要时测试特定类型。有时这是必要的,这就是为什么Python会给您提供type()
、isinstance()
、和issubclass()
,但要小心使用它们
Python的duck类型相当于“针对接口而不是对象编写代码”,即建议您不要让代码过于依赖对象的类型,而是查看它是否具有所需的接口。不同之处在于,在Python中,“接口”只是指提供特定行为的对象的一组非正式属性和方法,而不是专门命名为interface
的语言构造
您可以在某种程度上使用
abc
模块对Python“接口”进行形式化,该模块允许您使用所需的任何条件声明给定类是给定“抽象基类”(接口)的子类,例如“它有属性color
,tail\u length
,和quack
,并且quack
是可调用的。”但这仍然比具有接口特性的静态语言要严格得多。要理解Python中的接口,必须理解duck类型。从Python的角度来看:
duck typing:一种编程风格,它不查看对象的类型以确定其是否具有正确的接口;相反,只需调用或使用方法或属性(“如果它看起来像duck,嘎嘎叫起来像duck,那么它必须是duck”)通过强调接口而不是特定类型,精心设计的代码通过允许多态替换来提高其灵活性。Duck类型避免使用type()或isinstance()进行测试。(但是,请注意,Duck类型可以用抽象基类进行补充。)相反,它通常使用hasattr()测试或EAFP编程
Python鼓励为接口编码,只是它们不是强制执行的,而是按照惯例。在Python中,诸如iterables、callables或file interface之类的概念非常普遍——以及依赖于map、filter或reduce等接口的内置接口。接口意味着您希望某些方法在对象之间出现并标准化;这是接口或抽象基类的要点,或者您想考虑的任何实现。 例如(Java),可能有一个对称加密接口,如下所示:
public interface cipher
{
public void encrypt(byte[] block, byte[] key);
public void decrypt(byte[] block, byte[] key);
}
然后您可以实现它:
public class aes128 implements cipher
{
public void encrypt(byte[] block, byte[] key)
{
//...
}
public void decrypt(byte[] block, byte[] key)
{
//...
}
}
然后可以这样声明一个对象:
cipher c;
我们在这里做了什么?我们已经创建了这个对象c
,它的类型必须与接口的类型匹配。c
可以引用任何与此接口匹配的对象,因此下一阶段将是:
c = new aes128();
您现在可以调用希望密码
具有的方法
这就是java。现在,您可以在python中执行以下操作:
class aes128(Object):
def __init__(self):
pass
def encrypt(self, block, key):
# here I am going to pass, but you really
# should check what you were passed, it could be
# anything. Don't forget, if you're a frog not a duck
# not to quack!
pass
如果您想使用此选项,并且不确定传递的对象是否正确,请尝试使用它:
c = aes128()
try:
c.encrypt(someinput, someoutput)
except:
print "eh? No encryption method?!"
在这里,如果c.encrypt无法处理已传递的内容(如果该方法存在),则依赖于c.encrypt的实现来提升。当然,如果c
是字符串类型,因此不是您所需的正确类型,它也将自动抛出,您将捕获(希望如此)
简言之,一种编程形式是键入的,这样您就必须遵守接口规则,另一种是说您甚至不需要写下它们,您只需相信如果没有错误,它就会工作
我希望这能告诉你两者之间的实际区别
“针对接口而不是对象编写代码”的Python版本是什么
正确的引语是“针对接口编程,而不是实现”。该原则在Python中的使用方式与它在Smalltalk中的使用方式相同,Smalltalk是它的起源语言
“针对接口而不是对象进行编码”这句话在Python中有什么意义吗
是的,它有同样的标志