Python - 扩展和简化程序

时间:2017-09-27 08:32:28

标签: python function

我有一个计算直到用户输入上限的完美平方的程​​序。我的代码是:

"""Print all the perfect squares from zero up to a given maximum."""
import math

def read_bound():
   """Reads the upper bound from the standard input (keyboard).
      If the user enters something that is not a positive integer
      the function issues an error message and retries
      repeatedly"""
   upper_bound = None
   while upper_bound is None:
       line = input("Enter the upper bound: ")
       if line.isnumeric() and int(line) >= 0:
           upper_bound = int(line)
           return upper_bound
       else:
           print("You must enter a positive number.")



def is_perfect_square(num):
   """Return true if and only if num is a perfect square"""
   root = math.sqrt(num)
   return int(root) - root == 0



def print_squares(upper_bound, squares):
   """Print a given list of all the squares up to a given upper bound"""


   print("The perfect squares up to {} are: ". format(upper_bound))
   for square in squares:
       print(square, end=' ')



def main():
   """Calling the functions"""
   upper_bound = read_bound()
   squares = []
   for num in range(2, upper_bound + 1):
       if is_perfect_square(num):
           squares.append(num)

   print_squares(upper_bound, squares)


main()

我想略微扩展此程序以包含下限,以便程序计算并打印两个边界lower_boundupper_bound之间的完美正方形。在执行此操作时,我还要概括read_bound()函数,使其适用于下限和上限,同时仍然按原始程序打印提示符合适的提示字符串。通过将所需的提示字符串传递给read_bound()函数,我想出了一个可能解决方案的途径,以便主函数变为:

def main():
   """Every home should have one"""
   lower_bound = read_bound("Enter the lower bound: ")
   upper_bound = read_bound("Enter the upper bound: ")
   squares = []
   for num in range(lower_bound, upper_bound + 1):
       if is_perfect_square(num):
           squares.append(num)

   print_squares(lower_bound, upper_bound, squares)

这是一个解决方案的有效途径,在我的程序中添加下限同时进行概括吗?如果是这样,我如何调整read_bound()print_squares函数以适应解决方案?

1 个答案:

答案 0 :(得分:0)

您可以将代码更改为以下内容:

"""
Print all the perfect squares from zero up to a given maximum.
"""

import math

def read_bound(msg):
    """
    Reads a bound from the standard input (keyboard).  If the user
    enters something that is not a positive integer the function issues an
    error message and retries repeatedly
    """
    upper_bound = None
    while upper_bound is None:
         line = input(msg)
         if line.isnumeric() and int(line) >= 0:
              upper_bound = int(line)
              return upper_bound
         else:
              print("You must enter a positive number.")

def is_perfect_square(num):
    """
    Return true if and only if num is a perfect square
    """
    root = math.sqrt(num)
    return int(root) - root == 0

def print_squares(lower_bound, upper_bound, squares):
    """
    Print a given list of all the squares up to a given upper bound
    """
    print("The perfect squares between {} and {} are: ". format(lower_bound, upper_bound))
    for square in squares:
         print(square, end=' ')
    print()

def calculate_squares(lower_bound, upper_bound):
    return filter(is_perfect_square, range(lower_bound, upper_bound))

def main():
    """
    Calling the functions
    """
    lower_bound = read_bound("Enter the lower bound: ")
    upper_bound = read_bound("Enter the upper bound: ")
    print_squares(lower_bound, upper_bound,
                  calculate_squares(lower_bound, upper_bound + 1))

if __name__ == "__main__":
    main()

我将计算正方形的逻辑分成另一个函数calculate_squares。注意,这个函数表现懒惰,因此不是所有的正方形都存储 - 这通常是可取的。 print_squares然后逐个使用它们,因此对于非常大的范围,您可能会看到一些实时缓冲打印。另一个变化是它现在使用range(lower_bound, upper_bound)。它假设upper_bound是非包含性的,因此在main函数中使用upper_bound + 1调用它。它使用filter来“过滤”完美正方形的范围。

read_bound现在也采用msg参数,这似乎可以做你想要的。代码执行如下:

Enter the lower bound: 20
Enter the upper bound: 100
The perfect squares between 20 and 100 are: 1
25 36 49 64 81 100

你应该警惕这段代码不会像你想象的非常大的整数一样,例如:

>>> is_perfect_square((1 << 500) + 1)
True
>>> is_perfect_square(1 << 500)
True

这意味着可能会发生这样的事情:

Enter the lower bound: 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589377
Enter the upper bound: 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589387
The perfect squares between 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589377 and 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589387 are: 
3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589377 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589378 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589379 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589380 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589381 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589382 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589383 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589384 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589385 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589386 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589387 

这里你的程序确定两个给定整数之间的每个整数都是一个正方形。

这是由于Python的任意大小整数,但有限大小的浮点数。这里math.sqrt存在舍入错误,因为Python实际上无法以任何其他方式表示它。考虑到这一点将是棘手的 - 我建议不要从潜在的方块向后工作,而是从整数根到正方形向前工作,虽然这是非常重要的 - 跳转到下限但没有舍入错误的可靠方法很可能是实施起来非常复杂。