首页 > 解决方案 > 如何在一个范围内的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)

百万美元的问题是 - 如何使书籍总计?相信我,我已经尝试了很多不同的方法,但它们似乎不起作用。

也许我没有定义某些东西的功能。

标签: pythonloops

解决方案


我想给你一个关于 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)}'

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


推荐阅读