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