购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

Excel的主要功能是存储数据、分析数据和可视化数据。而Python在科学计算方面也极其强大,天生就适合搭配Excel工作。能同时引起专业程序员和初学者(他们可能几周只写那么几行代码)兴趣的编程语言不多,Python便是其中一门。专业程序员喜欢Python是因为它是一门通用编程语言。你可以用Python轻松地实现大部分事情。而对于初学者来说,比起其他语言,Python显得更加简单易学。Python的用途广泛,小到即时数据分析、自动化任务,大到如Instagram后端的代码库,都有Python的功劳。这也就意味着当你用Python编写的Excel工具流行起来之后,可以很容易地找到一名Web开发人员将你的Excel-Python原型转化为功能齐全的Web应用程序。Python的独特优势在于,处理业务逻辑的部分很可能不需要重写就能原封不动地从Excel原型迁移到Web生产环境中。

本节会介绍Python的各种核心概念,并会将它们和Excel及VBA进行对比,也会涉及可读性、Python标准库、包管理器、科学计算栈、现代语言特性、跨平台兼容性等内容。先来了解一下可读性。

当说代码“可读”时,意思是这些代码很容易理解——特别是对于那些并没有写这些代码的人来说。良好的可读性使得发现错误和维护代码更加容易,这也是为什么《Python之禅》( The Zen of Python )中会写道“可读性很重要”(readability counts)。《Python之禅》是对Python核心设计原则的精辟总结,在第2章中我们会学到如何输出这首禅诗。先来看看下面的VBA代码:

If i < 5 Then
    Debug.Print "i is smaller than 5"
ElseIf i <= 10 Then
    Debug.Print "i is between 5 and 10"
Else
    Debug.Print "i is bigger than 10"
End If

在VBA中,可以将上面的代码整理成下面这样,前后两段代码完全等效:

If i < 5 Then
    Debug.Print "i is smaller than 5"
    ElseIf i <= 10 Then
    Debug.Print "i is between 5 and 10"
    Else
    Debug.Print "i is bigger than 10"
End If

在第一个版本中,视觉上的缩进和代码逻辑一致。这使得代码易于阅读和理解,进而更容易发现其中的错误。在第二个版本中,初见这段代码的开发者可能看不到 ElseIf Else 条件,而如果这段代码来自更为庞大的代码库则更是如此。

Python不会接受像上面第二个版本那样的代码,它会强制你将视觉缩进和代码逻辑对齐,从而避免可读性问题。之所以有这种强制性,是因为当你在 if 语句或 for 循环中使用代码块时,Python依靠缩进来定义代码块。其他大多数语言用花括号而不是缩进来定义代码块,VBA则使用 End If 等关键字,就像我们刚才在前面的代码中看到的那样。使用缩进定义代码块的原因在于,编程时大部分时间是花费在维护代码而不是现写新的代码上。可读性好的代码可以帮助新进程序员(也可能是写下代码几个月之后的你自己)回顾过去、了解现状。

第3章会介绍Python的缩进规则,现在先来了解一下Python提供的随时可用的内置功能——标准库。

Python通过 标准库 提供了丰富的内置工具。Python社群喜欢称之为“自带电池”。无论是需要解压ZIP文件,还是从CSV文件中读取数据,抑或想要从互联网上获取数据,Python标准库都能给你安排妥当,并且通常只需要几行代码。如果想在VBA中实现同样的功能,则可能需要大量的代码,或是安装插件。通常你在网上找到的解决方案都只能在Windows中工作,到macOS中就不行了。

尽管Python标准库涵盖了大量的功能,但还是有一些功能难以编写,又或是使用标准库来实现效率很低。这个时候就该PyPI上场了。PyPI代表Python Package Index(Python包目录),它是任何人(包括你!)都可以上传开源Python包的巨大仓库,利用这些包可以扩展Python的功能。

PyPI和PyPy

PyPI读作“pie pea eye”,PyPy则读作“pie pie”。PyPy是另一种高效的Python实现。

如果你想更方便地从互联网上获取数据,就可以安装Requests包来获取一系列强大又好用的命令。要安装一个包,你需要在命令提示符或者终端中使用Python的包管理器,即pip。pip是pip installs packages的递归缩写。虽然听起来有点儿抽象,不过别担心,第2章会解释它是如何工作的。现在更重要的是理解为什么包管理器如此重要。一个主要原因是,任何优质的包可能不仅依赖于Python标准库,还会依赖于PyPI上的其他开源包。而这些依赖项又可能会依赖其他的包,层层递进。pip会递归地检查一个包的依赖项和子依赖项,并逐一下载安装。你还可以使用pip轻松地更新包,以保持各个依赖项都是最新版本。pip让你能够坚守DRY原则,因为不用重新发明轮子或者复制粘贴PyPI上已有的包。有了pip和PyPI,你就有了一套统一的机制来分发和安装依赖项——这正是Excel的插件所欠缺的。

开源软件

在这里我想简单谈一下 开源 (open source)。本节在前面内容中已经几次提到这个词。如果一款软件依照某种开源许可证分发,那么就意味着我们可以免费、自由地获取它的源代码,并且任何人都可以参与添加新功能、修复bug或撰写文档。Python本身以及大多数第三方Python包是开源的,大部分是由开发者在业余时间维护的。但这并不一定是一种理想状态。如果你的公司长期在用一个包,那么你会希望有专业开发者对其进行持续开发和维护。幸运的是,Python科学计算社区已经意识到了这一点:一些包对于科学计算至关重要,如果把它们留给只在晚上和周末对其进行开发的少数志愿者,则实在令人不放心。

非营利性组织NumFOCUS于2012年成立,它的诞生就是为了赞助科学计算领域的一些Python包和项目。NumFOCUS赞助的最受欢迎的项目包括pandas、NumPy、SciPy、Matplotlib和Project Jupyter。如今它也会对其他语言(比如R、Julia和JavaScript)的软件包提供支持。虽然还存在一些大型企业赞助商,但是每个人都可以作为一名自由社区成员加入NumFOCUS,另外捐献是可以减税的。

可以使用pip安装任何功能的包,而对于Excel用户来说,最有趣的当然还是用于科学计算的包。下一节会介绍如何通过Python进行科学计算。

Python成功的关键原因在于,它是作为一门通用编程语言诞生的。它的科学计算能力是在诞生之后通过第三方包的形式增加的。数据科学家可以和Web开发者使用同一门语言来做实验和研究,最终Web开发者可以围绕数据科学家开发的计算核心开发一个随时可上线的应用程序,这正是Python的独特优势。使用一门语言来构建科研应用程序可以减少冲突、减少实现时间,甚至减少花费。诸如NumPy、SciPy和pandas之类的科学计算库给我们提供了一种简洁的方式来表达数学问题。作为一个例子,来看看现代投资组合理论中比较有名的投资组合方差公式。

为投资组合方差, w 为单个资产的权重向量, C 为投资组合方差矩阵。若 w C 为Excel中的范围,则在VBA中可以像下面这样计算投资组合方差:

variance = Application.MMult(Application.MMult(Application.Transpose(w), C), w)

假定 w C 是pandas的DataFrame和NumPy中的数组,相比之下Python代码完全就像是数学记法:

variance = w.T @ C @ w

但这并非仅仅是美观和可读性方面的优势。NumPy和pandas背后使用了预编译的Fortran代码和C代码,在处理大型矩阵时和VBA相比有巨大的性能提升。

缺少对科学计算的支持是VBA明显的短板,但即便是核心语言特性方面,它也显然不敌Python。在下一节中你会看到这种差距。

自Excel 97以来VBA在语言特性方面几乎没有任何重大改进,但这并不意味着VBA不再受到支持。为了让VBA能够自动化Excel中的新功能,在每次Excel发布新版本时,微软也会对VBA进行更新,比如在Excel 2016中就添加了自动化Power Query的支持。作为一门近20年没有重大改进的语言,VBA缺少了一些所有主流语言都有的现代语言概念。举例来说,VBA中的错误处理看起来就有些过时了。如果想在VBA中得当地处理错误,就要这样做:

Sub PrintReciprocal(number As Variant)
    ' There will be an error if the number is 0 or a string
    On Error GoTo ErrorHandler
        result = 1 / number
    On Error GoTo 0
    Debug.Print "There was no error!"
Finally:
    ' Runs whether or not an error occurs
    If result = "" Then
        result = "N/A"
    End If
    Debug.Print "The reciprocal is: " & result
    Exit Sub
ErrorHandler:
    ' Runs only in case of an error
    Debug.Print "There was an error: " & Err.Description
    Resume Finally
End Sub

VBA的错误处理需要用到像 Finally ErrorHandler 这样的 标签 ,通过 GoTo Resume 语句可以让代码跳转到这些标签。在当时,人们认为标签是产生所谓 意大利面式代码 (对代码难以阅读和维护的一种打趣的说法)的罪魁祸首。这也就解释了为什么大多数还在积极开发中的语言引入了 try/catch 机制。这种机制在Python中叫作 try/except ,第11章会介绍。如果能熟练使用VBA,那么你可能也会喜欢Python的类继承特性。这种面向对象编程特性正是VBA所欠缺的。

除了一些现代语言特性,一门现代编程语言还有一项必备特性,那便是跨平台兼容性。下面来看看为什么跨平台兼容性如此重要。

即便在一台运行着Windows或者macOS的本地计算机上开发,在某个时候你也可能会想让代码在一台服务器或者云端上运行。服务器会通过其运算能力,让代码按计划执行,并使应用程序可以从任何地方访问。在第2章中我会介绍Jupyter笔记本,展示如何在服务器上执行Python代码。Linux是一种非常稳定、安全且高效的操作系统,绝大多数服务器使用的是Linux。Python程序可以在不修改代码的情况下在所有操作系统中运行,你可以轻松地从本地开发机器过渡到生产环境中。

相比之下,即便Excel VBA可以在Windows和macOS中运行,但还是很容易写出一些只能在Windows中执行的代码。在VBA的官方文档或论坛中,经常会看到这样的代码:

Set fso = CreateObject("Scripting.FileSystemObject")

只要调用了 CreateObject ,或者被要求在VBA编辑器的“工具 > 引用”选项中添加引用,你很有可能就是在处理只能在Windows系统中运行的代码。如果想让Excel文件可在Windows和macOS中使用,则还需要重点关注是否使用了 ActiveX控件 。ActiveX控件就是那些可以放在表格上的按钮、下拉菜单之类的控件元素,这些控件只能在Windows中使用。如果想让工作簿也能在macOS中使用,那么务必避免使用这些控件! eexC99NOc+2vWT3Hg3EPUmw5jSEOA7vDTKvAXop9GUp8JZtPuwEKzwusgQQRL4U4

点击中间区域
呼出菜单
上一章
目录
下一章
×