Python生成曼德博集合的单行晦涩代码工作原理解析
曼德博集合Python单行代码原理解析
这段晦涩单行代码的核心是用匿名lambda实现了曼德博集合的核心迭代逻辑,绕的写法主要是为了在不使用def定义命名函数的前提下实现递归。
1. 各变量的定义与来源
所有变量的绑定逻辑顺着调用链拆解如下:
a:最外层第一个lambda的形参,这个lambda被调用时,传入的实参是后面实现迭代逻辑的递归核心lambda,作用是把递归函数自身传入内部,解决lambda无法直接自引用递归的问题,是极简Y不动点组合子的实现部分。s:递归核心lambda的第一个形参,接收的实参就是递归函数自身(和外层的a指向完全相同的函数对象),用来在迭代逻辑内部触发下一轮递归调用。z:曼德博迭代过程中的当前复数值,初始调用时传入固定值0,每一轮递归都会更新为z*z + c,当递归终止时返回最终的z值,用来计算模长判断点是否属于曼德博集合。c:复平面上待判定点的复数坐标,短测试代码里取值为0.02*x + 0.05j*y,长代码里是遍历x、y坐标范围映射到复平面的每个采样点,整个迭代过程中c的值固定不变。n:剩余迭代次数,短测试代码初始传入10、长代码初始传入40,每完成一轮递归n就减1,当n等于0时停止迭代,返回当前的z值。- 补充:代码里的
x、y是复平面坐标的映射参数,短测试代码里是提前赋值的固定值,长代码里是双层循环遍历的行列索引,用来把字符画的行列位置映射到复平面的对应坐标。
2. 改写为常规函数的实现与调用
原来的嵌套lambda写法纯粹是为了压缩成单行、用匿名函数实现递归,换成常规def定义函数的写法逻辑会非常清晰,不需要绕高阶函数传自身的逻辑:
核心迭代函数定义
def mandel_iter(z, c, n): # 迭代次数耗尽,返回最终z值 if n == 0: return z # 按曼德博公式更新z,剩余迭代次数减1,继续递归 return mandel_iter(z * z + c, c, n - 1)
短测试代码对应调用
x = 10 y = 5 # 初始z=0,传入对应c值,迭代10次后取模长 res = abs(mandel_iter(0, 0.02*x + 0.05j*y, 10)) print(res)
完整分形字符画实现
对应原来的长代码,改写后逻辑和输出完全一致:
def mandel_iter(z, c, n): if n == 0: return z return mandel_iter(z * z + c, c, n - 1) canvas = [] # 遍历字符画的行(对应复平面虚轴) for y in range(-20, 20): line = [] # 遍历字符画的列(对应复平实轴) for x in range(-80, 20): c = 0.02 * x + 0.05j * y z_final = mandel_iter(0, c, 40) # 迭代后模长小于2判定为集合内点,输出*,否则输出空格 line.append('*' if abs(z_final) < 2 else ' ') canvas.append(''.join(line)) print('\n'.join(canvas))
注:曼德博集合的判定规则为:从z=0开始迭代
z = z² + c,若经过足够多次迭代后z的模长始终小于2,则点c属于曼德博集合,这段代码就是完全按照这个规则实现的。
内容的提问来源于stack exchange,提问作者Ivar Wine
相关产品推荐
相关产品推荐

