Engee 文档
Notebook

与其他语言的显著差异

尽管 Julia 的语法对于 MATLAB 用户来说可能并不陌生,但它并不是 MATLAB 的克隆。两者在语法和功能上存在重要差异。以下是 Julia 中的一些显著差异,它们可能会让习惯使用 MATLAB 的用户感到困惑。

与 MATLAB 的区别

  1. Julia 中的数组索引用方括号指定:A[i,j]。
In [ ]:
Pkg.add(["LinearAlgebra"])
In [ ]:
A = [1 2 3; 4 5 6; 7 8 9]
i = 2
j = 3
element = A[i, j]
println(element)
6

2.当 Julia 中的数组被赋值给另一个变量时,它不会被复制。在赋值 A = B 后,改变 B 中的元素会导致 A 中的元素发生变化。

In [ ]:
B = [1, 2, 3]
A = B
B[1] = 10
println(A)
[10, 2, 3]

3.在 Julia 中,传递给函数的值不会被复制。如果函数更改了数组,调用者将看到这些更改。

In [ ]:
function modify_array(arr)
    arr[1] = 100
end

A = [1, 2, 3]
modify_array(A)
println(A)
[100, 2, 3]

4.在 Julia 中,使用赋值运算符时数组不会自动扩大。在 MATLAB 中,您可以使用表达式 a(4) = 3.2 创建数组 a = [0 0 0 0 3.2],并使用表达式 a(5) = 7 将其扩展为 a = [0 0 0 0 3.2 7],而在 Julia 中,如果 a 的长度小于 5 或在此操作符中首次使用名称 a,相应操作符 a[5] = 7 就会出错。与 MATLAB 中的 a(end+1) = val 相比,Julia 的 push!和 append!函数可以更高效地递增 Vector 类型的对象。

In [ ]:
A = [1, 2, 3]
push!(A, 4)
println(A)

B = [5, 6, 7]
append!(B, [8, 9])
println(B)
[1, 2, 3, 4]
[5, 6, 7, 8, 9]

5.在 Julia 中,虚数单位 sqrt(-1) 用常数 im 表示,而不是 MATLAB 中的 i 或 j。

In [ ]:
z = 2 + 3im
println(z)
println("Действительная часть: ", real(z)) 
println("Мнимая часть: ", imag(z)) 
2 + 3im
Действительная часть: 2
Мнимая часть: 3

6.在 Julia 中,没有小数分隔符的数字字面形式(例如 42)创建的是整数而不是浮点数。因此,如果某些操作期望使用浮点数,则可能会产生区域外错误。例如,julia> a = -1; 2^a 将产生这样的错误,因为结果不是整数(详情请参见常见问题中的区域外错误)。

In [ ]:
a = 42  # целое число
b = 42.0 # число с плавающей запятой
c = float(42) # явное преобразование к типу Float64
println(a)
println(b)
println(c)
42
42.0
42.0

7.在 Julia 中,如果要返回或赋值多个值,则使用元组,例如 (a, b) = (1, 2) 或 a, b = 1, 2。Julia 没有 nargout 函数,而在 MATLAB 中,nargout 通常用于根据返回值的数量执行额外的操作。可选参数和命名参数可以用于类似的目的。

In [ ]:
function get_values()
    return 1, 2
end

x, y = get_values()
println(x)
println(y)
1
2

8.Julia 有真正的一维数组。列向量的大小是 N,而不是 Nx1。例如,rand(N) 表达式会创建一个一维数组。

In [ ]:
v = [1, 2, 3] # одномерный массив
Out[0]:
3-element Vector{Int64}:
 1
 2
 3

9.在 Julia 中,构造 [x,y,z] 总是创建一个包含三个元素的数组:x、y 和 z。- 要沿第一个维度("垂直")进行连接,请调用 vcat(x,y,z) 函数或使用分号([x; y; z])作为分隔符。- 要沿第二维("水平 "维)进行连接,请调用 hcat(x,y,z) 函数或使用空格([x y z])作为分隔符。- 要创建块矩阵(沿前两个维度进行连接),请调用 hvcat 函数或将空格和分号组合起来作为分隔符([a b; c d])。

In [ ]:
A = [1, 2, 3]
B = [4, 5, 6]
C = [7, 8, 9]

D = vcat(A, B, C) # вертикальная конкатенация
println(D)

E = hcat(A, B, C) # горизонтальная конкатенация
println(E)

F = [A; B; C] # разделитель ";"
println(F)

G = [A B C] # разделитель пробел
println(G)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1 4 7; 2 5 8; 3 6 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1 4 7; 2 5 8; 3 6 9]

10.在 Julia 中,构造 a:b 和 a:b :c 可以创建 AbstractRange 对象。要创建一个完整的向量,就像在 MATLAB 中一样,使用 collect(a:b) 方法。不过,通常没有必要调用 collect。在大多数情况下,AbstractRange 对象的行为与普通数组类似,但由于可以 "懒惰 "地计算值,因此效率更高。这种创建特殊对象而非完整数组的模式经常被使用,包括 range 等函数以及 enumerate 和 zip 等迭代器。特殊对象通常可以像普通数组一样使用。

In [ ]:
range = 1:5
vector = collect(range)
println(vector)
[1, 2, 3, 4, 5]

11.Julia 中的函数返回最后一个表达式或表达式的计算结果,并带有返回关键字。不必在函数定义中列出返回变量的名称(详见返回关键字部分)。

In [ ]:
function sum(x, y)
    x + y
end

result = sum(2, 3)
println(result)
5

12.在 Julia 中,调用不带参数的函数时,必须使用括号,例如 rand()。

In [ ]:
function example()
    println("Функция без аргументов")
end

example()
Функция без аргументов

13.在 Julia 中,不建议在表达式的末尾加上分号。表达式的结果不会自动显示(交互式命令行除外),因此没有必要在代码行末尾加上分号。您可以使用 println 函数或 @printf 宏在屏幕上显示某些数据。

In [ ]:
a = 2
b = 3
c = a + b
println(c)
5

14.在 Julia 中,如果 A 和 B 是数组,逻辑比较操作(如 A == B)不会返回逻辑值数组。相反,可以使用 A .== B 或类似的表达式来表示其他逻辑运算符,如 < 和 >。

In [ ]:
A = [1, 2, 3]
B = [2, 2, 3]
result = A .== B
println(result)
Bool[0, 1, 1]

15.在 Julia 中,运算符 &、| 和 ⊻ (xor) 是位运算符,就像 MATLAB 中的 and、or、and、or 和 xor 一样。它们的优先级与 Python 中位运算符的优先级相同(但与 C 语言不同)。它们可以应用于标量值,也可以逐元素应用于数组,还可以用于组合逻辑数组。但是,请注意操作顺序的不同:可能需要使用括号(例如,要选择 A 中等于 1 或 2 的元素,请使用表达式 (A .== 1) .| (A .== 2))。

In [ ]:
a = 5
b = 3
result = a & b
println(result)

A = [true, false, true]
B = [false, true, true]
result = A .& B
println(result)
1
Bool[0, 0, 1]

16.在 Julia 中,可以使用扩展运算符(splat 运算符)...将集合的元素作为参数传递给函数,例如 xs=[1,2]; f(xs...)。

In [ ]:
function sum_elements(x, y, z)
    return x + y + z
end

values = [1, 2, 3]
result = sum_elements(values...)
println(result)
6

17.Julia 中的 svd 函数以向量形式返回奇异值,而不是稠密的对角矩阵。

In [ ]:
using LinearAlgebra
A = [1 2; 3 4]
U, S, V = svd(A)
println(S)
[5.464985704219043, 0.3659661906262575]

18.在 Julia 中,...不是用来续写代码的。相反,不完整的表达式会自动在下一行继续。

In [ ]:
a = 2 +
    3
println(a)
5

19.Julia 中的结构体(struct)不支持在运行时动态添加字段,这一点与 MATLAB 中的类(class)不同。请使用 Dict 代替。Julia 中的字典不是有序的。

In [ ]:
struct MyStruct1
    field1::Int
end

s = MyStruct1(10)
println(s.field1)

# Используем словарь для добавления поля field2
s_dict = Dict(:field1 => s.field1, :field2 => 20)
println(s_dict[:field2])
10
20

20.在 Julia 中,每个模块都有自己的全局区域或命名空间,而在 MATLAB 中只有一个全局区域。

In [ ]:
module MyModule
    global_var = 10
    
    function my_function()
        println(global_var)
    end
end

MyModule.my_function()
10
WARNING: replacing module MyModule.

21.在 MATLAB 中,移除不必要值的惯用方法是使用逻辑索引,如表达式 x(x>3) 或运算符 x(x>3) = [] 来改变 x 的位置。为此,Julia 提供了高阶函数 filter 和 filter! ,允许使用表达式 filter(z->z>3, x) 和 filter!(z->z>3, x) 替代 x[x.>3] 和 x = x[x.>3]。使用 filter! 函数可以减少使用临时数组的频率。

In [ ]:
A = [1, 2, 3, 4, 5]
filtered_A = filter(x -> x > 3, A)
println(filtered_A)

filter!(x -> x > 3, A)
println(A)
[4, 5]
[4, 5]

22.提取(或 "取消引用")单元数组的所有元素,如 MATLAB 中的 vertcat(A{:}),在 Julia 中使用扩展运算符(splat 运算符),如 vcat(A...)。

In [ ]:
A = [1, 2]
B = [3, 4]
C = [5, 6]
array_of_arrays = [A, B, C]
concatenated_array = vcat(array_of_arrays...)
println(concatenated_array)
[1, 2, 3, 4, 5, 6]

23.在 Julia 中,adjoint 函数执行共轭转置;而在 MATLAB 中,adjoint 提供了adjoint 矩阵(经典adjoint),即执行代数补码矩阵的转置。

In [ ]:
A = [1+2im 3+4im]
adj_A = adjoint(A)
println(adj_A)
Complex{Int64}[1 - 2im; 3 - 4im;;]

24.在 Julia 中,表达式 (a ^ b ^ c) 的求值为 a^ (b^c),而在 MATLAB 中,表达式的求值为 (a ^ b) ^ c。

In [ ]:
a = 3
b = 2
c = 3
result = a^(b^c)
println(result)
6561

与 Python 的区别

1.在 Julia 中,代码块 for、if、while 等以结束关键字结束,而不是像 Python 那样缩进。没有 pass 关键字。

In [ ]:
for i in 1:5
    println(i)
end
1
2
3
4
5

2.在 Julia 中,字符串用双引号表示,多行文本使用三对双引号。此外,单引号用于表示字符。

In [ ]:
str1 = "Hello, World!"
str2 = """Это много-
строчный текст."""
char1 = 'c'
Out[0]:
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)

3.Julia 使用 * 操作符来连接字符串,而不是 Python 中的 +。^ 操作符用于重复字符串,而不是 *。

In [ ]:
str1 = "Hello, "
str2 = "World!"
concatenated_str = str1 * str2
repeated_str = str2 ^ 3
println(concatenated_str)
println(repeated_str)
Hello, World!
World!World!World!

4.在 Julia 中,列表对应于 Vector{Any} 类型或更通用的 Vector{T} 类型,其中 T 是某种元素类型。更高效的数组,如 NumPy 数组,可以用 Array{T} 数组表示,其中 T 是特定的元素类型。

In [ ]:
list1 = Any[1, "two", 3.0]
list2 = Vector{Int}(undef, 5)
array1 = Array{Int}(undef, 3, 3)
Out[0]:
3×3 Matrix{Int64}:
 3762813801648698725  3774918513298847538  7077182949550143800
 3762529018811868721  7364623875528025187      140502613063936
 3991368380935386977  3906925892200719205      140518684094896

5.Julia 中数组的索引从 1 开始,这与 Python 的索引从 0 开始不同。

In [ ]:
array = [1, 2, 3, 4, 5]
println(array[1])  # Выведет 1
1

6.Julia 中的 a[2:3] 相当于 Python 中的 a[1:3]。

In [ ]:
array = [1, 2, 3, 4, 5]
println(array[2:3])  # Выведет [2, 3]
[2, 3]

7.在 Julia 中,允许使用任意索引的 AbstractArray。在 Python 中具有特殊含义的负指数在 Julia 中被写成 a[end] 和 a[end-1]。

In [ ]:
array = [1, 2, 3, 4, 5]
println(array[end])  # Выведет 5
println(array[end - 1])  # Выведет 4
5
4

8.在 Julia 中,end 关键字用于索引最后一个元素。Python 中的 x[1:] 相当于 Julia 中的 x[2:end]。

In [ ]:
array = [1, 2, 3, 4, 5]
println(array[2:end])  # Выведет [2, 3, 4, 5]
[2, 3, 4, 5]

9.在 Julia 中,范围索引的格式是 x[start:step:stop],而在 Python 中是 x[start:(stop+1):step]。因此,Python 中的 x[0:10:2] 相当于 Julia 中的 x[1:2:10]。

In [ ]:
array = [1, 2, 3, 4, 5]
println(array[1:2:end])  # Выведет [1, 3, 5]
[1, 3, 5]

10.Julia 没有字符串延续语法。如果一个字符串包含一个完整的表达式,它就被认为是完整的。否则,字符串将被继续。您可以使用括号来继续表达式。

In [ ]:
a = (
    1 + 2 +
    3
)
println(a)  # Выведет 6
6

11.在 Julia 中,数组是按列展开的,而 NumPy 数组是按行展开的。在 Julia 中循环数组时,循环顺序必须与 NumPy 相反。

In [ ]:
A = [1 2; 3 4; 5 6]
for j in 1:size(A, 2), i in 1:size(A, 1)
    println(A[i, j])
end
1
3
5
2
4
6

12.在 Julia 中,函数参数的默认值会在每次方法调用时进行评估,这与 Python 不同,后者只在定义函数时进行评估。

In [ ]:
function f(x = rand())
    return x
end;
In [ ]:
println(f())  # Выполните ячейку несколько раз
0.975434444871681

13.在 Julia 中,命名参数必须与名称一起传递,这与 Python 不同。

In [ ]:
function foo(a; b = 1, c = 2)
    return a + b + c
end

println(foo(10, b = 3, c = 4))  # Выведет 17, нельзя вызывать как println(foo(10, 3, 4)), в случае с Python
17

14.在 Julia 中,Int 类型对应于机器整数类型(Int32 或 Int64),而在 Python 中,int 可以是任意长度。

In [ ]:
x = Int64(2) ^ Int64(64)
println(x)  # Выведет 0
0

15.在 Julia 中,虚数单位用常量 im 表示,而在 Python 中则使用 j。

In [ ]:
println(2im)  # Выведет 0 + 2im
0 + 2im

16.在 Julia 中,度运算符用 ^ 表示,而不是 Python 中的 **。

In [ ]:
println(2 ^ 3)  # Выведет 8
8

17.Julia 中的空值用 Nothing 类型的常量 nothing 表示,而 Python 使用 NoneType 类型的 None 对象。

In [ ]:
x = nothing
println(x)  # Выведет nothing
nothing

18.在 Julia 中,* 操作符执行矩阵运算,而在 Python 中,它执行逐元素乘法。在 Julia 中,.* 操作符用于逐元素乘法运算。

In [ ]:
A = [1 2;
     3 4]
B = [5 6;
     7 8]
println(A * B)  # Выведет матрицу, [19 22; 43 50]

println(A .* B)  # Выведет матрицу, [5 12; 21 32]
[19 22; 43 50]
[5 12; 21 32]

19.在 Julia 中,'运算符返回共轭向量,而在 Python 中,.T transpose 运算符返回原始向量。

In [ ]:
x = [1 2 3]
println(x')  # Выведет [1; 2; 3]
[1; 2; 3;;]

20.在 Julia 中,一个函数可以有多个具体实现(方法),这些实现(方法)是根据参数的类型来选择的。在 Python 中,一个函数只有一个实现,不支持多态性。

In [ ]:
function square(x::Number)
    return x * x
end

function square(x::String)
    return string(x, x)
end

println(square(2))  # Выведет 4
println(square("hello"))  # Выведет "hellohello"
4
hellohello

21.Julia 中没有类,而是使用只包含数据而不包含方法的结构。

In [ ]:
struct MyStruct
    x::Int
    y::Float64
end

function f(obj::MyStruct, z)
    return obj.x + obj.y + z
end

my_obj = MyStruct(1, 2.5)
println(f(my_obj, 3.5))  # Выведет 7.0
7.0

22.在 Python 中调用一个类实例的方法就相当于在 Julia 中调用一个函数。

In [ ]:
struct MyType
    x::Int
end

function f(obj::MyType, y)
    return obj.x + y
end

my_obj = MyType(10)
println(f(my_obj, 5))  # Выведет 15
15

23.Julia 中的结构只能有一个抽象超类,而 Python 中的类可以从多个超类继承。

In [ ]:
abstract type Animal end

struct Dog <: Animal
    name::String
end

struct Cat <: Animal
    name::String
end

dog = Dog("Buddy")
cat = Cat("Whiskers");

24.在 Julia 中,三元运算符的写法是 x > 0 ?1 : -1,而 Python 则使用条件表达式 1 if x > 0 else-1。

In [ ]:
x = 10
result = x > 0 ? 1 : -1
println(result)  # Выведет 1
1

25.在 Julia 中,异常处理使用 try-catch-finally 结构,而 Python 则使用 try-except-finally。

In [ ]:
try
    # Код, который может вызвать исключение
catch ex
    # Обработка исключения
finally
    # Выполнение кода, который будет выполнен в любом случае
end

结论

本例展示了 Julia 与 Matlab 和 Python 在语法和功能上的主要区别。