首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Sierpiński用于教学Python3的地毯分形动画

Sierpiński用于教学Python3的地毯分形动画
EN

Code Review用户
提问于 2019-01-30 17:01:22
回答 1查看 726关注 0票数 13

我正在教授编程(在本例中--1对1辅导对编程感兴趣的青少年),这段代码将是进展的最后一个阶段,用于生成Sierpiński三角形的良好图像。

欢迎对此代码进行改进的任何评论!但是,不明确的代码违反标准实践的问题尤其受欢迎,性能问题在这里不太重要。

代码语言:javascript
复制
from PIL import Image
from PIL import ImageDraw


def save_animated_gif(filename, images, duration):
    # done using https://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html#saving
    first_image = images[0]
    other_images = images[1:]
    first_image.save(filename, save_all=True, append_images=other_images, duration=duration, loop=0)

def make_pattern(draw, x, y, section_size, remaining_levels):
    if remaining_levels <= 0:
        return
    hole_color = (5, 205, 65)
    corner = (x + section_size / 3, y + section_size / 3)
    # -1 necessary due to https://github.com/python-pillow/Pillow/issues/3597
    opposite_corner = (x + section_size * 2/3 - 1, y + section_size * 2/3 - 1)
    draw.rectangle((corner, opposite_corner), fill=hole_color)
    parts = 3
    for x_index in range(parts):
        for y_index in range(parts):
            x_anchor = x + section_size * x_index / parts
            y_anchor = y + section_size * y_index / parts
            new_size = section_size / 3
            new_levels = remaining_levels - 1
            make_pattern(draw, x_anchor, y_anchor, new_size, new_levels)


def make_carpet(levels, size):
    carpet_color = (5, 60, 20)
    carpet = Image.new("RGBA", (size, size), carpet_color)
    draw = ImageDraw.Draw(carpet)
    make_pattern(draw, 0, 0, size, levels)
    return carpet


levels = 7
size = 3**levels
carpets = []
carpets.append(make_carpet(0, size))
standard_frame_time_in_ms = 1200
durations = [standard_frame_time_in_ms / 2] # first stage visible for a short time
for i in range(levels - 1):
    carpets.append(make_carpet(i + 1, size))
    durations.append(standard_frame_time_in_ms)
durations[-1] *= 4 # final stage of animation visible for a long time

save_animated_gif("Sierpiński's carpet.gif", carpets, durations)

产出:

全尺寸图像

EN

回答 1

Code Review用户

发布于 2019-01-30 18:06:07

我只有几个小小的建议:

我喜欢有“调整”,我可能想要更改稍后在我的文件顶部。这使得在不需要挖掘代码的情况下快速修改它们变得更容易了。我会把levelsstandard_frame_time_in_ms移到顶端,这样它们就更容易访问了。我还可能将levels更改为n_levels或类似的东西,以使其更清楚地表明它是一个代表有多少个级别的数字,而不是一个“级别”的集合。

现在,您正在使用减半的时间延迟部分填充durations,然后在循环中添加其余部分。不过,在循环中,我并不认为appenddurations是一个很好的理由。添加到durations中的数据与循环中可用的数据无关。

我会在循环之前把它填充进去。列表乘法使这很容易。不幸的是,长变量名称很难简洁地完成,但如果需要,可以将其拆分为两行:

代码语言:javascript
复制
durations = [standard_frame_time_in_ms // 2] + [standard_frame_time_in_ms] * (levels - 1)

durations = [standard_frame_time_in_ms // 2] + \
                [standard_frame_time_in_ms] * (levels - 1)

我还将其更改为使用整数除法(//),因为毫秒的分数可能不会被GIF制造商使用。

我会把整个程序放在最下面的一个函数中:

代码语言:javascript
复制
def main():
    carpets = []
    carpets.append(make_carpet(0, size))

    durations = [standard_frame_time_in_ms / 2] # first stage visible for a short time

    for i in range(levels - 1):
        carpets.append(make_carpet(i + 1, size))
        durations.append(standard_frame_time_in_ms)

    durations[-1] *= 4 # final stage of animation visible for a long time

    save_animated_gif("Sierpiński's carpet.gif", carpets, durations)

现在,您可以在希望main运行时调用它。特别是在使用REPL进行开发时,拥有长期运行的顶级代码可能会很痛苦。您不一定只因为加载了文件就想让整个程序运行。

你有:

代码语言:javascript
复制
carpets.append(make_carpet(0, size))

然后在循环中有:

代码语言:javascript
复制
carpets.append(make_carpet(i + 1, size))

我不喜欢这样的复制。通常有更好的方法。似乎您可以调整range的界限:

代码语言:javascript
复制
def main():
    carpets = []

    . . .

    for i in range(-1, levels - 1): # Start at -1 instead
        carpets.append(make_carpet(i + 1, size))

    . . .

不过,这基本上只是一个从range到地毯列表的转换。当将一个序列“转换”到另一个序列时,就会想到理解:

代码语言:javascript
复制
carpets = [make_carpet(i + 1, size) for i in range(-1, levels - 1)]

然后,如果将来证明这是有益的,那么只需将[]更改为()就可以轻松地使它变懒:

代码语言:javascript
复制
# Now it's a generator that only produces values as requested instead of strictly
carpets = (make_carpet(i + 1, size) for i in range(-1, levels - 1))
票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/212564

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档