我正在从教科书中学习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()