簡體   English   中英

為什么它返回 TypeError:“NoneType”類型的 object 沒有 len()

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

Python 3.8.2 Mac 大蘇爾 11.2.1

這段代碼應該是終端中的一個簡單的掃雷游戲,但是當我運行它時,我只收到一條錯誤消息(如下所示)我在搜索時找不到任何解決此問題的幫助,所以我想自己問一下

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()

當我運行此代碼時,它只返回

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()

我該如何解決這個問題

可迭代columns中至少有一個None值。 這是一個簡單的示例,它在給定相同的代碼行的情況下提供相同的錯誤:

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

結果:

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

至於為什么None值在那里, columns是從visible_board的。 我還沒有花時間完全理解你的邏輯,但我會指出構建visible_board的代碼行非常可疑:

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

當然,在我看來,它會構建一個包含很多None條目的列表。 在調試器中運行代碼時會驗證這一點。 在出現錯誤時, visible_board如下所示:

[['','','','','','','','','',''],[無,無,無,無,無,無,無,無,無,無],[無,無,無,無,無,無,無,無,無,無],[無,無,無,無,無,無,無,無,無,無],[無,無,無,無,無,無,無,無,無,無],[無,無,無,無,無,無,無,無,無,無],[無,無,無,無,無,無,無,無,無,無],[無,無,無,無,無,無,無,無,無,無],[無,無,無,無,無,無,無,無,無,無],[無,無,無,無,無,無,無,無,無,無,無]]

因此,您最終嘗試在None值上調用len屬性並得到您所做的錯誤也就不足為奇了。

這里似乎發生的是,您傳遞給max()的變量之一沒有定義(這就是NoneType通常的意思—— 某些東西沒有類型(例如,它是一個null值),所以你不能得到它的長度)。 也許您忘記了從您的某個函數中return某些內容,或者可能出現了您未預料到的 scope 錯誤。 從您的錯誤堆棧中很難分辨出來,因為您的代碼中沒有行號,並且您多次使用max()

這非常復雜,但不是那么“大”,並且您已經將邏輯很好地划分為函數。 我的建議是開始編寫一些單元測試,並且可能我會使用doctest來完成類似的事情。 這應該可以幫助您縮小問題的范圍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM