在python中用什么替换接口/协议

在python中用什么替换接口/协议,python,interface,protocols,Python,Interface,Protocols,我正在做一个国际象棋游戏,想做一个标准的棋子接口/协议。Python语言中没有这些,那么我应该使用什么呢?我读了一些关于工厂的书,但我不确定它们会有什么帮助。提前谢谢 简而言之,你可能根本不需要担心它。由于Python使用—请参见更广泛的定义—如果对象具有正确的方法,它将简单地工作,否则将引发异常 您可能有一个Piece基类,其中一些方法抛出NotImplementedError,以指示它们需要重新实现: class Piece(object): def move(<args&g

我正在做一个国际象棋游戏,想做一个标准的棋子接口/协议。Python语言中没有这些,那么我应该使用什么呢?我读了一些关于工厂的书,但我不确定它们会有什么帮助。提前谢谢

简而言之,你可能根本不需要担心它。由于Python使用—请参见更广泛的定义—如果对象具有正确的方法,它将简单地工作,否则将引发异常

您可能有一个
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
类块(对象):
def移动(或。
请注意,某些人可能不认为检查类型是“Pythonic”的,最好使用
NotImplementedError
方法或
abc
模块(如中所述)


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

我用Python编写了一个国际象棋游戏(使用tkinter),我这样做的方式是有一个Piece类,Queen/Knight/等。这些类继承自Piece类,一个Player类,一个Square类,以及tkinter主循环的一个主程序类。每个Piece都有一个颜色和位置,以及一个方法来帮助生成直线移动直到阻塞的片段的移动集。特定的Piece子类每一个都包含一个确定其移动集的方法。正方形对象包含一块和正方形在板上的位置

主程序类有一个
\uuuu init\uuuuu
设置棋盘、放置棋子、加载棋子图标和音效,并初始化选项。一个
绘制棋盘的方法重新绘制棋盘,重置所有棋子并重新绑定热键。然后还有各种其他方法来加载新图标、启动新游戏、设置音量,保存、撤消、城堡等

我还没有完成版本10,但是您可以获得版本9的源代码和资产


您也可以查看开放源码。我从未使用过它,但它看起来很不错。

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

尽管Python是动态的,可以使用duck类型,但仍然可以实现Java和C所称的“接口”。这是通过声明一个抽象基类来实现的。或者


定义ABC时,将所有类似接口的方法放在其中,并在其主体中包含
pass
raisenotimplementederror
。子类继承自ABC并重写这些方法,就像任何其他子类重写父类方法一样。(因为Python有多重继承,所以它们可以从您的ABC以及您喜欢的任何其他类继承。)

Python 3.8中的新功能:

接口和协议的一些好处是在开发过程中使用内置于IDE中的工具进行类型暗示,以及在运行前检测错误的静态类型分析。这样,如果您试图访问对象上未定义的任何成员,而不是只有在运行时才能发现

Python3.8中添加了
typing.Protocol
类作为“结构子类型”的机制这背后的力量是它可以用作隐式基类。也就是说,任何具有与
协议
的定义成员匹配的成员的类,在静态类型分析中都被视为它的子类

中给出的基本示例说明了如何使用此功能

来自输入导入协议
类支持关闭(协议):
def关闭(自身)->无:
# ...
班级资源:
# ...
def关闭(自身)->无:
self.file.close()文件
self.lock.release()
def close_all(事物:Iterable[SupportsClose])->无:
对于事物中的事物:
结束
文件=打开('foo.txt')
资源=资源()
关闭所有([文件,资源])#好的!
close_all([1])#错误:“int”没有“close”方法

注意:Python 3.5+的backport
typing.Protocol

Python的妙处在于接口不是必需的。由于duck类型,您只需创建几个具有相同方法签名的类即可:

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)

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

Python中的接口有什么意义,因为它不能强制您实现所有的方法?接口对于静态类型的语言很重要,您希望强制继承类实现e接口。对于像python这样的动态语言,类或类的客户机可以查找函数。如果类有函数,它可以执行它,不管它是否继承了它。@MalikBrahimi是的,在python中它不能被强制执行,但接口还提供了一种记录应该实现什么方法的方式。更像是绅士协议。与ABC,这正是python所做的。好吧……这里遗漏的是直接告诉代码的读者,资源实现了名为SupportsClose的接口。在python中这可能吗?是的,一些程序可能会发现这一点,但当我阅读资源时,我想直接看到“啊,资源实现了名为SupportsClose的接口”…这在python中是可能的吗?是的,可以显式声明一个实现。然后请将其包含在您的示例中,或者至少提到两者都是可能的。因为您给出的示例是一个反模式。当我看到这一点时,我真的认为“python是垃圾”。现在显式声明