我发现自己经常不得不为不同的目的反复更改和调整旧代码,但偶尔会实现两个版本前的相同目的。
一个例子是处理素数的函数。有时我需要的是一个包含 n 个素数的列表。有时我需要的是第 n 个素数。也许我会在未来的功能中遇到第三个需求。
无论如何,我都必须执行相同的过程,但只返回不同的值。我认为必须有更好的方法来做到这一点,而不仅仅是不断更改相同的代码。我想出的可能替代方案是:
返回一个元组或一个列表,但这似乎有点混乱,因为在包括数千个项目的列表中会有各种数据类型。
使用输入语句来指导代码,尽管我宁愿在单击运行时让它为我做所有事情。
弄清楚如何利用类特性来返回类属性并在需要的地方访问它们。这对我来说似乎是最干净的解决方案,但我不确定,因为我还是个新手。
只需为每个可重用功能制作五个版本。
我不想成为一个糟糕的程序员,那么哪个选择是正确的选择?或者也许我可以做一些我没有想到的事情。
你的问题确实很重要。这在程序员的日常生活中很重要。问题是:
我的代码可以重用吗?
如果不是,您将遇到代码冗余,在多个地方有相同的代码行。这是错误的最佳起点。想象一下,您想以某种方式改变行为,例如,因为您发现了一个潜在的问题。然后你在一个地方改变它,但你会忘记第二个位置。尤其是当您的代码达到 1,000、10,0000 或 100,000 行代码等维度时。
它在SRP中进行了总结,即单一职责原则。它指出每个类(也适用于函数)应该只有一个决定,即它“应该只做一件事”。如果一个函数做不止一件事,你应该把它分解成更小的块,更小的任务。
每次遇到(或编写)一个包含超过 10 或 20 行(真实)代码的函数时,您都应该持怀疑态度。此类功能很少遵守此原则。
对于您的示例,您可以将其识别为单独的任务:
yield对我使用)n素数。使用 1. 并将它们放入列表中n素数。使用 1.,但不保存每个数字,只是等待nth。不会像 2. 那样消耗那么多内存。该列表是可扩展的,您可以在任何级别重用它。每个函数都不会超过 10 行代码,而且您不会每次都重新发明轮子。
将它们全部放入一个模块中,并在与素数相关的欧拉问题的每个脚本中使用它。
一般来说,我为我的 Euler 问题脚本创建了一个小型库。您真的可以习惯于在“Project Euler”中编写可重用的代码。
您没有提到的另一个选项(据我所知)是使用可选的关键字参数。如果你认为小的原子函数太复杂(虽然我真的坚持你应该习惯它)你可以添加一个关键字参数来控制返回值。例如,在某些scipy函数中有一个参数full_output,它接受一个布尔值。如果为 False(默认),则仅返回最重要的信息(例如,优化值),如果为 True,则还返回一些补充信息,例如,优化执行的程度以及收敛所需的迭代次数。
你可以定义一个参数output_mode,可能的值"list","last"或者其他什么。
坚持使用小的、可重用的代码块。习惯这一点是您可以在“欧拉计划”中学到的最有价值的东西之一。
如果您尝试实现我为可重用函数提出的模式,您可能会在第 1 点立即遇到问题:如何为此创建生成器样式的函数?例如,如果您使用筛分法。但也不算太糟。