【问题标题】:How to summarise integers in a while loop in a range如何在一个范围内的while循环中总结整数
【发布时间】:2020-12-03 08:33:47
【问题描述】:

伙计们!

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

代码如下:

#!/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)

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

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

【问题讨论】:

    标签: python loops


    【解决方案1】:

    我想为您提供有关 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. 主循环

    您可以定义自己的异常。您可以阅读例如这个article。此外,我选择将用户输入的可能重试次数限制为 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 数据框。

    【讨论】:

    • Mathieu,非常感谢您的帮助!我很抱歉,但我忘了提到我是 python 的新手,我几乎不理解循环和迭代的主要概念 XD 这个任务太我老了,我不得不问我的同学和老师迭代 XD
    • @HeorhiyKremlov 我本可以猜到这么多。这就是为什么因为你的代码也写得很好,考虑到错误的用户输入,我想给你更多的选择。尝试尽快掌握好的做法。一个真正改进一段代码的简单方法是将代码拆分为基本块,这是我在第 3 部分中所做的功能(如果我们包括检查器功能,在这种情况下我包括作为输入的子功能,则为 4) .
    • 赞成这个答案以获得详细解释。
    【解决方案2】:

    您做错了什么是您为类别中的每个迭代分配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
    

    【讨论】:

    • 太棒了,谢谢您,先生!正常工作!它加起来 - 我无法想象我花了 6 个小时试图解决这个问题 -_-
    【解决方案3】:

    首先,此语句将您的书籍数量增加一倍,这使其计算错误

    books_total = books + books 
    

    你可以这样做:

    books_total += books 
    

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

    【讨论】:

    • 飞赞,谢谢!我现在看到代码是如何工作的。我花了很多时间试图解决这个问题-_-
    【解决方案4】:

    您可能希望将数据放入 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']
    

    如果您有许多分支,只需使用字符串 ('Computer') 来计算分支之间的总和:

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

    【讨论】:

    • Ruthger,谢谢您的回复,先生!非常感谢您的帮助:) 但是我才开始学习 Python,而且我才刚刚开始了解基本函数,例如 while、for in 和 if。
    • @HeorhiyKremlov:没问题,每个开发人员都从零开始。享受旅程:-)。
    猜你喜欢
    • 2013-02-25
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    • 2011-12-25
    • 2021-01-07
    相关资源
    最近更新 更多