我正在努力改进你在python的codecademy课程中制作的“战舰”游戏,我决定我的第一步是实现类。
我预期的代码输出是五行O O O O O
。当我在for循环中只使用一个print语句时会实现这一点,但它会引发错误说明:
Traceback (most recent call last):
File "D:/PythonProjects/Battleship/Main.py", line 21, in <module>
print(board)
TypeError: __str__ returned non-string (type NoneType)
当我离开代码时,它不会抛出错误但只会打印一行O的
有问题的代码:
class Board(object):
"""Creates the game board"""
board = []
def __init__(self, size):
self.size = size
for x in range(size):
self.board.append(["O"] * size)
def __str__(self):
for row in self.board:
display = (" ".join(row))
return display
board = Board(5)
print(board)
答案 0 :(得分:2)
您的__str__
方法会在循环的每次迭代中为display
分配一个新值。相反,你可以做类似的事情:
def __str__(self):
accumulator = ""
for row in self.board:
accumulator += " ".join(row) + "\n"
return accumulator
或者更简洁
def __str__(self):
return "\n".join([" ".join(row) for row in self.board])
除了那些一遍又一遍地设计这个的人之外,帮助每一个进入OOP的新入学的CS学生,如果它继承自list
,这个课就变得容易多了。它是描述游戏板的列表的容器 - 将其作为列表本身....
class Board(list):
def __init__(self, size):
"""Square board of length `size`"""
for row in range(size):
self.append(["O"] * size)
def __str__(self):
return "\n".join([" ".join(row) for row in self])
答案 1 :(得分:2)
首先,您不应该为board
使用类属性。这样做将在所有Board
实例之间共享实例,因此您将继续添加到同一列表中。而是为您创建的每个对象创建一个新列表:
class Board(object):
def __init__(self, size):
self.size = size
self.board = []
for x in range(size):
self.board.append(["O"] * size)
现在,为了回答你的问题,你实际上不应该得到那个类型的错误,因为当你在display
的循环中继续覆盖__str__
时,它确实得到至少一个不是{的值。 {1}},假设None
不为空(在您的示例中不是)。
但是你要做的是收集所有行并用新行符号连接它们:
board
或者在一行中:
def __str__(self):
display = []
for row in self.board:
display.append(" ".join(row))
return '\n'.join(display)