是否可以将所有这 4 个嵌套的 For 循环嵌套到一个带有额外级别的 For 循环中



我正在从教科书中学习Python,其中一个练习(没有可用的答案!)希望您创建4种星号模式。 此代码创建正确的输出。

如您所见,它是 4 个单独的代码块,每个代码块都有嵌套的 For 循环。我的问题是是否可以将其全部放入嵌套更深一级的 1 For 循环中(例如,对于范围 (4) 中的组> 对于范围 (10) 中的行> 对于范围内的星号(等)? 或者由于每个代码块的输出不同,这是我可以做到的最精细的吗?

任何见解都非常感谢!

for row in range(10):
for asterisk in range(row + 1):
print('*', end='')
print()
print()
for row in range(10):
for asterisk in range(10 - row):
print('*', end='')
print()
print()
for row in range(10):
print(' ' * row, end='')
for asterisk in range(10 - row):
print('*', end='')
print()
print()
for row in range(10):
print(' ' * (9 - row), end='')
for asterisk in range(row + 1):
print('*', end='')
print()

在尝试将代码推送到另一个级别的for循环之前,让我们尝试创建一个函数来表示每个部分所需的逻辑。

从一个版本的代码开始,并存根更改的部分。添加一个函数标头,并暂时存根参数。

def triangle(...):
for row in range(10):
...
for asterisk in range(...):
print('*', end='')
print()

请注意,我没有在三角形之间包括print。这有单独的逻辑(除了第一次,我们每次都想这样做;不是因为我们画的是什么样的三角形)

在我们尝试弄清楚如何填写空白之前,让我们尝试使用我们已经知道的内容来简化代码。现有代码使用print(' ' * row, end='')print(' ' * (9 - row), end='')打印特定数量的空格(由row确定)。for循环用于打印特定数量的星号。显然,我们可以改用*技术。所以:

def triangle(...):
for row in range(10):
...
print('*' * ..., end='')
print()

完成此操作后,我们看到我们有一个故意在末尾抑制换行符的print,紧跟着一个仅用于显示换行符的空print。这没有多大意义。我们可以只:

def triangle(...):
for row in range(10):
...
print('*' * ...)

好多了。

下一篇:我们的逻辑真的是有条件的吗?在代码的原始版本中,我们有时会对某些空格进行print,而有时则没有。但我们可以统一起来:"不打印空格"与"打印零空格"是一回事;因此,我们真正需要的只是一个规则,告诉我们要打印多少个空格,然后我们每次都可以使用相同的结构:

def triangle(...):
for row in range(10):
print(' ' * ..., end='')
print('*' * ...)

事实上,我们可以将这些print结合起来。我们希望一个接一个地打印两个东西(即中间有一个空sep),我们希望在此之后打印默认换行符。所以:

def triangle(...):
for row in range(10):
print(' ' * ..., '*' * ..., sep='')

好多了。转到我们实际填写空白的部分。

首先,我们必须传递哪些信息?我们需要知道两件事:是否将三角形右对齐,以及是否将其倒置打印。所以这些是我们的参数:

def triangle(upside_down, right):
for row in range(10):
print(' ' * ..., '*' * ..., sep='')

告诉我们打印多少颗星的规则是什么?

如果三角形是右侧朝上的,那么我们打印row + 1星星。否则我们需要10 - row星星。这与原始代码中传递给range的值匹配。

def triangle(upside_down, right):
for row in range(10):
stars = 10 - row if upside_down else row + 1
print(' ' * ..., '*' * stars, sep='')

告诉我们要打印多少个空格的规则是什么?

如果三角形右对齐,那么我们应该打印一些空格。几个?好吧,对于一个颠倒的三角形,我们直接使用了row数字。对于右侧向上的三角形,我们需要9 - row星星。但是我们可以简化这一点,通过考虑我们考虑恒星之后的剩余空间。我们总共想要 10 颗星加上空格,因此我们可以简单地减去10 - stars得到空间计数。

当然,如果三角形是左对齐的,那么我们打印零空格。

def triangle(upside_down, right):
for row in range(10):
stars = 10 - row if upside_down else row + 1
spaces = 10 - stars if right else 0
print(' ' * spaces, '*' * stars, sep='')

简单。让我们使用它:

triangle(False, False)
print()
triangle(True, False)
print()
triangle(True, True)
print()
triangle(False, True)

通过首先提取代码,如何迭代该代码变得更加清晰:我们只需要更改triangle调用的参数,并处理中间print。我们有一个明确定义的函数,它做一件事并有一个合理的名称 - 根据一本好的编程书试图教给你的所有原则。

我们如何反复调用具有不同、常量(即预先计算)参数的函数?很简单:我们将这些参数放在一些数据结构中,然后迭代它。要在除最后一个之外的每个triangle之后print,我们的诀窍是使用一些简单的标志逻辑(一个变量,告诉我们要显示什么 - 换行符,或者什么都没有 - 显示无条件更改)之前print第一个之外的每个triangle)。

因此,例如:

# This tells us which values we will use to call `triangle` each time.
configurations = ((False, False), (True, False), (True, True), (False, True))
# This tells us what we will display before each `triangle`.
before_triangle = ''
for upside_down, right in configurations:
print(before_triangle, end='')
before_triangle = 'n'
triangle(upside_down, right)

遍历 n×n 网格并让模式表达式决定是否打印*

n = 10
h = n / 2
patterns = [
lambda: i >= j,
lambda: i+j < n,
lambda: j >= i,
lambda: i+j >= n-1,
]
for p in patterns:
for i in range(n):
for j in range(n):
print(' *'[p()], end='')
print()
print()

输出(在线尝试!

*         
**        
***       
****      
*****     
******    
*******   
********  
********* 
**********
**********
********* 
********  
*******   
******    
*****     
****      
***       
**        
*         
**********
*********
********
*******
******
*****
****
***
**
*
*
**
***
****
*****
******
*******
********
*********
**********

奖金模式:

lambda: max(i,j) >= h,
lambda: abs(i-h)+abs(j-h) < h,
lambda: (i//2 | j//2) % 2,

输出:

*****
*****
*****
*****
*****
**********
**********
**********
**********
**********

*    
***   
*****  
******* 
*********
******* 
*****  
***   
*    
**  **  
**  **  
**********
**********
**  **  
**  **  
**********
**********
**  **  
**  **  

以下是从四个 for 循环中剔除常见逻辑的一种方法,也可以使用字符串乘法来消除内部循环:

patterns = [
[(1,1),   None],
[(-1,10), None],
[(-1,10), (1, 0)],
[(1,1),   (-1,9)]
]
begun = False
for (sign, plus), leftPat in patterns:
print('', end = 'n' * begun)
begun = True
leftSign, leftPlus = leftPat if leftPat else (0,0)
for row in range(10):
print(' ' * (row * leftSign + leftPlus), '*' * (row * sign + plus), sep='')

解释:

我们用星
  • 号参数(必需)和空格参数(可选,换句话说:可以None)的元组对(也是对)的列表填充patterns
  • 我们迭代模式
  • 对于每个模式,如果空间参数 (leftPat)None,我们使用默认值 (0,0)
  • 然后,我们使用字符串乘法打印指示的空格数,后跟模式中每一行的指示数量的星号
  • 还有其他逻辑使用begun在每个模式之间打印空白行

如果末尾的额外空行是可以接受的,则可以进一步简化为:

for (sign, plus), leftPat in patterns:
leftSign, leftPlus = leftPat if leftPat else (0,0)
for row in range(10):
print(' ' * (row * leftSign + leftPlus), '*' * (row * sign + plus), sep='')
print()

最新更新