简体   繁体   中英

How do I make an elif command which occurs in a for loop only register for certain instances of an item within the list?

Below is part of my code. Basically what this does is when run it creates credit cards with a random number and a given currency code and credit card limit. The Credit Card is a class and the money it stores is also a class (Which I have not included here for brevity and because I think they are not relevant to my question.) What happens in my code, however, is that my cancel statement works out fine but if I have two credit cards in a list and I try to cancel the second one it will again print out NO_SUCH_CARD. The card gets deleted anyway if its in the list. My guess is that his happens because the for loop iterates through the list and it first detects a card whose number is different than the given one, which is why it prints no such card, but I have no idea how to fix this. Help would be appreciated.

PATH = 'saved_cards.txt'
creditcard_list = []
import decimal
import ast
import collections
import os
import random


def currency_dictionary():
    '''Initialized at the start of the program. It finds and reads a currency.txt
       file and stores those in a dictionary'''
    final_dict = collections.defaultdict(list)
    with open("currency.txt", 'r') as f:
        currency_lines = f.readlines()
    for item in currency_lines:
        m = item.split(' ')
        final_dict[m[0]] = [int(m[1]), decimal.Decimal(m[2])]
    return final_dict





class Money():
    def __init__(self, money_amount: decimal, currency_code: str):
        self.m = decimal.Decimal(money_amount)
        self.c = str(currency_code)
        self.d = currency_dictionary()


def __repr__(self):
    return 'Money({}, {})'.format(self.m, self.c)

def __eq__(self, other):
    if type(other) != Money:
        return False

    elif self.c == other.c:
        return self.m == other.m

    elif self.c != other.c:
        dictionary_key1 = self.d[self.c]
        decimal_point1 = dictionary_key1[0]
        conversion_factor1 = dictionary_key1[1]
        x = self.m / conversion_factor1

        dictionary_key2 = self.d[other.c]
        decimal_point = dictionary_key2[0]
        conversion_factor = dictionary_key2[1]
        y = other.m / conversion_factor

        return x == y

def __ne__(self, other):
    if type(other) != Money:
        return True

    elif self.c == other.c:
        return self.m != other.m

    elif self.c != other.c:
        dictionary_key1 = self.d[self.c]
        decimal_point1 = dictionary_key1[0]
        conversion_factor1 = dictionary_key1[1]
        x = self.m / conversion_factor1

        dictionary_key2 = self.d[other.c]
        decimal_point = dictionary_key2[0]
        conversion_factor = dictionary_key2[1]
        y = other.m / conversion_factor

        return x != y

def __add__(self, other):
    if self.c == other.c:
        return Money((self.m + other.m), self.c)

    elif self.c != other.c:
        dictionary_key1 = self.d[self.c]
        decimal_point1 = dictionary_key1[0]
        conversion_factor1 = dictionary_key1[1]
        x = self.m / conversion_factor1

        dictionary_key2 = self.d[other.c]
        decimal_point = dictionary_key2[0]
        conversion_factor2 = dictionary_key2[1]
        y = other.m / conversion_factor2

        total = x + y
        return Money((total * conversion_factor1), self.c)


def __sub__(self, other):
    if self.c == other.c:
        return Money((self.m - other.m), self.c)

    elif self.c != other.c:
        dictionary_key1 = self.d[self.c]
        decimal_point1 = dictionary_key1[0]
        conversion_factor1 = dictionary_key1[1]
        x = self.m / conversion_factor1

        dictionary_key2 = self.d[other.c]
        decimal_point = dictionary_key2[0]
        conversion_factor2 = dictionary_key2[1]
        y = other.m / conversion_factor2

        total = x - y
        return Money((total * conversion_factor1), self.c)

class Credit_Card():
    def __init__(self, card_number, money_amount: Money, card_limit: int):
        if type(money_amount) != Money or type(card_limit) != int:
            raise TypeError('one of the types of the parameters entered is not valid')
        self.number = card_number
        self.amount = money_amount
        self.limit = card_limit

def __repr__(self):
    return 'Card#{}({}, {})'.format(self.number, self.amount, self.limit)

def user_interface():
    boolean = True

    while boolean:
        temp_list = []
        command = input()
        if command.split()[0] == 'ISSUE':
            if len(command.split()) == 3:
                x = "%0.5d" % random.randint(0,99999)
                currency_code = command.split()[1]
                card_limit = int(command.split()[2])
            if card_limit < 0:
                print("NEGATIVE_LIMIT")
            elif not currency_dictionary()[currency_code]:
                print("NO_SUCH_CURRENCY")
            else:
                for card in creditcard_list:
                    temp_list.append(card.number)
                if x not in temp_list and currency_dictionary()[currency_code]:
                    creditcard_list.append(Credit_Card(x, Money(0, currency_code), card_limit))
                    print('ISSUED', x)
                    print(creditcard_list)

        else:
            print("INVALID_ISSUE_COMMAND")


    elif command.split()[0] == 'CANCEL':
        templist2 = []
        if len(command.split()) == 2:
            card_number = command.split()[1]

            for card in creditcard_list:
                templist2.append(card)
            for i, card in enumerate(templist2):
                if card_number not in templist2[i].number:
                    print('NO_SUCH_CARD')
                elif templist2[i].amount.m != 0:
                    print('NONZERO_BALANCE')
                elif templist2[i].number == command.split()[1] and card.amount.m == 0:
                    del creditcard_list[i]
                    print('CANCELLED', card_number)


            print(creditcard_list)


    elif command.split()[0] == 'PURCHASE':
        if len(command.split()) == 4:
            card_number = command.split()[1]
            currency_code = command.split()[2]
            amount = int(command.split()[3])
            if currency_code not in currency_dictionary().keys():
                print('NO_SUCH_CURRENCY')
            elif amount < 0:
                print('NONPOSITIVE_AMOUNT')
            else:
                for i, card in enumerate(creditcard_list):
                    if card.number == card_number and 0 <= amount <= card.limit :
                        x = card.amount + Money(amount, currency_code)
                        creditcard_list[i] = Credit_Card(card.number, x, card.limit)
                    elif creditcard_list[i].number != card_number:
                        print('NO_SUCH_CARD')
                    elif amount > creditcard_list[i].limit:
                        print('OVER_LIMIT')

    elif command.split(0) == 'PAYMENT':


            print(creditcard_list)



if __name__ == '__main__':
    user_interface()

My output for the cancel command basically looks like this, and I'm pretty sure once I figure this out I'll be able to deal with the rest. Bold is input, non-bold is output.

**ISSUE USD 5000**
ISSUED 50695
[Card#50695(Money(0, USD), 5000)]
**ISSUE RON 3000**
ISSUED 25282
[Card#50695(Money(0, USD), 5000), Card#25282(Money(0, RON), 3000)]
**CANCEL 25282**
[Card#50695(Money(0, USD), 5000), Card#25282(Money(0, RON), 3000)]
*NO_SUCH_CARD*
CANCELLED 25282
[Card#50695(Money(0, USD), 5000)]

Note that the lists are only printed out for me to keep track of what cards are currently in the main list, and I will eventually remove those print statements. I have italicized the output I'm having a problem with.

The problem appears to be that you're modifying creditcard_list at the same time you are iterating through it. You should first create a temporary copy of the list to iterate through while later removing items from the actual list.

Edit: Ahh, it's printing "NO_SUCH_CARD" on the first card in the list! Not on the second. So in your example, you loop through a list of two; it first visits card #50695, which is not equal to 2582, so it prints "NO_SUCH_CARD". Then it visits 25282, deletes it, and prints "CANCELED". It's doing exactly what you wrote it to do. Instead, just loop through, deleting the card if you find it and silently skipping any card that doesn't match. In the end, if the card is not found print "NO_SUCH_CARD"

Edit2: Here's an example:

        found = False
        for card in templist2:
            if card_number == card.number:
                if card.amount.m != 0:
                    print('NONZERO_BALANCE')
                else:
                    del creditcard_list[i]
                    print('CANCELLED', card_number)
                found = True
                break
        if not found:
            print('NO_SUCH_CARD')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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