用什么代替python中的接口/协议

时间:2015-03-13 00:24:00

标签: python interface protocols

我正在制作国际象棋游戏,并希望制作一个标准的接口/协议。 Python没有语言中的那些,所以我应该使用什么?我读了一些关于工厂的内容,但我不确定他们会如何提供帮助。提前致谢!

6 个答案:

答案 0 :(得分:9)

简而言之,您可能根本不需要担心它。由于Python使用duck typing - 另请参阅Wikipedia article以获得更广泛的定义 - 如果对象具有正确的方法,则它将起作用,否则将引发异常。

你可能有一个Piece基类,其中一些方法抛出NotImplementedError来表明它们需要重新实现:

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

或者,您可以使用isinstanceisubclass显式验证您收到的对象,以确保它具有所有正确的方法,或者它是Piece的子类。 请注意,可能不会考虑检查类型&#34; Pythonic&#34;某些人使用NotImplementedError方法或abc模块 - 如this very good answer中所述 - 可能更受欢迎。

您的工厂只需要生成具有正确方法的对象实例。

答案 1 :(得分:4)

Python 3.7中的新功能:

接口和协议的一些好处是在开发过程中使用IDE内置的工具进行类型提示,并使用静态类型分析在运行时检测错误。这样,静态分析工具可以告诉您何时检查代码,如果您尝试访问未在对象上定义的任何成员,而不是仅在运行时查找。

typing.Protocol类将添加到Python 3.7中作为&#34;结构子类型的机制。&#34;这背后的力量是它可以用作隐式基类。也就是说,任何具有与Protocol定义的成员匹配的成员的类都被认为是静态类型分析的子类。

PEP 544中给出的基本示例显示了如何使用它。

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

答案 2 :(得分:3)

我通常不在Python中使用接口,但如果必须这样做,则可以使用zope.interface。然后,您可以验证类或对象是否实现某些接口。此外,如果类没有实现所有方法或属性,它也会引发错误。 Twisted和其他框架使用此库。

答案 3 :(得分:2)

我用Python写了一个国际象棋游戏(用tkinter),我这样做是为了有一个Piece类,Queen / Knight /等。继承自Piece类,Player类,Square类和tkinter主循环的主程序类的类。每件作品都有一个颜色和位置,以及一种帮助为直线移动直到被阻挡的棋子生成移动设置的方法。 Specific Piece子类每个都包含一个确定其移动集的方法。 Square对象包含Piece和棋盘上方块的位置。

主程序类有一个__init__,用于设置棋盘,放置棋子,加载棋子图标和声音效果,以及初始化选项。 draw_board方法重新绘制板,重置所有块并重新绑定热键。然后还有各种其他方法来加载新图标,开始新游戏,设置音量,保存,撤消,城堡等。

我还没有使用版本10,但您可以获取版本9 here的源代码和资源。

您还可以查看开源Shane's Chess Information Database。我从未使用它,但它看起来很不错。

答案 4 :(得分:1)

尽管Python是动态的,可以使用duck-typing,但仍然可以实现Java和C#调用&#34;接口&#34;。这是通过声明一个抽象基类来完成的。 https://docs.python.org/2/library/abc.htmlhttps://docs.python.org/3.4/library/abc.html

定义ABC时,将所有类似接口的方法放入其中,并在其正文中放置passraise NotImplementedError。子类继承自ABC并覆盖这些方法,就像任何其他子类重写父类方法一样。 (由于Python具有多重继承,因此它们可以从您的ABC以及您喜欢的任何其他类继承。)

答案 5 :(得分:0)

Python的优点是不需要接口。由于鸭子输入,您可以创建几个具有相同方法签名的类:

class Queen:
  def move(self, x, y):
    #do stuff

class Pawn:
  def move(self, x, y):
    # do stuff

这些类的实例可以互换使用:

def make_move(piece, x, y):
  piece.move(x, y)

q = Queen()
make_move(q, 0, 0)
p = Pawn()
make_move(p, 4, 5)

请注意,对于完全成熟的国际象棋游戏,上述绝不是一个好的设计。它仅用于说明目的。