装饰器

2022-09-23  本文已影响0人  Python_Camp
def my_function(a, b):
    return a + b

还有很多决定要留给代码的作者去做。你是否应该使用类型提示来表明参数的数据类型?你也许应该写一个文档串来解释这个函数的作用。如何实现逻辑仍然是100%由你决定的。你根本不需要把精力放在思考风格的选择上。

我建议你花10-15分钟浏览一下PEP8的风格指南,以吸取一些改进意见。每当你对某个特定的选择不确定时,你可以参考PEP8。

自动代码格式化器
也有像Black这样的自动代码格式化器,可以为你自动格式化代码。这些都是很好的! 然而,你应该知道,它们有局限性。

举个例子,PEP8建议在Python中用Error这个词来结束一个自我定义的异常类。因此,一个代表数据处理错误的类的开头应该写成,例如

class DataProcessingError(Exception)。
---

这是像Black这样的自动格式化器无法为你解决的问题。通过各种方式,使用Black这样的自动格式化器。但还是要确保对PEP8的大部分内容烂熟于心。

但我不想这样做!

照片:Matthew Henry on Unsplash
有一些读者声称,代码格式和代码风格并不重要。如果你真的没有看到PEP8的重要性,那么这是很合理的。只是要知道,如果你不遵守它,许多人就会认为你的代码质量差。格式不好的代码会让人产生期待,就像到处都是拼写错误的邮件。

3 - 变量名--比听起来更难!
在Python中给变量、函数、类、模块和包命名是一项艰苦的工作。事实上,Phil Karlton 有以下的名言。

在计算机科学中只有两件难事:缓存失效和命名事物。- 菲尔-卡尔顿

幸运的是,大多数数据科学家不需要处理缓存失效的问题。然而,你却被命名的事情所困扰。Python包和模块应该有简洁的全小写的名字。让我们讨论一下如何给我们的宝贝们起好名字;变量、函数和类。

简单的--约定
有几个简单的约定,一个人应该始终遵守。

首先,永远不要重写一个内置的东西。举个例子,创建以下变量可能是很诱人的。

a = 5
b = 2
min = 0
if a < b:
    min = a
else:
    min = b

上面的代码用一个变量min覆盖了内置函数min()。现在,如果你试图使用内置的min()函数,你的程序将会崩溃。引用《教父》的一句话:"看看他们是如何屠杀我的孩子的!" 😧

其次,对于变量、函数和类,有一些PEP8的惯例你应该遵守。变量和函数的名称都应该是小写的,其中不同的字用下划线隔开。

my_variable = 5
def my_function(a, b):
   return a + b

如果一个变量打算在整个程序中保持不变,那么你可以把它写成大写字母来表示。

my_nonchanging_variable = 5
对于类来说,它们的名字应该用大写的单词连接起来,如下所示。

class MyAwesomeClass()
---

上面的变量名称的具体选择并不具有很强的信息量。这就是我们现在要讨论的命名的困难部分。

困难-主观性
命名事物的困难之处在于不遵循上述的惯例。困难的部分是选择能够简洁地表明实体是什么(对于变量和类)或它做什么(对于函数)的名称。下面是我想强调的一些准则(适用于变量)。

仔细挑选长度。变量名称不应该太短或太长。太短的变量名,你最终会使用不是每个人都能理解的缩略语。你能说出c = 7或vprice = 5这些变量代表什么吗?断章取义,这些变量名有多糟糕是显而易见的。但是它们也可以扩展得太长,写成:

count_of_how_many_steps_our_pipeline_has = 7
variance_of_column_price_in_our_dataset = 5

现在它是可以理解的,但阅读起来却是一场噩梦。试着找到一个合适的中间点。

pipeline_steps = 7,variance_price = 7

怎么样?
不要提到数据类型。把变量的数据类型悄悄放在名称中往往是很诱人的。我们中的许多人都曾犯过将Pandas数据框架称为df_new的错误。

我们的想法是,通过偷偷加入df作为数据框架的缩写,你可以向读者表明这是一个数据框架。这种方法被称为 "匈牙利符号",在很大程度上是不可取的。

在Python中,你可以用type()函数很容易地检查某个东西的类型。如果你也在使用类型提示,那么匈牙利符号就完全没有用处了。我建议宁可把你可用的 "变量名里程 "用在更有用的地方。

使用直观的领域语言。你已经存储了西兰花、芹菜和甜菜等变量,这些变量统计了各自出售的蔬菜的数量。你现在需要一个容器类型(如字典)来存储所有这些变量。你怎么称呼这个字典呢?别担心,这不是一个骗人的问题。我不知道你怎么想,但我想把它叫做蔬菜。

尽可能地使用直观的领域语言。唯一的例外是,如果你期望你的代码被扩展到领域知识不再有意义的情况下。

对于函数,适用上述同样的准则(请不要将 "函数 "一词嵌入你的函数名称中)。唯一值得注意的是,函数通常是做一些事情而不是包含一些东西。因此,函数通常被赋予动作词(动词)以强调它们的作用。像prune_tree()和recommend_item()这样的名字就很好。

希望我已经说服了你,花一些时间给你的变量命名是值得的。在某些情况下,打破上述准则将是你最好的行动方案。例如,API(应用程序编程接口)的缩写是众所周知的。因此,名称为api_password的(私有!)变量是完全可以的。使用你自己的判断!

4 - 模块化你的代码
不是所有的代码都是平等的。有些代码很难扩展。有些代码不容易被重复使用。有些代码很难检查出错误。在所有这些方面进行改进的方法是将你的代码模块化。

这在实践中是什么意思呢?你的代码应该被划分为函数和类。这些函数和类又应该被归入 Python 模块。为什么要这样做呢?

考虑一下那些没有以任何方式分组的代码 (你可能认为这些代码是 "自由漂浮 "的)。这在一开始写起来当然很方便。然而,随着代码的增长,它变得越来越麻烦。

你不得不复制和粘贴代码来进行小的调整。现在,如果你想扩展它,你必须在所有重复的地方改变代码。天知道如果有同事要求使用你的代码中的某个功能,你会怎么做--一切都完全交织在一起。不要让我开始讨论如何检查你的代码中的错误。

一开始只是为了方便,现在却变成了一场噩梦😧。

解决办法是什么?你应该定期地将你的代码重构为函数和类。让我们来看看函数的情况。一个函数是一段可重复使用的代码。当你的代码在逻辑上被分组为函数时,你可以。

很容易重复使用一些代码。由于一个函数是一个独立的片段,你可以将该特定的函数导出到其他设置中。也许你已经开发了一个很棒的函数

clean_missing_values()

来清理数据集中的缺失值。现在你也可以在其他项目中使用这个函数(只需做最小的调整)。

轻松地检查你的代码中的bug。函数可以通过单元测试来测试错误。在编写Python时,最常见的编写单元测试的库是Unittest和(我最喜欢的)Pytest。
轻松地添加文档,使之更加清晰。

通过函数,你可以添加文档,解释它们的作用。你还可以给函数添加类型提示,向其他开发者和数据科学家解释输入和输出的数据类型。你会发现,一旦项目的复杂性增加,模块化的代码就会容易理解很多。

特别是对于数据科学家来说,代码经常被留在Jupyter笔记本单元中,完全没有模块化。这使得上述所有的问题如果长期得不到解决,就会变得活灵活现。

不要误会我的意思。Jupyter笔记本是数据探索和测试出机器学习模型的一个伟大工具。然而,请确保你设定一个时间,将代码重构为可维护的部分(函数和类)。

通过这样做,从长远来看,你会为自己节省很多痛苦。另外,你会成为团队中测试员/开发员最喜欢的人,这总是一个加分项😅。

5 -设计原则?没听说过!
你不使用设计原则?

通常情况下,设计原则是软件开发人员预先关注的东西。许多数据科学家的印象是,设计原则其实与他们没有太大关系。对于这种说法,我想指出Adam Judge关于一般设计的名言。

"好设计的替代品总是坏设计。不存在没有设计这回事。"--Adam Judge

亚当-贾奇肯定是在从视觉的角度谈论设计。然而,我认为这个结论对于写代码时的设计原则仍然是成立的。通过写代码,你正在使用设计原则。你也许只是没有很好地使用它们。

让我们从一些设计原则开始,来提高你的总体代码质量吧

可爱的首字母缩写词😍
照片:Gary Bendig on Unsplash
首先,有一些可爱的首字母缩写词正在被抛来抛去。你应该把这些当成指导原则,在写代码时牢记在心。

KISS: Keep It Simple Silly -
这个很直接。尽可能地减少复杂性。让我们举个例子。假设你想算出1到1000之间有多少个非平方数。

回顾一下,非平方数n只是一个不能用n=m**2来表示其他数字m的数字,下面的代码可以解决我们的问题。


non_square_numbers = len(set(range(1, 1001)).difference(set(map(lambda x: x ** 2, range(1, 1001))))))

诚实点吧。虽然上面的代码解决了问题(甚至使用了集合和map函数等很酷的功能),

但它看起来很可怕。你可能花了一些时间来阅读它。它太复杂了。请考虑以下的简化方案。

从数学输入sqrt

non_square_numbers = list(range(1, 1001))
for n in range(1, int(sqrt(1001)):
    non_square_numbers.remove(n ** 2)

新的代码不仅更清晰,而且更快。我只需要运行到1001的平方根的数字,因为我正在对数字进行平方运算。

从KISS中得到的教训是,有时让你的代码长一点也是值得的,如果它能让人更容易理解的话。

DRY:不要重复自己--这个原则鼓励将你的代码模块化为函数。通过这样做,你可以避免代码的重复。事实上,只要你发现自己有重复的代码,你就应该把你的代码模块化。

YAGNI: You Ain't Gonna Need It - 这个原则鼓励你不要过度设计解决方案。让我们来做一个具体的例子。

假设你正在编写一个数据管道,第一步是一个从SQL数据库中读取的函数。也许在未来,你还需要读取CSV文件。所以你也要实现这个功能。也许在未来,你还需要读取XML。或者JSON。或者Parquet文件。

在这种情况下,YAGNI的原则很简单。不要。你可能不需要所有的扩展,而且你写的代码永远不会被使用。相反,要确保你的代码有可能被扩展。但要把实际的扩展留到你真正有具体需要的时候再做。

遵循YAGNI原则,你的代码库会更小,需要担心的松散线程也会减少。

SOLID设计原则

一组成熟的设计原则(特别是在OOP中)是SOLID原则。它们形成了一组经过测试的设计原则,在过去的几十年里被大量使用。SOLID的五个设计原则是。

S - 单一责任原则
O--开放-封闭原则
L - 利斯科夫替代原则
I--接口隔离原则
D - 依赖性反转原则

并非所有的SOLID原则在数据科学中都同样有用。事实上,我很少在数据学科中使用Liskov的替代原则。不要误会我的意思,这是一个伟大的设计原则,我对Barbara Liskov非常尊敬。然而,在大量使用OOP的软件工程中,它肯定更有用。我认为SOLID原则中对数据科学家最重要的是单一责任原则。

单一责任原则指出,函数(以及类)应该有单一的责任。让我们通过一个例子来探讨这意味着什么。

假设你有一个函数process_data(),它将CSV文件加载为Pandas Dataframe,删除缺失的值,选择一些特征,然后最后绘制这些特征图。你的函数process_data()现在有四个职责:导入数据、清理数据、提取特征和绘图。为什么这样不好呢?

首先,现在要把你的代码输出到其他设置中去,难度就大了。你可能已经在函数process_data()中编写了顶级的缺失值清洗代码。你如何在其他地方使用这段代码,比如说,特征提取是不可能的?不是那么简单。

测试你的代码是否有错误也比较困难。通过做多件不同的事情,有更多的地方可以让bug隐藏。

单一责任原则建议将函数process_data()分成四个函数。这些函数可以被称为

import_csv_data()
clean_missing_values()
extract_features()
plot_features()

这样一来,每个函数都有一个单独的责任😃。

6 - 代码质量的进一步资源

我已经给了你一些提高代码质量的起点。接下来你应该到哪里去寻找关于这个主题的更多信息?

代码风格。

除了用心学习PEP8和使用有效的代码格式(如Black或autopep8)之外,真的没有更多的东西。如果你想确保你执行了这一点,那么就要求做代码审查的人对代码风格进行反馈。你可能还想研究一下PEP257中的Python惯例,以编写正确的文档说明。

变量名。我在这里最好的建议是注意你选择的变量名。除此以外,我在 Al Sweigart 的书《Beyond the Basic Stuff with Python》中发现了许多有趣的观点。

模块化的代码。编写模块化的代码需要努力。如果你不确定何时(以及如何)使用类,可以考虑学习更多关于OOP(面向对象的编程)的知识。我可以推荐免费的YouTube系列Python OOP教程作为一个好的起点。

除此之外,我建议你熟悉Python函数的每个方面,这样你就可以有效地使用它们。如果你不知道Python函数默认返回的值是None,那么你的代码可能会反映出这种知识的缺乏。

设计原则。我只是给了你一个关于设计原则的小建议。有一些关于这个主题的经典书籍,以及专门针对数据科学的书籍。不过,我还是要向你推荐ArjanCodes的YouTube视频。它们的质量非常高,而且对许多设计原则进行了专门的介绍。

7 - 总结

照片:Spencer Bergen on Unsplash
希望你在成为一个高质量的代码生产者的道路上走得更远。如果你的代码不是一夜之间就能完美的,也不要担心。获得高的代码质量是一个漫长的旅程,我仍然每天都在努力。

喜欢我的文章吗?请查看我的其他一些文章,了解更多的Python内容。

用美丽的类型提示Python代码现代化
在Python中可视化缺失值是令人震惊的简单。
用PyOD介绍Python中的异常/异样检测 🔥
5个强大的NumPy函数能在关键时刻救你一命
5个专家提示,让你在Python中的字典技能突飞猛进 🚀
如果你对数据科学、编程或两者之间的任何事情感兴趣,那么请随时在LinkedIn上添加我并打招呼 ✋

本文由mdnice多平台发布

上一篇下一篇

猜你喜欢

热点阅读