模块化、可重用的代码
你的问题确实很重要。这在程序员的日常生活中很重要。这是一个问题:
我的代码可以重用吗?
如果不是,您将遇到代码冗余,在多个地方有相同的代码行。这是 bug 的最佳起点。想象一下,你想以某种方式改变行为,例如,因为你发现了一个潜在的问题。然后你在一个地方改变它,但你会忘记第二个位置。尤其是当您的代码达到 1,000、10,0000 或 100,000 行代码时。
它在SRP中进行了总结,即单一职责原则。它指出每个类(也适用于函数)应该只有一个决定,即它“应该只做一件事”。如果一个函数做不止一件事,你应该把它分成更小的块,更小的任务。
每次遇到(或编写)包含超过 10 或 20 行(实际)代码的函数时,您都应该持怀疑态度。这样的功能很少坚持这个原则。
对于您的示例,您可以将其标识为单个任务:
- 一个一个地生成素数(生成意味着
yield
为我使用)
- 收集
n
素数。使用 1. 并将它们放入列表中
- 得到
n
素数。使用 1.,但不保存每个数字,只是等待n
th。不像 2. 那样消耗内存。
- 查找素数对:使用 1.,记住前一个数,如果与当前数的差为 2,则产生这对
- 收集所有素数对:使用 4. 并将它们放入列表中
- ...
- ...
该列表是可扩展的,您可以在任何级别重复使用它。每个函数的代码不会超过 10 行,而且您不会每次都重新发明轮子。
将它们全部放入一个模块中,并从每个脚本中使用它来解决与素数相关的欧拉问题。
一般来说,我为我的欧拉问题脚本创建了一个小型库。你真的可以习惯在“Project Euler”中编写可重用的代码。
关键字参数
您没有提到的另一个选项(据我所知)是使用可选关键字参数。如果你认为小的原子函数太复杂(尽管我真的坚持你应该习惯它),你可以添加一个关键字参数来控制返回值。例如,在某些scipy
函数中有一个参数full_output
,它接受一个布尔值。如果为 False(默认),则仅返回最重要的信息(例如,优化值),如果为 True,则还返回一些补充信息,例如,优化执行得有多好以及需要多少次迭代才能收敛。
你可以定义一个参数output_mode
,可能的值"list"
,"last"
或者其他任何东西。
推荐
坚持使用小的、可重用的代码块。习惯这一点是您可以在“Project Euler”中获得的最有价值的东西之一。
评论
如果您尝试实现我为可重用函数提出的模式,您可能会在第 1 点立即遇到问题:如何为此创建生成器样式的函数?例如,如果您使用筛法。但这还不错。