Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What to use in replacement of an interface/protocol in python

I am making a chess game and wanted to make a standard piece interface/protocol. Python does not have those in the language, so what am I supposed to use? I read a bit about factories, but I'm not sure how they would help. Thanks in advance!

like image 917
Big_Mac Avatar asked Mar 13 '15 00:03

Big_Mac


People also ask

What is interface equivalent in Python?

Since Python does support multiple inheritance, you can easily emulate the equivalence of interfaces. What that means is that interfaces are implicit in Python : if an object conforms to an interface, you can use it, no need to declare it like you would in statically typed languages such as Java or C# .

Why interfaces are not used in Python?

Interfaces are not natively supported by Python, although abstract classes and abstract methods can be used to go around this. At a higher perspective, an interface serves as a template for class design. Interfaces create methods in the same way that classes do, but unlike classes, these methods are abstract.

Are interfaces necessary in Python?

As a project grows, the need for a formal Python interface becomes more important as it becomes more difficult to infer return types. This ensures that the concrete class, which implements the interface, overwrites the abstract methods.

What protocols are used by Python?

Protocol class was added to Python 3.8 as part of PEP 544 as a mechanism for “structural subtyping.” Basically, it is used to define an interface class that acts as a blueprint for designing other classes. Like classes, interface classes define methods however Unlike classes, these methods are abstract methods.


2 Answers

New in Python 3.8:

Some of the benefits of interfaces and protocols are type hinting during the development process using tools built into IDEs and static type analysis for detection of errors before runtime. This way, a static analysis tool can tell you when you check your code if you're trying to access any members that are not defined on an object, instead of only finding out at runtime.

The typing.Protocol class was added to Python 3.8 as a mechanism for "structural subtyping." The power behind this is that it can be used as an implicit base class. That is, any class that has members that match the Protocol's defined members is considered to be a subclass of it for purposes of static type analysis.

The basic example given in PEP 544 shows how this can be used.

from typing import Protocol  class SupportsClose(Protocol):     def close(self) -> None:         # ...  class Resource:     # ...     def close(self) -> None:         self.file.close()         self.lock.release()  def close_all(things: Iterable[SupportsClose]) -> None:     for thing in things:         thing.close()  file = open('foo.txt') resource = Resource() close_all([file, resource])  # OK! close_all([1])     # Error: 'int' has no 'close' method 

Note: The typing-extensions package backports typing.Protocol for Python 3.5+.

like image 141
gooberwonder Avatar answered Sep 17 '22 18:09

gooberwonder


In short, you probably don't need to worry about it at all. Since Python uses duck typing - see also the Wikipedia article for a broader definition - if an object has the right methods, it will simply work, otherwise exceptions will be raised.

You could possibly have a Piece base class with some methods throwing NotImplementedError to indicate they need to be re-implemented:

class Piece(object):      def move(<args>):         raise NotImplementedError(optional_error_message)   class Queen(Piece):      def move(<args>):         # Specific implementation for the Queen's movements  # Calling Queen().move(<args>) will work as intended but   class Knight(Piece):     pass  # Knight().move() will raise a NotImplementedError 

Alternatively, you could explicitly validate an object you receive to make sure it has all the right methods, or that it is a subclass of Piece by using isinstance or isubclass. Note that checking the type may not be considered "Pythonic" by some and using the NotImplementedError approach or the abc module - as mentioned in this very good answer - could be preferable.

Your factory just has to produce instances of objects having the right methods on them.

like image 29
Vlad Avatar answered Sep 17 '22 18:09

Vlad