#python #python-3.x #validation #for-loop
Вопрос:
В настоящее время я пишу налоговый калькулятор, и я заметил, что если я ввожу неверный налоговый код, то сначала кажется, что он отклоняется, но затем программа, похоже, сохраняет исходные данные и просматривает их в обратном порядке (вот так).:
[User Input] Gross Income: £32,000 [User Input] Tax Code: 32,000 Tax Code after input: 32,000 Failed letter check Invalid input. Please enter your tax code. [User Input] Tax Code: y Tax Code after input: y Passed letter check Tax Code after letter check: y Tax Code during dictionary match check (false): y Failed dictionary match check Invalid input. Please enter your tax code. [User Input] Tax Code: 1257L Tax Code after input: 1257L Passed letter check Tax Code after letter check: 1257L Tax Code during dictionary match check (true): 1257L Passed dictionary match check Tax Code after dictionary match check: 1257L Personal Allowance: 12570 Tax Letter: L Tax Code after dictionary match check: y Personal Allowance: 0 Tax Letter: Y Tax Code after letter check: 32,000 Traceback (most recent call last): File "C:UsersJoshua.RiberioGittaxcalctaxcalc.py", line 336, in <module> salarycalc() File "C:UsersJoshua.RiberioGittaxcalctaxcalc.py", line 243, in salarycalc personal_allowance, tax_letter = get_tax_code() File "C:UsersJoshua.RiberioGittaxcalctaxcalc.py", line 78, in get_tax_code tax_letter = tax_code[tax_letter_index:].upper() TypeError: slice indices must be integers or None or have an __index__ method
Вот мой код:
def get_tax_code(): tax_code = input('Tax Code: ') print('Tax Code after input:', tax_code) tax_letter_index = '' # Checking input contains a letter for char in tax_code: if char.upper() in alpha: tax_letter_index = tax_code.index(char) print('Passed letter check') break if tax_letter_index == '': print('Failed letter check') print('Invalid input. Please enter your tax code.') get_tax_code() print('Tax Code after letter check:', tax_code) tax_letter = tax_code[tax_letter_index:].upper() # Checking input has a key match in the tax_letters dictionary if tax_letter not in tax_letters.keys(): print('Tax Code during dictionary match check (false):', tax_code) print('Failed dictionary match check') print('Invalid input. Please enter your tax code.') get_tax_code() elif tax_letter in tax_letters.keys(): print('Tax Code during dictionary match check (true):', tax_code) print('Passed dictionary match check') print('Tax Code after dictionary match check:', tax_code) # Getting personal allowance from Tax Code personal_allowance = tax_code[:tax_letter_index] if personal_allowance == '': personal_allowance = 0 else: personal_allowance = int(personal_allowance) * 10 # Setting personal allowance exceptions for gross income over £100,000 if gross_income > 100000: personal_allowance = set_personal_allowance - ((gross_income - 100000) / 2) if personal_allowance < 0: personal_allowance = 0 print('Personal Allowance:', personal_allowance) print('Tax Letter:', tax_letter) return personal_allowance, tax_letter
The excessive prints are just so I could see where the input was being changed. It seems as though after a successful run through, the code loops back up to the top using the previous invalid inputs, resulting in the code failing to run.
Can anybody see where I’m going wrong?
Notes
tax_letters
является определенным словарем, будет обновлять его для извлечения из выбранного CSV:
tax_letters = {
"L": "You’re entitled to the standard tax-free Personal Allowance",
"M": "Marriage Allowance: you’ve received a transfer of 10% of your partner’s Personal Allowance",
"N": "Marriage Allowance: you’ve transferred 10% of your Personal Allowance to your partner",
"T": "Your tax code includes other calculations to work out your Personal Allowance",
"0T": "Your Personal Allowance has been used up, or you’ve started a new job and your employer does not have the details they need to give you a tax code",
"BR": "All your income from this job or pension is taxed at the basic rate (usually used if you’ve got more than one job or pension)",
"D0": "All your income from this job or pension is taxed at the higher rate (usually used if you’ve got more than one job or pension)",
"D1": "All your income from this job or pension is taxed at the additional rate (usually used if you’ve got more than one job or pension)",
"NT": "You’re not paying any tax on this income",
"S": "Your income or pension is taxed using the rates in Scotland",
"S0T": "Your Personal Allowance (Scotland) has been used up, or you’ve started a new job and your employer does not have the details they need to give you a tax code",
"SBR": "All your income from this job or pension is taxed at the basic rate in Scotland (usually used if you’ve got more than one job or pension)",
"SD0": "All your income from this job or pension is taxed at the intermediate rate in Scotland (usually used if you’ve got more than one job or pension)",
"SD1": "All your income from this job or pension is taxed at the higher rate in Scotland (usually used if you’ve got more than one job or pension)",
"SD2": "All your income from this job or pension is taxed at the top rate in Scotland (usually used if you’ve got more than one job or pension)",
"C": "Your income or pension is taxed using the rates in Wales",
"C0T": "Your Personal Allowance (Wales) has been used up, or you’ve started a new job and your employer does not have the details they need to give you a tax code",
"CBR": "All your income from this job or pension is taxed at the basic rate in Wales (usually used if you’ve got more than one job or pension)",
"CD0": "All your income from this job or pension is taxed at the higher rate in Wales (usually used if you’ve got more than one job or pension)",
"CD1": "All your income from this job or pension is taxed at the additional rate in Wales (usually used if you’ve got more than one job or pension)"
}
gross_income
определяется в основной функции:
def salarycalc():
screen_clear()
global gross_income
gross_income = input('Gross Income: £')
if ',' in gross_income:
gross_income = gross_income.replace(',', '')
if '£' in gross_income:
gross_income = gross_income.replace('£', '')
gross_income = float(gross_income)
set_personal_allowance
является переменной, определяемой значением в словаре «tax_brackets», снова обновит это позже, чтобы извлечь из выборки CSV:
tax_brackets = {
'Personal Allowance': 12570,
'Basic': [0, 0.2],
'Higher': [50270, 0.4],
'Additional': [150000, 0.45]
}
set_personal_allowance = tax_brackets['Personal Allowance']
Комментарии:
1. Где находится
tax_letters
gross_income
иset_personal_allowance
определено?2. @vnk Я только что добавил примечание, чтобы прояснить это, спасибо, что посмотрели
3. ваша проблема в том, что внутри
get_tax_code()
вы снова запускаетесьget_tax_code()
— поэтому, закончив вторуюget_tax_code()
, она возвращается к первойget_tax_code()
и продолжает ее. Вы должны, по крайней мере, использоватьreturn
после выполнения (каждую) секундуget_tax_code()
— и он также выйдет первымget_tax_code()
, не продолжая его.
Ответ №1:
Таким образом, основная причина, по которой ваш код, вероятно, не работал, заключалась в повторяющихся рекурсивных вызовах. Чтобы упростить подход, я разбил необходимые функции на 2 проверочные проверки. Пожалуйста, обратите внимание, что я включил несколько примеров данных для проверки программы, вы можете соответственно игнорировать это.
Функция драйвера get_tax_code
работает до тех пор, пока две проверки верны, это означает, что она перестанет запрашивать ввод только после того, как налоговый код будет проверен как проверкой букв, так и соответствием словарю.
def get_tax_code(tax_letters):
gross_income = 32000
set_personal_allowance = 12570
check1 = True
check2 = True
while check1 or check2:
tax_code = input('Tax Code: ')
print('Tax Code after input:', tax_code)
tax_letter_index = verify1(tax_code)
if tax_letter_index != -1:
check1 = False
tax_letter = tax_code[tax_letter_index:].upper()
print('Tax Code after letter check:', tax_code)
x = verify2(tax_letter, tax_letters)
if x:
print('Tax Code during dictionary match check (true):', tax_code)
print('Passed dictionary match check')
print('Tax Code after dictionary match check:', tax_code)
check2 = False
else:
print('Tax Code during dictionary match check (false):', tax_code)
print('Failed dictionary match check')
print('Invalid input. Please enter your tax code.')
else:
print('Failed letter check')
print('Invalid input. Please enter your tax code.')
# Getting personal allowance from Tax Code
personal_allowance = tax_code[:tax_letter_index]
if personal_allowance == '':
personal_allowance = 0
else:
personal_allowance = int(personal_allowance) * 10
# Setting personal allowance exceptions for gross income over £100,000
if gross_income > 100000:
personal_allowance = set_personal_allowance - ((gross_income - 100000) / 2)
if personal_allowance < 0:
personal_allowance = 0
print('Personal Allowance:', personal_allowance)
print('Tax Letter:', tax_letter)
Это две вспомогательные функции, которые ранее были включены в get_tax_code
.
Первая функция verify1()
выполняет проверку букв, в то время как вторая verify2()
обрабатывает соответствие словаря. Значения, возвращаемые обеими этими функциями, определяют, будут ли обновлены контрольные значения, что в свою очередь решает, должен ли пользователь снова вводить tax_code
входные данные.
def verify1(tax_code):
tax_letter_index = ''
# Checking input contains a letter
for char in tax_code:
if char.upper().isalpha():
tax_letter_index = tax_code.index(char)
print('Passed letter check')
break
if tax_letter_index == '':
return -1
else:
return tax_letter_index
def verify2(tax_letter, tax_letters):
if tax_letter not in tax_letters.keys():
return False
elif tax_letter in tax_letters.keys():
return True
Выход
Tax Code: 3200
Tax Code after input: 3200
Failed letter check
Invalid input. Please enter your tax code.
Tax Code: y
Tax Code after input: y
Passed letter check
Tax Code during dictionary match check (false): y
Failed dictionary match check
Invalid input. Please enter your tax code.
Tax Code: 1257L
Tax Code after input: 1257L
Passed letter check
Tax Code during dictionary match check (true): 1257L
Passed dictionary match check
Tax Code after dictionary match check: 1257L
Personal Allowance: 12570
Tax Letter: L
Комментарии:
1. Это именно то, что я искал, спасибо. Пометил это как ответ. Это также научило меня некоторым основам, которых мне явно не хватало. Я ценю вашу помощь
2. Пожалуйста. Рад, что это помогло.