写给Python用户的Julia编程指南[updating]

本文的目的是,为拥有Python编程经验的用户提供一些指引,方便其快速上手Julia。

准备

下载和安装

官网提供了各个系统下的安装包,不过我建议新手先安装Julia PRO,这个有点类似Python下的Anaconda,目前版本还没有1.0,这里以0.6.2为例,安装Julia的同时还会安装一些Julia下常见的包(省去了许多包管理麻烦,当然,也会带来一些新的小问题,这个碰到的时候再细说)。

由于我日常开发在Windows下,所以以下内容中操作系统相关的部分都以Windows为主(Linux和Mac下要容易很多,应该问题不大)。

安装后直接双击桌面的JuliaPro - Command Prompt 0.6.2.1快捷键即可打开Julia的REPL界面,就跟IPython有点像(后面会详细介绍其与IPython的联系和区别),建议将JuliaPRO安装路径下Julia-0.6.2中的bin目录添加到环境变量Path中,这样可以直接在git-bash或者cmd中直接运行julia(如下图)。

Julia_REPL

Julia_REPL

Windows下开发学习的一点个人建议

我个人对Windows的态度是不吹不黑,但老实说,Windows下开发的体验很差。强烈建议安装个Debian/Ubuntu的WSL,除了不能直接跟底层GPU打交道外,我目前的开发中没遇到什么大问题,日常一般是开了两个terminal,一个显示REPL,另一个在Debian中切到对应的目录下做文件读取和服务管理。

编辑器

一般Python的开发会选择PyCharm之类的IDE,不过Julia下还没有与PyCharm对应的IDE。安装JuliaPRO之后,桌面会有一个Juno for JuliaPro 0.6.2.1,其实就是一个Atom上套了个插件,如果你原来就用Atom的话,也许你会喜欢这个编辑环境。我个人在Windows下倾向使用VSCode+Julia插件,不过社区里也有人用Vim和Emacs,选择一个适合你的就好。

使用VSCode的Julia插件的时候,需要配置(File -> Preferences -> Settings)julia的路径,如"julia.executablePath": "D:\workspace\software\JuliaPro-0.6.2.1\Julia-0.6.2\bin\julia.exe"。

当然,你一定注意到了桌面还有一个Jupyter 0.6.2.1,其实就是Jupyter+IJulia的内核,如果你习惯Jupyter的话几乎可以做到无缝迁移。

REPL

在IPython中,最常用的一个功能是查看函数的帮助文档,通过在函数/方法名后面加一个?来实现,不过在Julia的REPL中,是先输入?再输入函数名:

使用?的例子

使用?的例子

另外,在IPython中,经常会执行一些类似ls,pwd等等系统命令,这类命令在Julia中是通过函数来实现的(如readdir(), pwd())。此外,原来%%的魔法函数也有对应的函数实现。不过如果是在REPL中,可以直接输入;进入shell模式,执行各种命令(自行对比iPython中加了!执行命令)。

包管理

新版的Pkg管理模块比以前好用了很多,功能上有点像内置了一个pipenv。打开Julia的REPL后,按]进入Pkg管理模块,通过generate Foo即可新建一个Project,然后add Bar可以添加依赖,更多操作可以查看Pkg的Doc。

语法细节

下面从一些日常的操作来介绍如何从Python迁移到Julia。

代码结构

在Python中,代码是以目录结构组织起来的,然后用__init__.py来区分包和普通的目录,Julia的代码以模块(Modules)组织起来的,一个典型的Julia文件有如下结构:

module MyModule
using Lib

using BigLib: thing1, thing2

import Base.show

export MyType, foo

struct MyType
    x
end

bar(x) = 2x
foo(a::MyType) = bar(a.x) + 1

show(io::IO, a::MyType) = print(io, "MyType $(a.x)")
end

首先,module定义了整个模块,其作用范围一直到最后一行end,module名称一般采用驼峰式,在module中也可以定义一个__init__函数,其功能有点类似Python下的__init__.py文件(不完全对应,__init__.py某种程度上提供了下面export的功能)。

using Lib有点类似Python中的from xxx import *,此刻你脑海中想到的第一个问题应该是命名冲突!对,我一开始也这么想的,后来习惯了发现,好像问题不大,因为Julia是带类型的,一定程度上通过重载缓解了这个问题。

using BigLib: thing1, thing2就是显式地导入,类似from xxx import foo, bar

个人感觉,Julia中import主要用于扩展某个函数的时候使用,这一点using做不到(using只用于提供查找变量的搜索空间)。importall就是import的扩展版(新版本中importall已废弃)。

export则是,将该module内部的某些变量暴露出去。在Python中可能是通过__foo等来实现的。

函数部分的区别和联系后面再详述。

有时候,我们想直接从某个文件中导入,需要用include("foo.jl")来实现。

有一个函数whos()可以用来查看当前的变量信息,有点像Python中的globals()

数据结构

index

在Julia中,按index访问访问元素的时候,是从1而不是0开始的。这大概是我自己从Python迁移到Julia最不习惯的一方面(一不小心就出错了)。访问最后一个元素要使用end关键字,有点像Python中的-1。另外,Julia中索引的时候,是左闭右闭[]的,不是Python中的左闭右开[)

string

list

Python中最常用的就是list了,Julia中并没有严格与之对应的数据结构,不过,就一般使用而言,可以把一维的Array{Any,1}拿来用。

Tuple

和Python中基本一致,未来也会目前支持类似Python3中的NamedTuple

numpy

这里单独说明下,Julia可以看作是自带了numpy的Python,Numpy的许多操作都能在标准库中Array部分找到。

记录几个需要注意的点:

iterator

struct

对比Python中的class

macro

这个先放这里,在Python中很少会接触,前期迁移到Julia中的时候,只需要掌握一些常用的宏就可以了。

Grammar

Julia中有些Python中没有的语法糖,个人感觉有些还算有意思,有些就比较累赘了。

function

如果不考虑类型的话,Julia下的function和Python相比,主要的差别是:

operator

type

这个应该是从Python转Julia最大的区别,没有捷径,好好阅读文档。这里我记下点自己觉得比较常用的几个知识点:

接下来?