Accessing List leads to AttributeError: 'Nonetype' object has no attribule 'value'

Viewed 52

I have created a module for a War Simulator. I am getting "AttributeError: 'NoneType' object has no attribute 'value'" when I am calling the function.

Here is the code for the module:

import Deck
import Player

WAR_DRAW_COUNT = 5
player_one_cards = []
player_two_cards = []


def create_players() -> tuple[Player, Player]:

    player_one = Player.Player("Billy Bob")
    player_two = Player.Player("Joe Bab")
    return (player_one, player_two)


def create_deck() -> Deck:
    deck = Deck.Deck()
    deck.shuffle()
    return deck


def deal_cards(deck: Deck, player_one: Player, player_two: Player) -> None:

    for cards in range(26):
        player_one.add_cards(deck.deal_one())
        player_two.add_cards(deck.deal_one())


def can_go_to_war(player: Player) -> bool:

    if player.has_empty_hand() and player.get_play_hand_card_values() < 5:
        return False
    return True


def draw_war_cards(player_one: Player, player_two: Player,
                   player_one_cards: list, player_two_cards: list) -> None:

    for card in range(WAR_DRAW_COUNT):
        player_one_cards.append(player_one.remove_card())
        player_two_cards.append(player_two.remove_card())
    return None


def has_no_cards(player_one: Player, player_two: Player) -> bool:

    if player_one.has_empty_hand():
        print(f"{player_one.name} out of cards!")
        print(f"{player_two.name.upper()} WINS!")
        return True
    if player_two.has_empty_hand():
        print(f"{player_two.name} out of cards!")
        print(f"{player_one.name.upper()} WINS!")
        return True
    return False


def prepare_hands(player_one: Player, player_two: Player,
                  player_one_cards, player_two_cards) -> None:

    player_one_cards.append(player_one.remove_card())
    player_two_cards.append(player_two.remove_card())
    return None


def compare_values(player_one: Player, player_two: Player) -> bool:

    if player_one_cards[-1].value > player_two_cards[-1].value:
        player_one.add_cards(player_one_cards)
        player_one.add_cards(player_two_cards)
        return False
    elif player_one_cards[-1].value < player_two_cards[-1].value:
        player_two.add_cards(player_one_cards)
        player_two.add_cards(player_two_cards)
        return False
    else:
        print('WAR!')
        return True

When I call the funtion from the main function at_war = War.compare_values(player_one, player_two), I get the error: AttributeError: 'NoneType' object has no attribute 'value'

Why is this?

I separated the code into main modules, Deck, Player, Card, and War.

Here is the traceback error:

  File ***\main.py", line 54, in <module>
    main()
  File "***\main.py", line 33, in main
    at_war = War.compare_values(player_one, player_two,
  File "\***\War.py", line 69, in compare_values
    if player_one_cards[-1].value > player_two_cards[-1].value:
AttributeError: 'NoneType' object has no attribute 'value'

Here is the additional Code:


class Player:
    def __init__(self, name):
        self.name = name
        self.all_cards = []

    def get_name(self):
        return self.name

    def remove_card(self):
        if self.has_empty_hand():
            print(f"{self.name} has no cards to remove")
        return None

        return self.all_cards.pop(0)

    def add_cards(self, new_cards):
        if type(new_cards) == type([]):
            # List of single card objects
            self.all_cards.extend(new_cards)
        else:
            # List of multiple card objects
            self.all_cards.append(new_cards)


    def get_card_count(self):
        return len(self.all_cards)

    def has_empty_hand(self):
        if len(self.all_cards) == 0:
            return True
        else:
            return False

    def __str__(self):
        if len(self.all_cards) == 1:
            return f"{self.name} has {len(self.all_cards)} card."
        else:
            return f"{self.name} has {len(self.all_cards)} cards."


import War


def main():
    round_number = 0
    game_on = True
    at_war = True

    # War.setup
    player_one, player_two = War.create_players()
    deck = War.create_deck()
    War.deal_cards(deck, player_one, player_two)

    while game_on:

        round_number += 1
        print(f'Round {round_number}')

        if War.has_no_cards(player_one, player_two):
            break

        # Start a new round
        War.player_one_cards.clear()
        War.player_two_cards.clear()

        War.prepare_hands(player_one, player_two, 
                          War.player_one_cards, War.player_two_cards)

        at_war = True

        while at_war:
            
            at_war = War.compare_values(player_one, player_two)

            if at_war:

                if not War.can_go_to_war(player_one):
                    print(f"{player_one.name} unable to declare war.")
                    print(f"{player_two.name.upper()} WINS!")
                    game_on = False
                    break

                if not War.can_go_to_war(player_two):
                    print(f"{player_two.name} unable to declare war.")
                    print(f"{player_one.name.upper()} WINS!")
                    game_on = False
                    break
                War.draw_war_cards(player_one, player_two,
                                   player_one_cards, player_two_cards)


if __name__ == "__main__":
    main()

0 Answers
Related