使用Python绘制沙漏图形是循环嵌套练习中的常见场景,这类需求通常需要先输出上半部分递减的星号行,再输出下半部分递增的星号行,整个过程中变量的作用范围、赋值逻辑如果处理不当,就容易出现变量未定义的报错。下面先通过一张示意图直观展示标准沙漏图形的输出效果。

沙漏图形绘制的基础实现逻辑
沙漏图形的核心结构分为上下两部分,上半部分每行的星号数量从n*2-1递减到1,空格数量从0递增到n-1;下半部分每行的星号数量从3递增到n*2-1,空格数量从n-2递减到0,其中n是沙漏的半高。基础实现的代码示例如下:
n = 3 # 沙漏半高,控制整体大小
# 绘制上半部分
for i in range(n):
space_num = i
star_num = 2 * (n - i) - 1
print(' ' * space_num + '*' * star_num)
# 绘制下半部分
for i in range(n-2, -1, -1):
space_num = i
star_num = 2 * (n - i) - 1
print(' ' * space_num + '*' * star_num)变量未定义错误的常见触发场景
1. 变量在循环外未初始化
如果在循环内部声明变量,却在循环外部调用该变量,就会出现变量未定义的错误。比如下面的错误写法:
n = 3
for i in range(n):
# 变量仅在循环内部定义
temp_space = i
# 循环结束后调用temp_space,此时如果循环未执行就会报错
print(temp_space)当n的值为0时,range(n)不会执行循环,temp_space从未被赋值,调用时就会抛出NameError,提示变量未定义。
2. 变量作用域嵌套错误
如果在嵌套循环中,内层循环使用了外层循环未定义的变量,也会触发报错。例如下面的错误代码:
n = 3
for i in range(n):
# 此处未定义j变量
print(' ' * j + '*' * (2*i+1))代码中直接使用了j变量,但是没有提前对j进行赋值,运行时会直接提示j未定义。
3. 条件分支中变量未覆盖所有情况
如果变量只在if分支中赋值,而没有else分支的赋值逻辑,当条件不满足时变量就未被定义。比如:
n = 3
for i in range(n):
if i % 2 == 0:
line_len = 2*i + 1
# 缺少else分支,当i为奇数时line_len未赋值
print('*' * line_len)当i为1、3等奇数时,line_len没有被赋值,调用时就会触发变量未定义错误。
避免变量未定义错误的方法
1. 提前初始化变量
对于需要在循环或条件分支外使用的变量,要在对应的代码块之前完成初始化,确保变量在任何执行路径下都有值。修改后的示例如下:
n = 3
temp_space = 0 # 提前初始化变量
for i in range(n):
temp_space = i
print(temp_space) # 此时即使n为0,temp_space也有初始值02. 明确变量的作用域范围
嵌套循环中使用的变量,要在对应的循环层级提前定义,避免跨层级调用未定义的变量。正确的沙漏下半部分绘制代码应该明确变量的定义位置:
n = 3
for i in range(n-2, -1, -1):
# 在循环内明确定义需要的变量
space_num = i
star_num = 2 * (n - i) - 1
print(' ' * space_num + '*' * star_num)3. 条件分支覆盖所有执行路径
使用if条件分支时,要搭配else分支,或者对变量设置默认值,确保所有执行路径下变量都有赋值。改进后的代码如下:
n = 3
for i in range(n):
if i % 2 == 0:
line_len = 2*i + 1
else:
line_len = 1 # 奇数情况也赋值
print('*' * line_len)4. 使用IDE的语法检查功能
编写代码时可以使用PyCharm、VS Code等工具,这些IDE会自动检测未定义的变量并给出提示,在运行代码前就可以提前发现这类问题,减少运行时报错的概率。
完整的沙漏绘制无报错示例
结合上述规避方法,完整的沙漏图形绘制代码如下,不会出现变量未定义的问题:
def draw_hourglass(n):
# 上半部分
for i in range(n):
space_num = i
star_num = 2 * (n - i) - 1
print(' ' * space_num + '*' * star_num)
# 下半部分
for i in range(n-2, -1, -1):
space_num = i
star_num = 2 * (n - i) - 1
print(' ' * space_num + '*' * star_num)
draw_hourglass(4)运行上述代码,会输出半高为4的标准沙漏图形,所有变量都在对应的作用域内提前定义,覆盖了所有执行路径,不会出现变量未定义的问题。