В Python, как мне обновить баланс, когда я снимаю деньги, а затем вносить деньги? - PullRequest
2 голосов
/ 03 мая 2019

Я создаю банкомат с использованием кода Python, и мне нужно создать функции ввода и вывода, которые ведут себя так же, как и банкомат. Отдельно работают функции пополнения и снятия. Однако, когда я сначала снимаю деньги, а затем пополняю деньги, баланс не обновляется. То же самое, когда я делаю депозит, затем снимаю.

Спасибо, и ваша помощь очень ценится.

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    counter = 0
    while counter <= 2:
        while counter == 0:
            withdraw = int(input("Enter the amount you want to withdraw: AED "))
            counter = counter + 1
        while ((int(balance) - int(withdraw)) < 0):
            print("Error Amount not available in card.")
            withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
            continue
        while ((float(balance) - float(withdraw)) >= 0):
            print("Amount left in your account: AED" + str(balance - withdraw))
            return (balance - withdraw)
        counter = counter + 1


def deposit():
    counter = 0
    while counter <= 2:
        while counter == 0:
            deposit = int(input("Enter amount to be deposited: "))
            counter = counter + 1
        while ((int(balance) + int(deposit)) >= 0):
            print("Amount left in your account: AED" + str(balance + deposit))
            return (balance + deposit)
        counter = counter + 1

withdraw()
deposit()

Если я сниму 17, баланс будет 583. Однако, когда я внесу 12, баланс станет 612, что неверно, это должно быть 595.

Ответы [ 5 ]

4 голосов
/ 03 мая 2019

Вы вообще не меняете переменную «баланс»! Ваш код должен выглядеть примерно так:

balance = withdraw()
balance = deposit()

Но есть и другие проблемы с вашим кодом. Прежде всего, вы не должны делать так много бросков. Вы должны преобразовать пользовательский ввод один раз в число, а затем просто рассчитать все с этим типом. Вы используете float и int. Если вы хотите заполнить валютой, вы должны использовать, вероятно, десятичную (https://docs.python.org/2/library/decimal.html),, потому что арифметика с плавающей запятой не является точной для некоторых особых случаев (вам нужно округлить), а целое число, очевидно, не обеспечивает арифметику с плавающей запятой.

Также ваше специальное использование while не соответствует общепринятым стандартам кодирования и затрудняет чтение вашего кода. Лучше написать одну функцию, чтобы получить пользовательский ввод и отделить его от логики изъятия () и депозита ().

РЕДАКТИРОВАТЬ: Поскольку вы, кажется, новичок, я предоставлю минимальное рабочее решение.

import decimal

balance = 600

def get_user_input(action):
  # Get user input and convert it to decimal type
  return decimal.Decimal(input("Please enter amount to {} from your account: ".format(action)))

def withdraw():
  amount = get_user_input("withdraw")
  return balance - amount

def deposit():
  amount = get_user_input("deposit")
  return balance + amount

print("Your Balance is {} AED".format(balance))
balance = withdraw()
balance = deposit()
print("Your Balance is {} AED".format(balance))
2 голосов
/ 03 мая 2019

Вы просто забыли сохранить новый баланс, вы просто распечатали его

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    while True:
        withdraw = int(input("Enter amount to be withdrawn: "))
        if withdraw > balance:
            print("Error Amount not available in card.")
        else: 
            new_balance = balance - withdraw
            print("Amount left in your account: AED" + str(new_balance))
            return (new_balance)

def deposit():
    deposit = int(input("Enter amount to be deposited: "))
    new_balance = balance + deposit
    print("Amount left in your account: AED" + str(new_balance))
    return (new_balance)

# This is the only place you HAVE to change for it to work
balance = withdraw()
balance = deposit()   

У вас была возможность немного изменить его, но самое главное, вы должны сохранить новый баланс.

Я также предлагаю сделать целочисленное преобразование более безопасным, проверив, является ли оно целым числом, прежде чем преобразовать его в единицу.

        withdraw_string = input("Enter amount to be withdrawn: ")        
        try:
            withdraw_int = int(withdraw_string)
            is_int = True
        except ValueError:
            print("INVALID INPUT")
            is_int = False

        if is_int == True:
1 голос
/ 03 мая 2019

В обеих ваших deposit() и widthdraw() функциях вы фактически никогда не касаетесь переменной, которая удерживает ваш баланс, поэтому вы не видите изменения.

Вы определили переменную balance , но вы ни разу не обновляли это значение с помощью balance = balance - x. Вы только печатаете результат этой математической операции с str(balance + deposit), этот код фактически не изменит ваш баланс.

Чтобы изменить баланс , необходимо обновить глобальную переменную с помощью balance += widthdraw. Но если вы вставите этот код в свой код, вы получите следующую ошибку:

UnboundLocalError: локальная переменная «баланс», на которую ссылается перед присваиванием

Это связано с тем, что для обновления глобальной переменной внутри функции вам необходимо использовать ключевое слово global , чтобы была сделана ссылка на глобальную переменную. Docs.

Теперь работает следующий код, вот две важные строки:

balance -= withdraw
balance += deposit

Вот как вы на самом деле изменяете значение в переменной balance вместо того, чтобы просто видеть результат математической операции.

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    global balance
    counter = 0
    while counter <= 2:
        while counter == 0:
            withdraw = int(input("Enter the amount you want to withdraw: AED "))
            counter = counter + 1
        while ((int(balance) - int(withdraw)) < 0):
            print("Error Amount not available in card.")
            withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
            continue
        while ((float(balance) - float(withdraw)) >= 0):
            balance -= withdraw
            print("Amount left in your account: AED " + str(balance))
            return (balance)
        counter = counter + 1


def deposit():
    global balance
    counter = 0
    while counter <= 2:
        while counter == 0:
            deposit = int(input("Enter amount to be deposited: "))
            counter = counter + 1
        while ((int(balance) + int(deposit)) >= 0):
            balance += deposit
            print("Amount left in your account: AED" + str(balance))
            return balance
        counter = counter + 1

withdraw()
deposit()

Отказ от ответственности : Вы можете определенно удалить свои заявления о возврате из снять и депозит , поскольку они практически бесполезны в этом способе решение проблемы. Почему бесполезно? Поскольку глобальная переменная balance изменяется внутри методов. Операторы return были бы полезны, если бы вместо этого вы изменили balance вне методов. Примерно так:

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    counter = 0
    while counter <= 2:
        while counter == 0:
            withdraw = int(input("Enter the amount you want to withdraw: AED "))
            counter = counter + 1
        while ((int(balance) - int(withdraw)) < 0):
            print("Error Amount not available in card.")
            withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
            continue
        while ((float(balance) - float(withdraw)) >= 0):
            tmp_balance -= withdraw
            print("Amount left in your account: AED " + str(tmp_balance))
            return tmp_balance
        counter = counter + 1


def deposit():
    counter = 0
    while counter <= 2:
        while counter == 0:
            deposit = int(input("Enter amount to be deposited: "))
            counter = counter + 1
        while ((int(balance) + int(deposit)) >= 0):
            tmp_balance += deposit
            print("Amount left in your account: AED" + str(tmp_balance))
            return tmp_balance
        counter = counter + 1

balance = withdraw()
balance = deposit()

Вторым способом вы манипулируете значением balance , основываясь на результатах, которые предоставляют вам методы. Разница здесь в том, что когда вы звоните снимать или депозит , вы на самом деле этого не делаете, вы не увидите, как это отразится, пока не сделаете это с balance = withdraw(). Есть хорошее преимущество в том, чтобы делать это таким образом, чтобы убедиться, что не возникает никаких исключений, и что если снять или депозит полностью завершен на 100%, то вы можете зафиксировать изменения.

Я решил пойти немного дальше в вашем коде, так как у вас, похоже, много кастингов ints , float и циклов while.

Вот пример того, как к нему можно подойти, если он поможет дать кому-то больше идей: (помните, нет единого пути с кодом, мы все кодируем по-разному)

  • Используйте декоратор для обработки int () отливок. Вы можете прочитать о декораторах здесь: https://www.python.org/dev/peps/pep-0318/. Когда вы повторили код (почти копирование и вставка), это, как правило, признак применения СУХОГО (не повторяйте себя). Вы можете применить DRY, сняв ответственность с общей функции, которую вы можете вызывать, или с помощью удивительного Python, использовать декораторы. Таким образом, декораторы - это не что иное, как функции, и вы можете «декорировать» их, просто поместив @ decorator_name . Это просто означает, что декоратор будет выполнен до вызова декорированной функции.
  • Я не буду приводить к float , потому что в вашем коде вы всегда приводите input к int () . Если это так, то balance никогда не должно быть плавающим.
  • Создайте класс с именем ATM, который можно создать с помощью переменной cash_available , которая является наличными в банкомате.
  • Удалить фиксированные циклы while (counter = 2), использовать вместо этого один цикл и позволить пользователю выйти по команде.
  • Снимите ответственность за ввод данных для метода снятия и дайте пользователю возможность решить, хотят ли они снова снять.
  • Поскольку вы используете Python 3, примените f"" строковый формат.

Итак, теперь код.

def exit_on_input_cast_error(func):
def wrapper(arg):
    try:
        return func(arg)
    except ValueError as ex:
        print("Exiting, bye.")
        exit()
return wrapper


class ATM():
"""A simple atm machine"""

def __init__(self, balance):
    self.cash_available = balance

@exit_on_input_cast_error
def withdraw(self):
    '''Withdraws entered amount, until user exits'''
    continue_withdraw = True
    while continue_withdraw:
        withdraw_amount = self._get_withdraw_input()
        self.cash_available -= withdraw_amount
        self.print_balance("left in")
        withdraw_again = str(input("Would you like to withdraw another amount? (Y or N)"))
        continue_withdraw = withdraw_again.lower() in ['1', 'y', 'yes']
    self.print_bye()

@exit_on_input_cast_error
def _get_withdraw_input(self):
    input_error = True
    while input_error:
        withdrawl = int(input("Enter the amount you want to withdraw (Press N to exit): AED "))

        if (self.cash_available - withdrawl) < 0:
            print("Error Amount not available in machine.")
            input_error = True
        elif (self.cash_available - withdrawl) > self.cash_available:
            print("Error, you can't withdraw a negative amount.")
            input_error = True
        else:
            input_error = False
    return withdrawl

@exit_on_input_cast_error
def deposit(self):
    input_error = True
    while input_error:
        depositing = int(input("Please enter the amount you want to deposit (Press N to exit): AED "))
        if (self.cash_available + depositing) < self.cash_available:
            print("You cannot deposit a negative amount.")
        else:
            input_error = False
            self.cash_available += depositing
    self.print_balance("now in")
    self.print_bye()

def print_balance(self, custom_insert = 'in'):
    print(f"Amount {custom_insert} your account: AED {self.cash_available}")

def print_bye(self):
    print("Thank you for using our services today, bye.")

Давайте пройдёмся понемногу.

Это декоратор.

def exit_on_input_cast_error(func):
    def wrapper(arg):
        try:
            return func(arg)
        except ValueError as ex:
            print("Exiting, bye.")
            exit()
    return wrapper

Это всего лишь синтаксис для декоратора. Важной частью является функция возврата (arg) . Это функция, которая будет поймана. Так что этот декоратор просто отвечает за перехват исключения ValueError , которое может быть выдано, когда вы пытаетесь привести что-то вроде int('a'). Этот декоратор предназначен для предотвращения попыток пользователя вывести или внести строки в банкомат. Поскольку это код, который вы будете использовать как для ввода, так и для ввода, я поместил его в качестве декоратора для простоты вызова (принцип привет DRY).

Далее у нас есть конструктор класса . Я надеюсь, что вы знакомы с классами, если нет, вы можете найти множество ссылок и документации, чтобы понять разницу между class и method , как у вас было первоначально. Самым большим преимуществом в этом случае является то, что вы можете иметь несколько банкоматов с разным количеством наличных денег в каждом. Или вы можете создать экземпляр класса банкомата и настроить его как язык или тип монеты. Вещи, как это.

class ATM():
"""A simple atm machine"""

def __init__(self, balance):
    self.cash_available = balance

Вот такой нормальный синтаксис для определения класса. "" "Простой банкомат" "" - это строка документа , поэтому при вызове классов .__ doc __ вы получите это взамен.

Теперь к хорошему.

@exit_on_input_cast_error
def _get_withdraw_input(self):
    input_error = True
    while input_error:
        withdrawl = int(input("Enter the amount you want to withdraw (Press N to exit): AED "))

        if (self.cash_available - withdrawl) < 0:
            print("Error Amount not available in machine.")
            input_error = True
        elif (self.cash_available - withdrawl) > self.cash_available:
            print("Error, you can't withdraw a negative amount.")
            input_error = True
        else:
            input_error = False
    return withdrawl

Этот метод предназначен для обработки получения ввода пользователя. Посмотрите, как оно украшено @ exit_on_input_cast_error ? Это означает, что если пользователь вводит «а», то программа завершает работу. Это происходит потому, что приведение int(...) сгенерирует исключение ValueError , которое улавливает декоратор. В псевдокоде метод выполняет следующие действия:

while there's an error do the following:
    Get the user input and cast it as an int. 
    Make sure the amount user has introduced matches the following criteria:
        It is not more than the cash available in the atm.
        It is not a negative number.

Это в основном то, что делает этот метод. Он продолжает просить пользователя ввести верный ввод, пока пользователь не сделает это или не завершит работу, введя «N». И почему они выходят, когда они вводят "N". Поскольку «N» не является int , поэтому, когда приведение происходит в этой строке:

withdrawl = int(input("Enter the amount you want to withdraw (Press N to exit): AED "))

A ValueError будет сгенерировано int () , после чего это исключение будет перехвачено удобным декоратором @exit_on_input_cast_error, который затем печатает "Bye" и выходит для вас. Круто, верно?

Далее следует фактический метод вывода, который вы использовали . Разница теперь в том, что существует только один цикл, который продолжает спрашивать пользователя, хочет ли он продолжать снятие снова после завершения действия. Пользователь может либо выйти, либо выйти снова.

@exit_on_input_cast_error
def withdraw(self):
    '''Withdraws entered amount, until user exits'''
    continue_withdraw = True
    while continue_withdraw:
        withdraw_amount = self._get_withdraw_input()
        self.cash_available -= withdraw_amount
        self.print_balance("left in")
        withdraw_again = str(input("Would you like to withdraw another amount? (Y or N)"))
        continue_withdraw = withdraw_again.lower() in ['1', 'y', 'yes']
    self.print_bye()

В псевдокоде:

while the user wants to withdraw:
    Get the user input
    Check that the withdraw action does not result in 0 or negative number. 
    Print the balance
    Ask the user if they want to withdraw again.

По сути, это то, что делает метод. И это используется для новых методов, которые предназначены для печати сообщений.

def print_balance(self, custom_insert = 'in'):
    print(f"Amount {custom_insert} your account: AED {self.cash_available}")

def print_bye(self):
    print("Thank you for using our services today, bye.")

Эти методы можно вызывать и передавать в пользовательских частях сообщения, например print_balance . Они показывают приватную переменную класса ATM . В методе изъятия я должен указать, что вы можете снимать деньги до точки достижения 0. Машина позволит вам продолжать снимать деньги, но не позволит вам, поскольку в ней 0 наличных.

И, наконец, метод депозита.

@exit_on_input_cast_error
def deposit(self):
    input_error = True
    while input_error:
        depositing = int(input("Please enter the amount you want to deposit (Press N to exit): AED "))
        if (self.cash_available + depositing) < self.cash_available:
            print("You cannot deposit a negative amount.")
        else:
            input_error = False
            self.cash_available += depositing
    self.print_balance("now in")
    self.print_bye()

Как видите, очень просто и следует тому же принципу. Вот как бы вы вызывали реальные методы:

atm_a = ATM(600)
atm_a.withdraw()

Вот вывод кода:

Enter the amount you want to withdraw (Press N to exit): AED 100
Amount left in your account: AED 500
Would you like to withdraw another amount? (Y or N)Y
Enter the amount you want to withdraw (Press N to exit): AED -1
Error, you can't withdraw a negative amount.
Enter the amount you want to withdraw (Press N to exit): AED 501
Error Amount not available in machine.
Enter the amount you want to withdraw (Press N to exit): AED 5
Amount left in your account: AED 495
Would you like to withdraw another amount? (Y or N)yes
Enter the amount you want to withdraw (Press N to exit): AED 5
Amount left in your account: AED 490
Would you like to withdraw another amount? (Y or N)no
Thank you for using our services today, bye.

Если вы хотите снять и внести депозит:

atm_a = ATM(600)
atm_a.withdraw()
atm_a.deposit()

Вот вывод кода:

Enter the amount you want to withdraw (Press N to exit): AED 500
Amount left in your account: AED 100
Would you like to withdraw another amount? (Y or N)no
Thank you for using our services today, bye.
Please enter the amount you want to deposit (Press N to exit): AED -1
You cannot deposit a negative amount.
Please enter the amount you want to deposit (Press N to exit): AED 1000
Amount now in your account: AED 1100
Thank you for using our services today, bye.

Обратите внимание, что вы можете внести депозит только один раз, и тогда он существует. Это потому, что я не реализовал это, поскольку я уже сделал это для снимите . Любой желающий может просто скопировать его в депозит , если захочет.

Надеюсь, это было не так уж и много, и мне удалось это объяснить. К этому можно добавить множество вещей:

  • Контрольные примеры
  • Разница между наличными в банкомате физически и остатком на счете пользователя
  • При снятии средств, зная, есть ли у вас правильное количество счетов, чтобы дать желаемую сумму ... и т.д.
0 голосов
/ 03 мая 2019

Вы не изменяете переменную balance, вы возвращаете значение только с добавленным или уменьшенным deposit или withdraw.

Попробуйте изменить свой код, чтобы он сохранил новый balance перед возвратом.Поэтому вместо:

print("Amount left in your account: AED" + str(balance - withdraw))
return (balance - withdraw)

Попробуйте:

balance = (balance - withdraw)
print("Amount left in your account: AED" + str(balance))
return balance

Затем сделайте то же самое с функцией deposit.

Ваш новый код:

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    counter = 0
    while counter <= 2:
        while counter == 0:
            withdraw = int(input("Enter the amount you want to withdraw: AED "))
            counter = counter + 1
        while ((int(balance) - int(withdraw)) < 0):
            print("Error Amount not available in card.")
            withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
            continue
        while ((float(balance) - float(withdraw)) >= 0):
            balance = (balance - withdraw)
            print("Amount left in your account: AED" + str(balance))
            return balance
        counter = counter + 1


def deposit():
    counter = 0
    while counter <= 2:
        while counter == 0:
            deposit = int(input("Enter amount to be deposited: "))
            counter = counter + 1
        while ((int(balance) + int(deposit)) >= 0):
            balance = (balance + deposit)
            print("Amount left in your account: AED" + str(balance))
            return balance
        counter = counter + 1

withdraw()
deposit()
0 голосов
/ 03 мая 2019

Я согласен с предложением @Chetan Ranpariya, вы не изменили переменную balance в своем коде для обеих функций. Вы можете изменить переменную balance, используя выражение balance += <increase amount>, balance -= <decrease amount> или balance = balance + <increase amount> и т. Д.

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    counter = 0
    while counter <= 2:
        while counter == 0:
            withdraw = int(input("Enter the amount you want to withdraw: AED "))
            counter = counter + 1
        while ((int(balance) - int(withdraw)) < 0):
            print("Error Amount not available in card.")
            withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
            continue
        while ((float(balance) - float(withdraw)) >= 0):
            print("Amount left in your account: AED" + str(balance - withdraw))
            return (balance - withdraw)
        counter = counter + 1


def deposit():
    counter = 0
    while counter <= 2:
        while counter == 0:
            deposit = int(input("Enter amount to be deposited: "))
            counter = counter + 1
        while ((int(balance) + int(deposit)) >= 0):
            print("Amount left in your account: AED" + str(balance + deposit))
            return (balance + deposit)
        counter = counter + 1

balance = withdraw()
balance = deposit()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...