我正在制作国际象棋游戏,并希望制作一个标准的接口/协议。 Python没有语言中的那些,所以我应该使用什么?我读了一些关于工厂的内容,但我不确定他们会如何提供帮助。提前致谢!
答案 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
或者,您可以使用isinstance或isubclass显式验证您收到的对象,以确保它具有所有正确的方法,或者它是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.html或https://docs.python.org/3.4/library/abc.html
定义ABC时,将所有类似接口的方法放入其中,并在其正文中放置pass
或raise 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)
请注意,对于完全成熟的国际象棋游戏,上述绝不是一个好的设计。它仅用于说明目的。