编写可重用的代码

时间:2013-02-08 06:38:31

标签: python

我发现自己经常不得不为了不同的目的而反复改变和修改旧代码,但偶尔会实现两个版本之前的相同目的。

这方面的一个例子是处理素数的函数。有时我需要的是一个n素数列表。有时我需要的是第n个素数。也许我会从路上的功能中遇到第三个需求。

我做任何事情虽然我必须做同样的过程但只返回不同的值。我认为必须有一个更好的方法来做到这一点,而不仅仅是不断改变相同的代码。我提出的可能的替代方案是:

  1. 返回一个元组或列表,但这似乎有点混乱,因为包含数千个项目的列表中会有各种数据类型。

  2. 使用输入语句来指导代码,但我宁愿让它在我点击运行时为我做一切。

  3. 弄清楚如何利用类功能返回类属性并在需要的地方访问它们。这对我来说似乎是最干净的解决方案,但我不确定,因为我还是新手。

  4. 只需为每个可重复使用的功能制作五个版本。

  5. 我不想成为一个糟糕的程序员,所以选择哪个是正确的选择?或者也许我可以做一些我没想过的事情。

3 个答案:

答案 0 :(得分:4)

模块化,可重复使用的代码

你的问题确实很重要。这对程序员的日常生活很重要。这是个问题:

我的代码是否可以重复使用?

如果不是,您将遇到代码冗余,在多个地方使用相同的代码行。这是bug的最佳起点。想象一下,你想以某种方式改变行为,例如,因为你发现了一个潜在的问题。然后你在一个地方改变它,但你会忘记第二个位置。特别是如果您的代码达到1,000,10,0000或100,000行代码的维度。

总结在 SRP Single-Responsibilty-Principle中。它指出每个类(也适用于函数)应该只有一个决定,它“应该只做一件事”。如果一个函数不止一件事,你应该将它分成更小的块,更小的任务。

每次遇到(或写入)超过10或20行(实际)代码的函数时,您都应该持怀疑态度。这些功能很少遵循这一原则。

对于您的示例,您可以将其识别为单个任务:

  1. 逐个生成素数(生成暗示我使用yield
  2. 收集n素数。使用1.并将它们放入列表
  3. 获得n素数。使用1.,但不保存每个数字,只等待n。不会消耗尽可能多的内存。
  4. 查找素数对:使用1.,记住前一个数字,如果与当前数字的差异为2,则产生此对
  5. 收集所有素数对:使用4.并将它们放入列表
  6. ...
  7. ...
  8. 该列表是可扩展的,您可以在任何级别重用它。每个函数都不会超过10行代码,每次都不会重新发明轮子。

    将它们全部放入一个模块中,并在每个脚本中使用它来处理与素数相关的欧拉问题。

    总的来说,我为Euler Problem脚本启动了一个小型库。你真的可以习惯在“Project Euler”中编写可重用的代码。

    关键字参数

    你没有提到的另一个选项(据我所知)是使用可选的关键字参数。如果你认为小的原子函数太复杂了(虽然我真的坚持你应该习惯它),你可以添加一个关键字参数来控制返回值。例如,在一些scipy函数中有一个参数full_output,它带有一个bool。如果它是假的(默认),则仅返回最重要的信息(例如,优化值),如果它是真的,则返回一些补充信息,例如,优化执行的程度以及收敛所花费的迭代次数。 / p>

    您可以定义参数output_mode,其中包含可能的值"list""last" ord。

    建议

    坚持使用可重复使用的小块代码。习惯这是你可以在“Project Euler”中获得的最有价值的东西之一。

    备注

    如果您尝试实现我为可重用函数提出的模式,您可能会在第1点立即遇到问题:如何为此创建生成器样式的函数?例如,如果您使用筛子方法。但它并不太糟糕。

答案 1 :(得分:0)

我的猜测,创建包含以下内容的模块:

  1. 私有核心功能(例如:第n个第一个素数的返回列表,甚至更通用的东西)
  2. 几个使用核心的包装器/ util函数,并以不同的方式准备输出。 (例如:第n个素数)

答案 2 :(得分:0)

尝试尽可能减少您的功能,并重复使用它们。

例如,您可能有next_primen_primes重复调用的函数n_th_prime

这也使您的代码更易于维护,就像您想出一种更有效的方法来计算素数一样,您只需更改next_prime中的代码。

此外,您应该尽可能使输出保持中性。如果你的函数返回了几个值,它应该返回一个list或一个生成器,不是一个逗号分隔的字符串。