Python 中的 Java 抽象/接口设计
我有许多类,它们都共享相同的方法,只是实现不同。在 Java 中,让每个类实现一个接口或扩展一个抽象类是有意义的。 Python 是否有与此类似的东西,或者我应该采取替代方法?
I have a number of classes which all share the same methods, only with different implementations. In Java, it would make sense to have each of these classes implement an interface or extend an abstract class. Does Python have anything similar to this, or should I be taking an alternative approach?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Python 中的接口背后有一个故事。多年来一直占据主导地位的原始态度是,你不需要它们:Python 遵循 EAFP(请求宽恕比请求许可更容易)原则。也就是说,您不需要指定您接受一个我不知道的 ICloseable 对象,您只需在需要时尝试
关闭
该对象,并且如果它引发异常,那么它也会引发异常。因此,本着这种心态,您只需单独编写类,然后按照您的意愿使用它们。如果其中之一不符合要求,你的程序就会抛出异常;相反,如果您使用正确的方法编写另一个类,那么它就会正常工作,而不需要指定它实现您的特定接口。
这工作得很好,但是接口有明确的用例,特别是对于较大的软件项目。 Python 的最终决定是提供
abc
模块,它允许您编写抽象基类,即除非重写其所有方法,否则无法实例化的类。您认为使用它们是否值得由您决定。介绍 ABC 的 PEP 比我解释得更好:
There's a bit of a story behind interfaces in Python. The original attitude, which held sway for many years, is that you don't need them: Python works on the EAFP (easier to ask forgiveness than permission) principle. That is, instead of specifying that you accept an, I don't know, ICloseable object, you simply try to
close
the object when you need to, and if it raises an exception then it raises an exception.So in this mentality you would just write your classes separately, and use them as you will. If one of them doesn't conform to the requirements, your program will raise an exception; conversely, if you write another class with the right methods then it will just work, without your needing to specify that it implements your particular interface.
This works pretty well, but there are definite use cases for interfaces, especially with larger software projects. The final decision in Python was to provide the
abc
module, which allows you to write abstract base classes i.e. classes that you can't instantiate unless you override all their methods. It's your decision as to whether you think using them is worth it.The PEP introducing ABCs explain much better than I can:
我对 Python 不太熟悉,但我大胆猜测它并不熟悉。
Java 中存在接口的原因是它们指定了一个契约。例如,实现 java.util.List 的东西保证有一个 add() 方法来符合接口上定义的一般行为。您可以在不知道其特定类的情况下放入 List 的任何(正常)实现,调用接口上定义的一系列方法并获得相同的一般行为。
此外,开发人员和编译器都可以知道这样的方法存在并且可以在相关对象上调用,即使他们不知道其确切的类。这是静态类型所需的一种多态性形式,以允许不同的实现类,但仍然知道它们都是合法的。
这在 Python 中实际上没有意义,因为它不是静态类型的。您不需要声明对象的类,也不需要让编译器相信您调用的方法确实存在。鸭子类型世界中的“接口”就像调用方法并相信对象可以正确处理该消息一样简单。
注意 - 欢迎更有知识的 Pythonista 进行编辑。
I'm not that familiar with Python, but I would hazard a guess that it doesn't.
The reason why interfaces exist in Java is that they specify a contract. Something that implements
java.util.List
, for example, is guaranteed to have anadd()
method to conforms to the general behaviour as defined on the interface. You could drop in any (sane) implementation of List without knowing its specific class, call a sequence of methods defined on the interface and get the same general behaviour.Moreover, both the developer and compiler can know that such a method exists and is callable on the object in question, even if they don't know its exact class. It's a form of polymorphism that's needed with static typing to allow different implementation classes yet still know that they're all legal.
This doesn't really make sense in Python, because it's not statically typed. You don't need to declare the class of an object, nor convince the compiler that methods you're calling on it definitely exist. "Interfaces" in a duck-typing world are as simple as invoking the method and trusting that the object can handle that message appropriately.
Note - edits from more knowledgeable Pythonistas are welcome.
也许你可以使用这样的东西。这将充当抽象类。因此每个子类都被迫实现 func1()
May be you can use something like this. This will act as an abstract class. Every subclass is thus forced to implement func1()
我在 3.5+ 中编写了一个 库 ,允许用 Python 编写接口。
要点是在
inspect
的帮助下编写一个类装饰器。然后你可以像这样编写类:
但是下面会给你一个错误:
I wrote a library in 3.5+ the allows for writing interfaces in Python.
The gist is to write a class decorator with the help of
inspect
.You can then write classes like this:
Below would give you an error though:
根据这篇文章 https://realpython.com/python-interface/ ,这就是你可以do
formal interface
:当抽象方法未被重写时会引发错误的正式接口。
according this articule https://realpython.com/python-interface/ , this is how you can do
formal interface
:formal interface that will raise errors when the abstract methods aren’t overridden.