Python生成矩形内所有点:如何以更Pythonic方式优化重复代码
嘿,你的方法能正常运行真是太棒了!重复代码不仅看起来乱糟糟的,后续改逻辑也容易出纰漏,咱们来用更Pythonic的方式把它重构一下,彻底干掉那些重复的代码块。
首先我猜你的原始代码大概是类似这样的(毕竟是四段顺时针遍历的逻辑):
def generate_rect_pixels(min_x, max_x, min_y, max_y): # 上边:左到右遍历 for x in range(min_x, max_x + 1): yield (x, min_y) # 右边:上到下遍历 for y in range(min_y + 1, max_y + 1): yield (max_x, y) # 下边:右到左遍历 for x in range(max_x - 1, min_x - 1, -1): yield (x, max_y) # 左边:下到上遍历 for y in range(max_y - 1, min_y, -1): yield (min_x, y)
针对这种重复的遍历逻辑,有两种很Pythonic的优化思路:
方案1:抽象参数,用统一逻辑处理所有边
咱们可以把每个边的遍历规则(固定坐标、遍历范围、步长、坐标顺序)整理成参数列表,然后用一段通用代码循环处理所有边:
def generate_rect_pixels(min_x, max_x, min_y, max_y): # 每个元组代表一条边的规则:(固定坐标值, 遍历起始, 遍历结束, 步长, 是否先放遍历值) edges = [ (min_y, min_x, max_x + 1, 1, True), # 上边:遍历x,固定y=min_y (max_x, min_y + 1, max_y + 1, 1, False), # 右边:遍历y,固定x=max_x (max_y, max_x - 1, min_x - 1, -1, True), # 下边:反向遍历x,固定y=max_y (min_x, max_y - 1, min_y, -1, False) # 左边:反向遍历y,固定x=min_x ] for fixed_val, start, end, step, is_traversed_first in edges: for val in range(start, end, step): yield (val, fixed_val) if is_traversed_first else (fixed_val, val)
这种写法把所有边的规则集中在一处,后续要调整某个边的遍历范围或方向,直接修改对应参数即可,代码复用性和可读性都拉满。
方案2:用生成器表达式+yield from简化
如果觉得抽象参数有点繁琐,也可以用生成器表达式拆分每个边的逻辑,再用itertools.chain串联起来,写法更紧凑:
from itertools import chain def generate_rect_pixels(min_x, max_x, min_y, max_y): top = ((x, min_y) for x in range(min_x, max_x + 1)) right = ((max_x, y) for y in range(min_y + 1, max_y + 1)) bottom = ((x, max_y) for x in range(max_x - 1, min_x - 1, -1)) left = ((min_x, y) for y in range(max_y - 1, min_y, -1)) yield from chain(top, right, bottom, left)
这种方式没有完全消除重复的定义,但比原始的四段循环整洁很多,而且利用了Python生成器和yield from的特性,非常符合Python的简洁风格。
额外小提示:边界情况适配
上面两种方案都能自动处理min_x == max_x或min_y == max_y的特殊情况(比如矩形变成一条线或单个像素),因为range在起始和结束相等时会生成空序列,不会重复生成无效的点,逻辑依然通顺。
内容的提问来源于stack exchange,提问作者bzier
相关产品推荐
相关产品推荐

