如果你对数据科学感兴趣,你可能对这个工作流程很熟悉:通过运行Jupyter笔记本开始一个项目,然后开始编写python代码,运行复杂的分析,甚至训练模型。随着笔记本文件的函数、类、图表和日志的大小不断增长,您会发现自己面前堆积着一大堆代码。运气好的话,一切都会顺利进行。那你真的很好!然而,Jupyternotebooks隐藏了一些严重的陷阱,这些陷阱可能会使编码变成一场噩梦。让我们看看这是如何发生的,然后讨论防止这种情况发生的最佳编码方法。JupyterNotebook的问题通常,如果您尝试将Jupyter原型制作提升到一个新的水平,事情可能不会按照您预期的方式进行。以下是作者在使用该工具时遇到的一些情况,你应该很熟悉:一旦所有对象(函数或类)都被定义和实例化,可维护性就变得非常困难:即使你想对功能,也必须在笔记本中的某个地方修复,然后重新运行重新编码。你绝对不希望这种情况发生。将逻辑和处理功能分离在外部脚本中不是更简单吗?由于其交互性和即时反馈,jupyternotebook激励数据科学家在全局命名空间中声明变量而不是使用函数。这是python开发中的不良做法,它限制了有效的代码重用。可重复性也会受到影响,因为笔记本电脑变成了一个包含所有变量的大型状态机。在此配置中,您必须记住哪些结果被缓存,哪些没有缓存,并且您必须期望其他用户遵循您的单元执行顺序。笔记本在后台格式化的方式(JSON对象)使代码版本控制变得困难。这也是为什么我很少看到数据科学家使用GIT来提交不同版本的笔记本,或者合并分支来实现特定功能的原因。结果,团队协作变得低效和笨拙:团队成员开始通过电子邮件或Slack交换代码片段和笔记本,回滚到以前的代码版本成为一场噩梦,文件组织开始变得一团糟。这是我在没有适当版本控制的情况下使用Jupyternotebooks两到三周后通常在项目中看到的:analysis.ipynbanalysis_COPY(1).ipynbanalysis_COPY(2).ipynbanalysis_FINAL.ipynbanalysis_FINAL_2.ipynbJupyternotebooks非常适合探索和快速制作原型。它们当然不是为可重用性或生产用途而设计的。如果您使用Jupyternotebook开发了数据处理管道,最好的情况是代码仅按单元执行顺序在notebook或VM上线性同步运行。但这并没有说明您的代码在更复杂的环境中的行为方式,例如更大的输入数据集、其他异步并行任务或更少的资源分配。我们实际上很难测试笔记本,因为它们的行为有时是不可预测的。作为一个大部分时间都花在VSCode上的人,我经常利用代码添加、样式格式化、代码结构、自动完成和代码库搜索等强大的扩展,所以当我切换回Jupyter时,我无能为力有点力不从心的感觉。与VSCode相比,JupyterNotebook缺少实施最佳编程实践的扩展。好吧,抱怨够多了。我非常喜欢Jupyter,认为它对设计工作非常有用。你绝对可以用它来引导小项目或快速原型想法,但你必须遵循软件工程的原则。当数据科学家使用笔记本时,有时会忽略这些原则,让我们回顾一下其中的一些原则。让您的代码再次伟大的技巧这些技巧是根据不同的项目、我参加的聚会以及与我过去合作过的软件工程师和架构师的讨论汇编而成的。请注意,以下假设我们正在编写python脚本,而不是笔记本。1.清理代码代码质量最重要的维度是清晰度,干净、可读的代码对于协作和可维护性至关重要。这样做将帮助您获得更清晰的代码:使用有意义的、描述性的和暗示性的变量名。例如,如果你想声明一个关于属性(如年龄)的布尔变量来检查一个人是否老,你可以使用is_old使其既具有描述性又具有类型信息。声明数据也是如此:使其可解释。#notgood...importpandasasspddf=pd.read_csv(path)#better!transactions=pd.read_csv(path)避免只有你能理解的缩写和没人能容忍的长变量名。不要直接在代码中编码“幻数”。在变量中定义它们,以便每个人都明白它们指的是什么。#notgood...optimizer=SGD(0.0045,momentum=True)#better!learning_rate=0.0045optimizer=SGD(learning_rate,momentum=True)遵循PEP8命名对象的约定:例如,函数和方法名称以小写字母表示字母、单词用下划线分隔、类名遵循UpperCaseCamelCase约定、常量用大写等。使用缩进和空格让你的代码更漂亮。有一些标准约定,例如“每个缩进使用4个空格”、“单独的部分应该有额外的空行”等。图片来源:prettier.io/2。使代码模块化当您开始构建可以在同一项目或其他项目中重用的东西时,您必须将代码组织成逻辑功能和模块,这有助于构建更好的组织和可维护性。例如,你正在做一个NLP项目,你可能有不同的处理函数来处理文本数据(标记化、剥离URL、修饰符等)。您可以将所有这些单元放入一个名为text_processing.py的python模块中,然后从那里导入它们,主程序会轻得多。以下是编写模块化代码的一些技巧:不要重复自己。尽可能概括或合并您的代码。函数应该用来做一件事。如果一个函数执行多个操作,则很难泛化。函数中的抽象逻辑,但不要过度设计,否则你可能会得到太多的模块。根据您的判断,如果您没有经验,请查看流行的GitHub存储库,例如scikit-learn并学习它们的编码风格。3.重构代码重构旨在重组代码的内部结构而不改变其功能,并且通常在代码的工作(但仍未完全组织)版本上完成。它有助于删除重复的功能、重组文件结构并添加更多抽象。资料来源:unsplash4。提高代码效率编写执行速度快、占用内存和存储空间少的高效代码是软件开发中的另一项重要技能。编写高效的代码需要多年的经验,但这里有一些提示可以帮助您确定您的代码是否运行缓慢以及如何改进它:在做任何事情之前,检查算法的复杂性以估计其执行时间。通过检查每个操作的运行时间来检查脚本中可能存在的瓶颈。尽可能避免for循环并使操作矢量化,尤其是在使用NumPy或pandas等库时。通过使用多处理来利用计算机的CPU内核。5.使用GIT或任何其他版本控制系统使用GIT+Github帮助我提高了编码技能并更好地组织了我的项目。由于我在与朋友和同事合作时使用它,因此我遵守了过去没有遵守的标准。图片来源:freecodecamp无论是在数据科学还是软件开发中,使用版本控制系统都有很多好处。跟踪您的更改并回滚到任何以前的代码版本通过合并和拉取请求在团队成员之间高效协作提高代码质量代码审查将任务分配给团队成员并提供持续集成和持续交付挂钩以自动构建和部署项目。图片来源:Atlassian6。测试代码如果您想要构建一个执行一系列操作的数据管道,并且您想要确保它按设计执行,一种方法是编写检查预期行为的测试。测试可以像检查函数的输出形状或预期值一样简单。图片来源:https://pytest-c-testrunner.re为函数和模块编写测试有很多好处:提高代码的稳定性,更容易发现bug。PreventingunexpectedoutputhelpsdetectedgecasesPreventsbreakingcodefrompushedtoproduction7.使用日志记录错误,你可以使用日志记录。以下是一些有效使用日志记录的技巧:根据要记录的消息的性质使用不同的级别(调试、信息、警告)。在日志中提供有用的信息以帮助解决相关问题。importlogginglogging.basicConfig(filename='example.log',level=logging.DEBUG)logging.debug('Thismessageshouldgotothelogfile')logging.info('Soshouldthis')logging.warning('Andthis,too')来源:techgig告别codeNightmare,这些小技巧不得不学。
