[docs] Julia 与 Python 的显著差异

对文档的一些补充:与 Python 的显著差异 · Julia中文文档

文档中说的很清楚的部分就不赘述了。


与 Python 的显著差异

字符串

  • Julia 中的字符串使用双引号构造,如 "text",也可以使用三引号构造多行字符串。而在 Python 中可以使用单引号('text')或者双引号("text")。
    单引号在 Julia 中用来表示单个字符,例如 'c'
    julia> "text"
    "text"
    
    julia> "a"
    "a"
    
    julia> 'a'
    'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
    
    julia> typeof("a")
    String
    
    julia> typeof('a')
    Char
    

索引与切片

  • Julia 里的切片包含最后一个元素。Julia 里的 a[2:3] 等同于 Python 中的 a[1:3]
    【这里要同时注意 Julia 索引从 1 开始】

  • Julia 的范围语法为 x[start:step:stop],而 Python 的格式为 x[start:(stop+1):step]
    因此 Python 中的 x[0:10:2] 等价于 Julia 里的 x[1:2:10]。类似的 Python 中的反转数组 x[::-1] 等价于 Julia 中的 x[end:-1:1]

  • 在 Julia 中队一个矩阵取索引 X[[1,2], [1,3]] 返回一个子矩阵,它包含了第一和第二行与第一和第三列的交集。
    在 Python 中 X[[1,2], [1,3]] 返回一个向量,它包含索引 [1,1][2,3] 的值。
    Julia 中的 X[[1,2], [1,3]] 等价于 Python 中的 X[np.ix_([0,1],[0,2])]
    Python 中的 X[[1,2], [1,3]] 等价于 Julia 中的 X[[CartesianIndex(1,1), CartesianIndex(2,3)]]
    julia

    julia> X = [1 2 3; 4 5 6; 7 8 9]
    3×3 Array{Int64,2}:
     1  2  3
     4  5  6
     7  8  9
    
    julia> X[[1,2], [1,3]]
    2×2 Array{Int64,2}:
     1  3
     4  6
    
    julia> [[CartesianIndex(1,1), CartesianIndex(2,3)]]
    1-element Array{Array{CartesianIndex{2},1},1}:
     [CartesianIndex(1, 1), CartesianIndex(2, 3)]
    
    julia> X[[CartesianIndex(1,1), CartesianIndex(2,3)]]
    2-element Array{Int64,1}:
     1
     6
    

    python

    >>> import numpy as np
    >>> X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    >>> X
    array([[1, 2, 3],
           [4, 5, 6],
           [7, 8, 9]])
    >>> X[[0,1], [0,2]]
    array([1, 6])
    >>> X[np.ix_([0,1], [0,2])]
    array([[1, 3],
           [4, 6]])
    

表达式的续行

  • Julia 没有下一行继续的语法:当输入的表达式很复杂、很长的时候,除非到某一行结尾,这个表达式结束了,不然会一直继续读取下一行。
    一种强制让表达式延续的语法是:将多行表达式包在一对括号中。
    【注:简单来说表达式随便换行,会自动续上的】

取余、取模与转置

  • % 在 Julia 中是取余操作符(remainder),而 Python 表示取模(modulus)。
    【译注:二者在参数有负数时有区别】
    【julia 中 % 对应 Julia 的函数 rem;Python 中的 % 对应 Julia 的 mod

  • Julia 中的伴随操作符 ' 返回向量的转置(一种行向量的懒惰表示法)。
    Python 中对向量执行 .T 返回它本身(没有效果)。

    julia> a = collect(1:3)
    3-element Array{Int64,1}:
     1
     2
     3
    
    julia> a'
    1×3 LinearAlgebra.Adjoint{Int64,Array{Int64,1}}:
     1  2  3
    

变量的作用域

  • 小心 Julia 中的非常量全局变量,尤其它出现在循环中时。因为你在 Julia 中可以写出贴近硬件的代码,这时使用全局变量的影响非常大(参见性能建议)
    【注:别用全局变量就好了,要么是常量,要么就传参,参数多就打包到可变的结构体里。】

  • 在 Julia 中大多数代码块都会引入新的本地作用域(local scope)。例如:循环和异常处理的 try — catch — finally。
    注意:列表推断(comprehensions)与生成器在 Julia 和 Python 中都会引入新的作用域;而 if 分支则都不会引入。
    【注:经典新手问题:为什么 REPL 里以下代码报错?】

    julia> sum = 0
    0
    
    julia> for i in 1:5
               sum += i
           end
    ERROR: UndefVarError: sum not defined
    Stacktrace:
     [1] top-level scope at .\REPL[36]:2
    

    答:因为 for 引入了新的作用域。要么你把 sum 设为全局变量,要么把这段放到函数里面。

    julia> sum = 0;
    julia> # 1. global var: sum
    
    julia> for i in 1:5
               global sum
               sum += i
           end
    
    julia> sum
    15
    
    julia> function f()
               sum = 0
               for i in 1:5
                   sum += i
               end
               sum # return
           end
    
    f (generic function with 2 methods)
    
    julia> f()
    15
    
2 个赞

还有个,Julia中的÷div (大致上)对应Python中的 // ,我一开始入门的时候找了这个函数老半天。

直接去把英文文档也给改了吧。

感觉是除了这些“显著”差异,大家可能更想要一个函数、关键字对应表。

索引方面还有一个重要的内容是

x[1] 在Julia下表示线性索引,对于x=rand(4, 4)而言, x[5] == x[1, 2]. 而在 numpy 下x[1] 则代表切片 x[1,:] 并且 x[5] 会直接报错

Reference: https://docs.julialang.org/en/v1/manual/arrays/#man-supported-index-types-1

最近发现一个,Julia 解包赋值时允许被解包的Iterable长度与赋值的变量数不等,而Python不行。

Julia:

julia> a, b = (1,2,3)
(1, 2, 3)

julia> a
1

julia> b
2

Python:

>>> a,b = (1,2,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
1 个赞