Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 什么';是“;针对接口而不是对象”;编写代码;?_Python_Oop_Interface_Inversion Of Control - Fatal编程技术网

Python 什么';是“;针对接口而不是对象”;编写代码;?

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类型有文件(实际上是类似文件的对象

灵感来源于

“针对接口而不是对象编写代码”这句话在Python中有什么意义吗

我正在寻找类似于中的答案,但有Python片段和想法。

在Python中,“针对接口而不是对象编写代码”没有字面意义,因为该语言没有接口功能。粗略的Python等价物是“使用duck typing”。如果您想查看对象是否是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中有什么意义吗

是的,它有同样的标志