如何在while循环中总结一个范围内的整数



伙计们!

我正在尝试做评估任务。它要求我输入某些科目(化学、计算机、生物、物理、艺术(的分支数量。然后它要求我把这些科目的书籍数量放在每个分支上。然后它让我计算书籍的总数,并计算平均数。我几乎已经完成了,但还有最后一个障碍对我来说——如何计算这些分支和科目的书籍总数。如果你能向我解释一下,我将不胜感激。

这是代码:

#!/usr/bin/env python3
branches = 0
while branches < 1:
try:
branches = int(input("Enter branches: "))
except (ValueError, TypeError):
print("Number of branches must be an integer")
else:
if branches < 1:
print("Number of branches must be at least 1")

for i in range(branches):
for category in ["Computer", "Physics", "Chemistry", "Biology", "Arts"]:
books = -1
while books < 0:
try:
string_branches = str(i+1)
books = int(input("Enter the number of books for " + category +  " of branch " + string_branches + " :" ))
except (ValueError, TypeError):
print("Number of books must be an integer")
else:
if books < 0:
print("Number of books must be at least 1")
books_total = 0
books_total = books + books 
books_per_category = books_total  / branches
print("Following the information of all the branches of the main library: ")
print("Total number of books: ",books_total )
print("Average numbers of books per category: ",  books_per_category)

价值百万美元的问题是——如何使书籍加起来达到总数?相信我,我试过很多不同的方法,但似乎都不起作用。

也许我并没有定义什么东西的功能。

我想给您一个关于CLI的更详细的答案,如何通过将代码拆分为函数来清理代码,如何定义自己的异常,以及如何删除两个主循环中的一个。此外,我选择存储每一个输入,而不是一边求和一边求和。例如,输出可以是:

{'Computer': [1, 3], # 2 branches with 1 and 3 books
'Physics': [4], # 1 branch with 4 books
'Chemistry': [2, 3, 2],
'Biology': [2],
'Arts': [2]}

代码分为3部分:

  1. 异常
  2. 输入
  3. 主回路

您可以定义自己的异常。你可以阅读例如这篇文章。此外,我选择将用户输入的可能重试次数限制为5次。这样,程序总是有结束的。我用大写字母定义了RETRIES,通常我会将其视为导入的全局变量。

#%% Define custom exceptions
RETRIES = 5
class ConsecutiveWrongAnswers(Exception):
"""Exception raised when the users input too many times a wrong answer
to a query. 
Attributes:
retries -- Number of retries
"""
def __init__(self, retries):
self.retries = retries
self.message = f'The input was invalid more than {self.retries} times!'
super().__init__(self.message)

class InvalidBranchNumber(Exception):
"""Exception raised for errors in the branch number input.
Attributes:
branch -- invalid branch number.
message -- explanation of the error.
"""
def __init__(self, branch, 
message="Branch number input should be a positive integer."):
self.branch = branch
self.message = message
super().__init__(self.message)
def __str__(self):
return f'{self.branch} -> {self.message}'

class InvalidBooksNumber(Exception):
"""Exception raised for errors in the branch number input.
Attributes:
books -- invalid books number.
message -- explanation of the error.
"""
def __init__(self, branch, 
message="Books number input should be a positive integer."):
self.books = books
self.message = message
super().__init__(self.message)
def __str__(self):
return f'{self.books} -> {self.message}'

然后,我定义了输入函数,它将允许用户尝试输入有效的输入,最多RETRIES次。输入在返回之前进行检查。

#%% Input functions
def input_branch_number(category, retries=RETRIES):

def check_branch(branch):
if branch <= 0:
raise InvalidBranchnNumber(branch)

attempt = 0
while True:
attempt += 1
if attempt > retries:
raise ConsecutiveWrongAnswers(retries)

try:
branch = int(input(f'[IN] Branch number for category {category}: '))
check_branch(branch)
break
except (InvalidBranchNumber, ValueError, TypeError):
print (f"Invalid ID: branch number should be a positive integer.)")
except:
raise

return branch
def input_books_number(category, branch_id, retries=RETRIES):

def check_books(books):
if books <= 0:
raise InvalidBooksNumber(books)

attempt = 0
while True:
attempt += 1
if attempt > retries:
raise ConsecutiveWrongAnswers(retries)

try:
books = int(input(f'[IN] Books number for (category, branch n°) - ({category}, {branch_id}): '))
check_books(books)
break
except (InvalidBooksNumber, ValueError, TypeError):
print (f"Invalid ID: branch number should be a positive integer.)")
except:
raise

return books

最后,主循环现在读起来简单多了:

#%% Main loop
# Initialize the data structure which will contain the number of books per category and per branch. 
books_logs = dict()
for category in ["Computer", "Physics", "Chemistry", "Biology", "Arts"]:
# Input the number of branch per category
branch = input_branch_number(category)

# For each category, initialize an empty list. The list will be filled by the number of books per branch
books_logs[category] = list()
for branch_id in range(branch):
# Input the books for each (category, branch_id)
books = input_books_number(category, branch_id)
books_logs[category].append(books)

现在,您可以使用books_logs字典来对每个分支、每个类别求和,或者获取总数。

注意:对于字符串格式,我建议您使用python格式标志来提高可读性,而不是像您那样对str对象求和:

f'This is a formatting string with {n_characters} characters and {n_words}.'

{}之间的元素可以是任何东西,它将由python评估/执行。你可以有公式,例如

k = 2
f'I want to format with leading zeros integer {k} to get {str(k).zfill(3)}'

最后,我选择了一个非常简单的数据结构,但你可以用另一个字典来替换它。特别是,正如Rutger Righart所建议的那样,您可以使用pandas数据帧。

您做错的是为类别中的每个迭代分配0books_total。您需要在读取输入之前声明它,并在每次迭代中将输入添加到它中。

books_total = 0 # init here
for i in range(branches):
for category in ["Computer", "Physics", "Chemistry", "Biology", "Arts"]:
books = -1
while books < 0:
try:
string_branches = str(i+1)
books = int(input("Enter the number of books for " + category +  " of branch " + string_branches + " :" ))
except (ValueError, TypeError):
print("Number of books must be an integer")
else:
if books < 0:
print("Number of books must be at least 1")
books_total += books # add the input to books_total

首先,此语句使您的图书数量翻倍,这使其成为错误的计算

books_total = books + books 

你可以做:

books_total += books 

您必须在循环外声明total_books,每次输入新书时,都要将该数字添加到总图书中。

您可能需要将数据放入Pandas DataFrame中。

#!/usr/bin/env python3
import pandas as pd
branches = 0
while branches < 1:
try:
branches = int(input("Enter branches: "))
except (ValueError, TypeError):
print("Number of branches must be an integer")
else:
if branches < 1:
print("Number of branches must be at least 1")

df = pd.DataFrame({})
for i in range(branches):
for category in ["Computer", "Physics", "Chemistry", "Biology", "Arts"]:  
books = -1
while books < 0:
try:
string_branches = str(i+1)
books = int(input("Enter the number of books for " + category +  " of branch " + string_branches + " :" ))
df[category+string_branches] = pd.Series(books)
except (ValueError, TypeError):
print("Number of books must be an integer")
else:
if books < 0:
print("Number of books must be at least 1")
books_total = 0
books_total = books + books 
books_per_category = books_total  / branches
print("Following the information of all the branches of the main library: ")
print("Total number of books: ",books_total )
print("Average numbers of books per category: ",  books_per_category)

从那里,您可以更容易地进行不同的sum操作。

df.apply(sum, axis=1)

例如,按类别求和。

df['Computer1']+df['Computer2']

如果你有很多分支,只需使用字符串("计算机"(来计算分支之间的总和:

df.loc[:, list(df.columns[df.columns.str.contains(pat = 'Computer')])].apply(sum, axis=1)

最新更新