本文包含附属链接。有关更多信息,请参阅我的附属公司披露。
Python 培训师Matt Harrison引起了不小的轰动。
他的一些熊猫示例,如下面的示例,在 Twitterverse 中引起了不同人的情绪反应:
一个人评论说:“没有人在他们正常的头脑中写出这样的代码。对吧?”有人引用推文说:“如何不编写 Python 代码。”
问题是,正如他所说,Matt 是一位经验丰富的程序员,“在战壕中工作多年”。他撰写了有关Python和pandas的畅销书,并定期在顶级公司培训数据科学团队。
我知道这个故事必须有更多内容。
批评马特代码的人与塑造马特充满 lambda、方法链式的 pandas 编写风格的现实之间是否存在一些脱节?我决定联系一下,看看马特是否有兴趣在 Twitter 上与我讨论他的代码以及对它的反应。
我很高兴他答应了。
大卫:我对你在 Twitter 上的帖子中看到的话语非常着迷。而且,你知道,看着你处理它也很有趣。但我觉得您发布的代码示例周围有一些上下文,有些人可能会丢失。是这样吗?
马特:是的,也许我应该快速谈谈我的背景,以便人们知道我来自哪里。我有计算机科学学位,你知道,我在校外最初的想法是我会成为一名软件工程师。我离开学校的第一份工作是做自然语言处理,我职业生涯的大部分时间都在使用 Python 从事数据工作。我不是统计学家。我不是管理员。我的背景是编写代码。
我现在做的是培训 Python 数据领域的专业人士,但我也为公司做一些咨询和建议。我是一名教育工作者,但我会说我有时间在战壕里。所以我不会阅读幻灯片或只是因为我认为在互联网上骚扰人们很有趣。
正如我所说,作为一名教育工作者,我的目标是秘密地向使用代码作为工具的人教授最佳实践,更一般地说,向人们传授软件工程最佳实践。声称不想成为编码员的人。他们只是将代码用作工具,对吗?但他们正在编码,我的目标是帮助他们编写专业的代码,这样他们以后不会因为编写而讨厌自己。
也就是说,我知道代码就像每个人的孩子一样,编码人员在他们的代码中投入了大量的时间、汗水和泪水。当你称某人的孩子丑陋或说他们的孩子做事不正确时,这对很多人来说就像是对他们的人身冒犯,他们会采取错误的方式。所以,我明白了。
但你不是你的代码,就像你不是你工作的公司一样。您的身份应该与您的代码分开。因此,如果您使用代码,您的目标将是您希望能够更好地使用代码,或者这就是我认为您的目标。如果不是,那对我来说可能很奇怪。
话虽如此,我认为你永远不会让一百个人就一种真正的编码方式或一种正确的编码方式达成一致。 70% 的人会说你应该做面向对象的编程。 20% 的人可能会说你需要做 Rust。也许他们中的 1% 会说你需要进行函数式编程或类似的事情。所以你永远不会就此达成共识。
大卫:用你的方式编写 pandas 代码的电梯音调是什么?
Matt:你会在数据科学界看到的一件常见事情是这样的概念,即Untitled1.ipynb
和Untitled2.ipynb
。这个概念是,当数据科学家早上上班时,他们会拿走他们昨天工作的任何 Jupyter 笔记本,复制并粘贴它,然后重新开始。这有点像,“好吧,当我使用 Excel 时,我只是将它保存为一个新文件,然后我就从它开始,”对吗?
我的目标是提供帮助,因此您没有Untitled28.ipynb
,您有Analysis_for_ClientA.ipynb
,这是您唯一的笔记本。你明天可以回到它,从你离开的地方重新开始,你会很有效率。
您的代码将更易于阅读。其他人可以使用您的代码,您可以测试您的代码,您可以在一周内回到您的代码并拿起它,其他人也可以这样做。
大卫:你在 Twitter 上被一些人称为看门人。在一条推文中,您说您为专业人士编写代码。看门人的想法就是从这里来的吗?如果您不以某种方式编写代码,那它就不是“专业的”?
马特:是的,我想是的。你知道,有人很不高兴,因为我说我教专业人士。我问他们的听众是谁,他们说他们和老师或研究生一起工作。他们认为我声称我教专业人士的说法是对他们的抨击。不知何故,他们不专业。
我明白他们在说什么。但是,我确实教专业人士。就像,这就是我所做的。我走进你听说过的大公司,在他们的平台上观看节目,我教他们如何编写能够很好地为他们服务的代码。其中很多人不一定是软件工程师,但他们正在编写代码。
大卫:我认为你的内容在某种程度上填补了空白。如果你搜索 pandas,你会找到 pandas 文档和一大堆面向初学者的内容。这几乎适用于编程中的任何事情。因此,在搜索引擎上容易找到的内容与我认为专业人士实际需要的内容之间存在差距。这对这件事有影响吗?
Matt:你通过搜索找到的代码风格——我写过这样的代码。这很痛苦。 Medium 上的大多数数据科学帖子都类似于“要记住的顶级 Pandas 函数”之类的东西。这些帖子单独教授操作,这没关系。但在实践中,我从来没有一个数据集是我孤立地做一件事的。
在我 20 多年的数据工作中,我有多个步骤,我不关心中间步骤。我关心原始数据,即将到来的内容,我关心我将要可视化或发送到机器学习系统的干净数据。我关心最终的结果。写一个链是让我得到这些最终结果的秘诀。
大卫:是什么将初学者的熊猫代码与专业的熊猫代码区分开来?
Matt:我想说,如果你想编写好的 pandas 代码——让我们引出专业术语,只说好的 pandas 代码——你应该知道如何编写 lambdas。您应该知道如何进行列表和字典理解。很多人可能不使用的字典解包在熊猫世界中非常有用。
有人说,“我想编写我的代码,以便从未使用过 pandas 或 Python 的人可以查看并使用它。”好吧,如果那是你的听众,那祝你好运。我不想迎合最低公分母。
我假设他们理解什么是 lambdas、理解和字典解包。我还假设观众有一些最低水平的 Python 经验。我不认为 lambdas 和字典解包和列表理解一定是初学者级别的 Python 代码。
所以我并不是说以这种初学者风格编写代码的人不是专业人士。我是说他们的代码是以天真的方式编写的。如果这冒犯了他们,我很抱歉。我不认为这是他们的错。我认为这是因为,正如您所说,互联网上的许多内容都是以这种初学者风格编写的,向您展示了如何孤立地做某事。
大卫:您曾多次提到您与那些不一定认为自己是程序员,而是专业的 pandas 用户的人一起工作。在更传统的软件工程环境中,是否有其他适合编写 pandas 代码的方式?
Matt:不。我想说,如果你正在编写 pandas 代码,你应该接受这个链。基本上,这是一个约束。如果您将自己限制在约束中,它会迫使您考虑沿途所做的每一步。
大卫:项目的规模是一个因素吗?您看到人们使用的笔记本通常有多大?
马特:我见过一些笔记本,它们可以做更长的事情。但是,我的意思是,人们抱怨五行这样的链条是有史以来最糟糕的事情。
大卫:是的,我看到一些评论,人们反对连续几条连锁店。就像,来吧,真的吗?
马特:嗯,有得墨忒耳定律,这是一个通用的编程原则。如果你有一个对象并且你调用了一个对象的实例成员并且你调用了该对象的一个实例成员并且你链接了这些操作,那么这违反了得墨忒耳定律,它说你不应该询问内部部分关于内部部分。无论您从哪里开始,都应该公开执行此操作的功能。
我真的不相信我违反了得墨忒耳定律。我们在这里并没有真正处理内部零件的内部零件。这与那完全不同。我们有一个 DataFrame,我们正在返回另一个 DataFrame。我们不会深入挖掘 DataFrame 并拉出这部分,然后再拉出其中的一些子部分。
大卫:很多软件工程最佳实践在大范围内都是有意义的。但它们不一定在小范围内有意义。你最终会得到很多样板。就像,您可以在一个文件中的几个函数中完成此操作,那么您为什么要四处散布并做所有这些事情呢?
但是,你知道,在一定规模上这是有道理的,因为如果你不这样做,处理事情就太难了。是否存在可能使链接不太理想的可伸缩性问题?
马特:在我看来,这里的规模是你有超级复杂的数据。也许你最终会得到一个很长的链条。在这种情况下,您可以做的一件事就是利用.pipe()
。也许这二十行正在清理温度数据,或者其他什么。所以你可以说.pipe(clean_temperature_data)
并删除这二十行。
但是我见过人们编写了一大堆管道,它们都发送到一行代码。我的观点是:您应该能够阅读管道中的内容。通过分离事物,您会给自己带来更多的认知开销,因为现在您必须上下滚动才能阅读所有这些事物是什么,而之前链中的行告诉您它是什么。
但是,在某些情况下,合法地进行链接会使事情变得困难。也许您确实需要一个中间变量,因为您正在计算源自两个不同事物的事物。有一些方法可以做到这一点而不会破坏链条。您可以使用.pipe()
来制作中间变量,如果需要,您可以稍后参考。所以,我还没有看到任何东西表明链接不会随着代码大小而扩展。
至于我们可能想到的另一个尺度,即数据大小,需要注意的一点是 pandas 是一种内存工具。您的数据需要适合内存。这就是为什么我在加载数据时要做的第一件事就是设置正确的类型以缩小数据。前几天我举了一个例子,我用几行代码缩小了 95%。
另一件事是,pandas在写时复制语义方面并不是特别聪明。事实上,它并没有这个。对于我的客户,我通常推荐 3X–10X 的内存开销,以便您有空间来执行这些操作。所以,是的,数据大小可能是个问题。
人们不得不链接的反对意见之一是它与数据大小有关。但它实际上比我们所谓的朴素风格问题要少。也许天真的这个词有一个不好的含义,但它有点像那样。您制作所有这些中间变量,对吗?您实际上存储了对所有这些中间对象的引用,这些中间对象都是您的数据的副本。
当你链接时,通常会创建一个副本,但没有指针或变量保存它。它会收集垃圾。你创建了一个中间变量,然后接下来的事情对它做一些事情,此时,没有其他人在使用那个中间变量,所以它就消失了。您不必担心或管理它。
大卫:稍微切换一下,我很想知道可读性对你意味着什么。是什么让代码可读?
马特:我认为这是一个没有标准答案的问题。如果你问十个人,你会得到十个不同的答案。我会说我不只是教熊猫,我还教 Python。很多上 Python 基础课的人会听到我说:“你的目标不是编写易于编写的代码。你的目标是编写易于阅读的代码。
但是美丽在旁观者的眼中,因此,您需要再次考虑您的观众是谁。我不认为编写 Python 代码的专业人员或编写 Pandas 代码的专业人员应该编写易于被没有任何培训或背景的新人阅读的代码。
我会说有一些基线。以任何惯用的 Python 风格编写 Python,而不是 C 或 Java。我看到很多大学毕业的人说他们学过 Python,但实际上他们学过 C++ 或 Java。老师把他们的Java内容翻译成Python,这不是特别难,现在学生知道Python了,对吧?但他们并不真正了解 Python。
话虽如此,仅仅因为我以这种链接方式编写 pandas 并不意味着当我编写 Python 代码时,我会在所有地方都编写链。有人问我面向对象编程在哪里与 pandas 一起使用。当我编写熊猫代码时,我不编写类。这是否意味着我从不写课程?不,我一直在写课。只是我在写熊猫的时候真的不需要使用类。
所以我想我会从熊猫的角度来回答这个问题。对我来说,可读的 pandas 代码就像一个食谱。它有步骤。你可以说这是第一步,这是第二步,这是第三步。链接是一种约束,如果您遵循该约束,基本上会迫使您编写代码,就好像它是一个食谱一样。
大卫:对我来说,对于“什么是可读代码?”有一种不令人满意的显而易见的答案。这就是我无需费力就能阅读和理解的任何代码。如果我必须写下来并做笔记才能理解几行代码,那么我们就开始离开可读性的领域了。
当我第一次在你的 Twitter 帖子中看到链式风格时,吸引我的一件事是我只需要考虑每个步骤在做什么,而不是它是如何完成的。我发现自己写了更多这样的代码。不一定是链接,而是以更具声明性的风格。这是我在遇到的 pandas 代码中经常看到的,而且我认为,尤其是在方法链中。
但是还有另一个反对意见,人们必须使用我们尚未讨论的链接。我看到人们争辩说,无法访问链中的中间步骤使得代码难以测试和调试。你能谈谈吗?
马特:我把这段代码发布到网上,我想很多人都会说,“哦,你就像走到电脑前,输入整段代码,然后你就完成了?中间在哪里?步骤?我该如何调试这个?
我建议人们去 YouTube 上搜索我惯用的 pandas 演讲,我在其中表明这是最终结果。这不像我坐在电脑上一口气写完这整件事。我坐在电脑前,逐行制作,边做边测试。
我不在乎最后的中间结果。我正在检查它们,并验证我正在做的事情确实有效。我认为很多事情就像他们不明白我是如何到达那个终点的,因为他们只是看到了终点。
而且,你知道,我通常会挑战人们并问“你会如何重写这个?”大多数人不接受,但一个人确实接受了,他们就像,“我要写这个又大又长的笔记本,我在这里声明一些变量。”他们就像,“你需要在里面放一些 Markdown。”
很多人说我需要使用 Markdown,因为你需要评论。所以你需要有多个单元格,因为你需要在它们之间有 Markdown,对吧?然后每个单元格需要在其上方进行一些降价,以解释它在做什么以及诸如此类的事情。
我的意思是,如果这对你来说是可读的,那就太好了。但问题是,当我明天回到这个问题时,我必须找到这些单元并按顺序运行它们。如果你碰巧把它们弄得乱七八糟,那我就有点糟糕了。
在我的笔记本中,我完成后将我的链放入一个函数中,然后我只是将该函数放在我的代码的最顶部,我明天可以回来,加载我的原始数据,然后运行它很好走。
话虽如此,如果我确实想要中间变量,我可以使用.pipe()
并创建一个全局变量。我在我的Effective Pandas书中展示了这方面的例子。你如何调试它?您可以注释掉管道并通过。这真的很容易。人们问你是否可以使用调试工具。是的。您在该行放置一个断点,然后您可以在该点单步执行该方法。声称您无法调试它对我来说是一种虚假的说法。
大卫:那么你对这一切的最终想法是什么?人们应该从我们的谈话中得到什么?
Matt:如果人们不喜欢链接,那对他们来说可能是个坏消息,因为我相信我们会看到更多像Polars这样的下一代工具,它是 Rust 中的 DataFrame 实现。
您必须在 Polars 中使用链条。您可以在链的最后执行一个.filter()
,它将返回读取 CSV 文件并根据过滤器限制它读取的列和行。您可以从链中进行查询优化,如果您没有在 Polars 中进行链,您将无法获得。
真的,我的建议是尝试在 pandas 中进行链接。我想很多人对此有不良反应,但他们从未尝试过。很多读过我的书的人说,“我很怀疑,但我试过了,现在它改变了我编写 pandas 代码的方式。”
想学习如何编写有效的 pandas 代码?
查看 Matt 的最新著作《 Effective Pandas》。它向您展示了如何清理数据、创建强大的可视化效果以及编写您自己的数据配方。并且有一整章专门用于调试。
立即访问Matt 网站上的电子书或在Amazon上订购印刷版。
我最喜欢的部分是 Matt 如何使用图表来解释操作并帮助您建立使用 pandas DataFrames 的心智模型:
来自Effective Pandas 的示例图。
在 Twitter ( @__mharrison__ ) 上关注 Matt,并在metasnake.com上查看他的所有书籍和培训课程。
想要更多这样的吗?
每周六发送一封电子邮件,其中包含一个可操作的提示。
总是少于你的 5 分钟。
现在订阅