科学Python代码的可读性(换行符、变量名、导入)



Python的风格最佳实践适用于科学编码吗?

我发现很难保持科学Python代码的可读性。

例如,建议为变量使用有意义的名称,并通过避免import *来保持命名空间的有序性。因此,例如:

    import numpy as np
    normbar = np.random.normal(mean, std, np.shape(foo))

但这些建议可能会导致一些难以阅读的代码,尤其是考虑到79个字符的线宽。例如,我刚刚写了以下操作:

net["weights"][ix1][ix2] += lrate * (CD / nCases - opts["weightcost_pretrain"].dot(net["weights"][ix1][ix2]))

我可以跨越行来表达:

net["weights"][ix1][ix2] += lrate * (CD / nCases - 
     opts["weightcost_pretrain"].dot(net["weights"][ix1][ix2]))

但这似乎并没有好到哪里去,我不确定第二行缩进有多深。当一行被双缩进到嵌套循环中,并且一行只有50个字符可用时,这些类型的行延续会变得更加棘手。

我应该接受科学Python看起来很笨重,还是有办法避免像上面的例子那样的行?

一些潜在的方法是:

  • 使用较短的变量名
  • 使用较短的字典关键字名称
  • 直接导入numpy函数并为其指定短名称
  • 为算术运算的组合定义辅助函数
  • 将操作分解为更小的部分,并在每条线上放置一个

我希望你能明智地选择其中的哪一个,避免哪一个以及其他补救措施的建议。

  • 为算术运算的组合定义辅助函数
  • 将操作分解为更小的部分,并在每条线上放置一个

这两个想法都很好——符合PEP8背后的意图,也符合Python风格。事实上,每当有人建议修改PEP 8以提供更多关于长队的信息时,一半的回答通常是"如果你超过了底线,你可能在一个表达中做得太多了"。

而且,更普遍地说,分解代码并为合理的操作提供合理的名称总是一个好主意。

当然,在不知道所有这些东西到底代表什么的情况下,我只能猜测如何将它们分开,但我认为这样的东西会非常可读和有意义:

cost = opts["weightcost_pretrain"].dot(net["weights"][ix1][ix2])
weight = lrate * (CD / nCases - cost)
net["weights"][ix1][ix2] += weight

我认为风格指南总是适用的-我每天都在科学工作中使用Python,发现如果我把长行分解成逻辑组件和合理的变量名,或者使用了一个函数,我可以更容易地阅读代码,几个月后就可以毫不费力地返回代码。

我会做一些更像这样的事情:

weights = net["weights"][ix1][ix2]
opts_arr = opts["weightcost_pretrain"]
weights += lrate * (CD / nCases - opts_arr.dot(weights))

Python"简洁"的另一种说法是,Python在语法上很密集,我发现阅读和理解一长串Python比阅读和理解Java更难(尤其是当使用第三方库中隐藏低级逻辑的高级函数时,如NumPy)。

最新更新