简体   繁体   English

为什么它返回 TypeError:“NoneType”类型的 object 没有 len()

[英]Why is it returning TypeError: object of type 'NoneType' has no len()

Python 3.8.2 Mac Big Sur 11.2.1 Python 3.8.2 Mac 大苏尔 11.2.1

This code is supposed to be a simple minesweeper game in the terminal but when i run it i only get a error message (shown below) i couldn't find any help to this problem when searching around so i thought to ask it myself instead这段代码应该是终端中的一个简单的扫雷游戏,但是当我运行它时,我只收到一条错误消息(如下所示)我在搜索时找不到任何解决此问题的帮助,所以我想自己问一下

import random
import re

class Board:
    def __init__(self, dim_size, num_bombs):
        self.dim_size = dim_size
        self.num_bombs = num_bombs

        self.board = self.make_new_board() 
        self.assign_values_to_board

        self.dug = set() 

    def make_new_board(self):
        board = [[None for _ in range(self.dim_size)] for _ in range(self.dim_size)]

    def assign_values_to_board(self):
        for r in range(self.dim_size):
            for c in range(self.dim_size):
                if self.board[r][c] == '*':
                    continue
                self.board[r][c] = self.get_num_neighboring_bombs(r, c)

    def get_num_neighboring_bombs(self, row, col):
        num_neighboring_bombs = 0
        for r in range(max(0, row-1), min(self.dim_size-1, row+1)+1):
            for c in range(max(0, col-1), min(self.dim_size - 1, col+1)+1):
                if r == row and c == col:
                     continue
                if self.board[r][c] == '*':
                    num_neighboring_bombs += 1

        return num_neighboring_bombs

        bombs_planted = 0
        while bombs_planted < self.num_bombs:
            loc = random.randint(0, self.dim_size**2 - 1)
            row = loc // self.dim_size
            col = loc % self.dim_size

            if board [row][col] == '*':
                # bomb already plated here
                continue

            board[row][col] = '*' # plant the bomb
            bombs_planted += 1

        return board

    def dig(self, row, col):
        self.dug.add((row, col))

        if self.board[row][col] == '*':
            return False
        elif self.board[row][col] > 0:
            return True

        for r in range(max(0, row-1), min(self.dim_size-1, row+1)+1):
            for c in range(max(0, col-1), min(self.dim_size - 1, col+1)+1):
                if (r, c) in self.dug:
                    continue
                self.dig(r, c)

        return True

    def __str__(self):
        visible_board = [[None for _ in range(self.dim_size)] for _ in range(self.dim_size)]
        for row in range(self.dim_size):
            for col in range(self.dim_size):
                if (row,col) in self.dug:
                    visible_board[row][col] = str(self.board[row][col])
                else: 
                    visible_board[row][col] = ' '

            string_rep = ''

            widths = []
            for idx in range(self.dim_size):
                columns = map(lambda x: x[idx], visible_board)
                widths.append(
                    len(
                        max(columns, key = len)
                    )
                )

            indices = [i for i in range(self.dim_size)]
            indices_row = '   '
            cells = []
            for idx, col in enumerate(indices):
                format = '%-' + str(widths[idx]) + "s"
                cells.append(format % (col))
            indices_row += '  '.join(cells)
            indices_row += '  \n'

            for i in range(len(visible_board)):
                row = visible_board[i]
                string_rep += f'{i} |'
                cells = []
                for idx, col in enumerate(row):
                    format = '%-' + str(widths[idx]) + "s"
                    cells.append(format % (col))
                string_rep += ' |'.join(cells)
                string_rep += ' |\n'

            str_len = int(len(string_rep) / self.dim_size)
            string_rep = indices_row + '-'*str_len + '\n' + string_rep + '-'*str_len

            return string_rep

def play(dim_size=10, num_bombs=10):
    board = Board(dim_size, num_bombs)
    safe = True

    while len(board.dug) < board.dim_size ** 2 - num_bombs:
        print(board)
        user_input = re.split(',(\\s)*', input("Where would you like to dig? Input as row,col: "))
        row, col = int(user_input[0]), int(user_input[-1])
        if row < o or row >= board.dim_size or col < 0 or col >= dim_size:
            print("Invalid location. Try again")
            continue

        safe = board.dig(row, col)
        if not safe:
            break

    if safe:
        print("Victory Royale!")
    else:
        print("You suck. Game Over")
        board.dug = [(r,c) for r in range(board.dim_size) for c in range(board.dim_size)]
        print(board)

if __name__ == '__main__':
    play()

When i run this code it only returns当我运行此代码时,它只返回

Traceback (most recent call last):
  File "/Users/henry/Documents/projects/GamesPython/Minesweeper/game.py", line 134, in <module>
    play()
  File "/Users/henry/Documents/projects/GamesPython/Minesweeper/game.py", line 115, in play
    print(board)
  File "/Users/henry/Documents/projects/GamesPython/Minesweeper/game.py", line 82, in __str__
    max(columns, key = len)
TypeError: object of type 'NoneType' has no len()

How can i fix this problem我该如何解决这个问题

The iterable columns has at least one None value in it.可迭代columns中至少有一个None值。 Here is a simple example that provides the same error given the same line of code:这是一个简单的示例,它在给定相同的代码行的情况下提供相同的错误:

columns = [ "a", None, "b" ]
max(columns, key = len)

Result:结果:

max(columns, key = len)
TypeError: object of type 'NoneType' has no len()

As to why that None value is in there, columns is built from visible_board .至于为什么None值在那里, columns是从visible_board的。 I haven't spent the time to understand your logic completely, but I will point out that the line of code that builds visible_board is very suspicious:我还没有花时间完全理解你的逻辑,但我会指出构建visible_board的代码行非常可疑:

visible_board = [[None for _ in range(self.dim_size)] for _ in range(self.dim_size)]

Sure looks to me like it's going to build a list with a lot of None entries in it.当然,在我看来,它会构建一个包含很多None条目的列表。 That is verified when running your code in a debugger.在调试器中运行代码时会验证这一点。 At the point of the error, visible_board looks like this:在出现错误时, visible_board如下所示:

[[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '], [None, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None], [None, None, None, None, None, None, None, None, None, None]] [['','','','','','','','','',''],[无,无,无,无,无,无,无,无,无,无],[无,无,无,无,无,无,无,无,无,无],[无,无,无,无,无,无,无,无,无,无],[无,无,无,无,无,无,无,无,无,无],[无,无,无,无,无,无,无,无,无,无],[无,无,无,无,无,无,无,无,无,无],[无,无,无,无,无,无,无,无,无,无],[无,无,无,无,无,无,无,无,无,无],[无,无,无,无,无,无,无,无,无,无,无]]

So it isn't surprising that you end up trying to cal the len attribute on a None value and get the error that you do.因此,您最终尝试在None值上调用len属性并得到您所做的错误也就不足为奇了。

What seems to be happening here is that one of the variables you are passing to max() is not defined (that is what NoneType usually means -- something has no type (eg. it's a null value), so you can't get the length of it).这里似乎发生的是,您传递给max()的变量之一没有定义(这就是NoneType通常的意思—— 某些东西没有类型(例如,它是一个null值),所以你不能得到它的长度)。 Maybe you have forgotten to return something from one of your functions, or perhaps there is a scope error you aren't expecting.也许您忘记了从您的某个函数中return某些内容,或者可能出现了您未预料到的 scope 错误。 It's really hard to tell from your error stack because there are no line numbers in your code and you use max() a bunch of times.从您的错误堆栈中很难分辨出来,因为您的代码中没有行号,并且您多次使用max()

This is pretty complicated, but not that "large," and you have divided your logic nicely into functions.这非常复杂,但不是那么“大”,并且您已经将逻辑很好地划分为函数。 My suggestion would be start writing some unit tests, and probably I'd use doctest for something like this.我的建议是开始编写一些单元测试,并且可能我会使用doctest来完成类似的事情。 That should help you narrow-down the problem.这应该可以帮助您缩小问题的范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM