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