Julia 语言初学笔记

 

Julia 与 Python 的主要差异

 

  Julia Python
if, for, while 代码块 

以 end 关键字结束,缩进不重要

无 pass 关键字

由缩进决定

有 pass 关键字

字符串引号 单引号用于字符;双引号用于字符串 不区分单双引号
字符串连接

字符串连接:*

字符串重复:^ 

字符串插值:$

字符串连接:+

字符串重复:*

字符串插值:% 或 format 函数

数组索引

从 1 开始(类似 R)

 

不支持负索引,末尾元素的索引为 end

从 0 开始

 

支持负索引,末尾元素的索引为 -1

切片

包含冒号后的终点元素

例:(Julia)a[2: 3] \Leftrightarrow a[1: 3](Python)

 

冒号后的终点元素不能为空,如需直至末尾的切片,须用 end

例:(Julia)a[2: end] \Leftrightarrow a[1: ](Python)

不含冒号后的终点元素

 

冒号后的终点元素可以为空,此时表示切片直至末尾

有步长的切片

a[起点: 步长: 终点]

 

例:(Julia)a[end: -1: 1] \Leftrightarrow a[: : -1](Python)

a[起点: 终点: 步长]
矩阵索引

子矩阵:

X[[1,2], [1,3]] 表示矩阵 X 的第 1、2 行和第 1、3 列的交点构成的子矩阵

 

元素索引:

(Julia)X[[CartesianIndex(1,1), CartesianIndex(2,3)]] \Leftrightarrow X[[0,1], [0,2]](Python)

子矩阵:

(Julia)X[[1,2], [1,3]] \Leftrightarrow X[np.ix_([0,1],[0,2])](Python)

 

元素索引:

X[[1,2], [1,3]] 表示矩阵 X 中索引为 [1, 1] 和 [1, 3] 所对应元素组成的向量

行连接 括号 反斜杠或括号
数组 列优先(Fortran 模式) NumPy: 行优先(C 模式)
默认参数

每次函数调用时重新加载

 

例:

f(x=rand()) = x 每次调用时,返回一个新的随机值

g(x=[1,2]) = push!(x,3) 每次调用时,均返回[1,2,3]

不要使用可变对象作为默认值
关键字参数 函数调用时,须输入关键字 函数调用时,可不输入关键字,按位置顺序传参即可
% 运算符

取余运算

 

例:

7 % 3 = 1

(-7) % 3 = -1

取模运算

 

例:

7 % 3 = 1

(-7) % 3 = 2

溢出

Int 类型对应 Int32 或 Int64,数值过大时可能溢出

如需表示更大的数值,可使用 Int128, BigInt, Float64 等数据类型

 

例:2 ^ 64 == 0

int 可表示任意长度的整数,不会溢出
虚数单位 im j
幂运算 ^ **
空值 nothing None
矩阵乘法

矩阵乘法:*

按元素相乘:.*

矩阵乘法:@

按元素相乘:*

转置 ' NumPy: .T
多态

支持多态,同一个函数名可对应多种方法

不支持多态,函数有唯一表达

无类,只有结构体 struct,包含数据但无方法 有类
调用 包与模块的调用与文件结构无关 代码结构取决于路径(包)和文件(模块)
条件表达式(三目运算符)

可用于变量赋值

 

例:(Julia)x > 0 ? 1 : -1 \Leftrightarrow x = 1 if x > 0 else x = -1(Python)

不可用于变量赋值
@ 运算符 装饰器
异常

try - catch - finally 结构

常规工作流中不建议使用异常处理结构,可能会影响代码性能

try - except - finally 结构
条件判断 须使用显式布尔值(类似 Java)

允许使用隐式布尔值(类似 C)

注:Python 语言规范中,建议尽可能使用隐式 False

局部作用域 除 if 外的代码块,包括 try - catch - finally,均有局部作用域 (此条同 Julia)
命名规则

变量名使用小写;

除非难于理解,否则单词之间不加下划线;

类型(Type)或模块(Module)使用双驼峰形式命名,不使用下划线形式;

函数(Function)或宏(Macro)使用小写,且不加下划线;

能够修改自变量的函数(mutating / in-place)以叹号结尾。

除类之外,均使用下划线形式命名;

类使用双驼峰形式命名;

全局变量所有字母全部大写。

 

参考资料:

Noteworthy differences from Python

 

 

Julia 的一些有趣用法

 

UTF-8

变量与函数,均可以使用 UTF-8 编码下的字符命名:

支持 markdown 方式输入特殊字符:

Julia 语言初学笔记_第1张图片

 

机械极小值(Machine Epsilon)

只有浮点数才有机械极小值,含义为,与下一个可表示的浮点数之间的距离

eps(T):T 为浮点数类型(Float32 / Float64),返回 1.0 与下一个可表示的浮点数之间的距离

eps(x):x 为浮点数,返回 x 与下一个可表示的浮点数之间的距离;该数值随 x 的增大而增大

上/下一个浮点数可由 prevfloat / nextfloat 函数获得

Julia 语言初学笔记_第2张图片

 

变量系数

Julia 语言初学笔记_第3张图片

系数乘法的运算优先级:低于一元运算符,高于二元运算符

Julia 语言初学笔记_第4张图片

不可以将括号形式的变量作为系数,乘于括号形式的变量前,否则会报函数调用的错误:

Julia 语言初学笔记_第5张图片

冲突解决:

  • 0x11 表示十六进制下的 11,不表示以 0 为系数乘以 x11 变量;
  • 1.5e10 或 1.5E10 表示浮点数,不表示以 1.5 为系数乘以 e11 或 E10 变量;
  • 1.5f22 表示 Float32 类型的浮点数,不表示以 1.5 为系数乘以 f11 变量,但由于大写的 F 没有该功能,故 1.5F22 正常表示以 1.5 为系数乘以 F11 变量

 

Inf 和 NaN

有关 Inf 和 NaN 的大小比较:

  • Inf 与自身相等,比除 NaN 之外的任何数都大;
  • -Inf 与自身相等,比除 NaN 之外的任何数都小;
  • NaN 不等于、不小于、不大于任何数,包括其自身

Julia 语言初学笔记_第6张图片

数组运算时需注意:

 

Unicode

有效的 Unicode 数值范围为:[0x0000, 0xD7FF] 和 [0xE000, 0x10FFFF],但并非所有数值均被分配字符。

单引号内使用 \u 可以表示四位十六进制数对应的 Unicode 字符;使用 \U 则表示八位十六进制数对应的 Unicode 字符,但由 Unicode 的数值范围可知,最大有效长度仅为六位十六进制数。

Julia 语言初学笔记_第7张图片

含有 Unicode 字符串,由于字符的长度可能超过 1 byte,某些索引可能不合法,此时可使用 firstindex, lastindex, nextind, prevind 方法:

Julia 语言初学笔记_第8张图片

也可用于字符遍历:

Julia 语言初学笔记_第9张图片

length(str, i, j) 函数用于获取位置 i 到 j 之间(闭区间)有效字符的数量:

Julia 语言初学笔记_第10张图片

 

三引号字符串

Julia 语言初学笔记_第11张图片

有关三引号字符串的缩进:

每一行的缩进程度取决于缩进最小的一行。如下所示,示例中的最后一行决定了缩进程度:

起始三引号的所在行和由空格组成的行,不决定缩进程度;起始三引号的所在行,不受缩进程度的影响:

Julia 语言初学笔记_第12张图片

 

复合函数、向量化函数

复合函数:

函数链:

Julia 语言初学笔记_第13张图片

向量化函数:点运算符

宏 @. 用于所有函数均为向量化调用时,可以简化点运算符过多的情况:

Julia 语言初学笔记_第14张图片

点运算符与函数链一同使用:

Julia 语言初学笔记_第15张图片

 

短路计算(short-circuit evaluation)

  • a && b:当且仅当表达式 a 为 true 时,计算表达式 b;
  • a || b:当且仅当表达式 a 为 false 时,计算表达式 b

Julia 语言初学笔记_第16张图片

Julia 语言初学笔记_第17张图片

不使用短路计算的布尔运算,可使用位布尔运算符:

Julia 语言初学笔记_第18张图片

 

循环

for 循环内定义的计数变量 i,只在循环内可见(作用域只在循环内):

Julia 语言初学笔记_第19张图片

for 循环可在任何容器内迭代,此时使用关键字 in 或运算符 ∈:

Julia 语言初学笔记_第20张图片

多层循环可组合在同一行,按照笛卡尔积迭代,如遇 break 语句,直接跳出所有循环;而多行 for 的循环遇 break 语句时,只跳出当前循环:

Julia 语言初学笔记_第21张图片

 

变量作用域

词法作用域(lexical scoping):

Julia 语言初学笔记_第22张图片

模块内定义的变量,不能在模块外重新赋值:

Julia 语言初学笔记_第23张图片

函数内定义的变量,作用域只在函数内:

Julia 语言初学笔记_第24张图片

Julia 语言初学笔记_第25张图片

如前所述,循环内定义的变量,作用域只在循环内:

Julia 语言初学笔记_第26张图片

如需在外部使用循环内迭代后的计数变量,可使用 outer 关键词:

Julia 语言初学笔记_第27张图片

可以使用宏 @isdefined() 来确定变量是否定义:

Julia 语言初学笔记_第28张图片

let 代码块:let 内定义的变量,只在内部有效,如与外部变量重名,两个变量对应的是不同的存储空间

Julia 语言初学笔记_第29张图片

Julia 语言初学笔记_第30张图片

 

常量

若对常量进行重新赋值,当赋值类型不同时,会报错;类型相同时,会报警告:

Julia 语言初学笔记_第31张图片

而当重新赋值不会导致数值改变时,则不会给出警告信息:

Julia 语言初学笔记_第32张图片

然而,若重新赋值的常量为可变对象时,会报警告:

Julia 语言初学笔记_第33张图片

虽然可以对常量进行重新赋值,但是这强烈不建议这种做法,改变常量的值可能导致各种以外的问题发生。

例如,当某方法引用了一个常量,且在常量值被改变前被编译时,就会一直保持使用旧的数值:

Julia 语言初学笔记_第34张图片

 

复合类型(结构体)

filednames 函数可用于获得其所有字段名

除其中可变对象外,各字段的值均不可变。

Julia 语言初学笔记_第35张图片

声明复合类型时在前面加上 mutable 关键字,即变为可变类型:

Julia 语言初学笔记_第36张图片

参数复合类型:

Julia 语言初学笔记_第37张图片

不同参数的复合类型之间不互为子类型,但可以在参数内加入 <: 或 >: 运算符获得几种类型的并集,此时父子类型关系成立:

Julia 语言初学笔记_第38张图片

 

元组

长度为1时,要加逗号:

可变元组:元组中的最后一个元素可为特殊类型 Vararg,即长度可变

Julia 语言初学笔记_第39张图片

命名元组:

Julia 语言初学笔记_第40张图片

 

方法

方法指的是,一个函数的一种可能行为的定义,体现了语言的多态性。

Julia 语言初学笔记_第41张图片

方法歧义:

Julia 语言初学笔记_第42张图片

NTuple 参数:

Julia 语言初学笔记_第43张图片

上例中另一种消除歧义的方式:

Julia 语言初学笔记_第44张图片

 

构造器

外部构造器:

Julia 语言初学笔记_第45张图片

内部构造器:(注:new 函数仅在 struct 内有定义)

Julia 语言初学笔记_第46张图片

Julia 语言初学笔记_第47张图片

new 函数可以无参:

Julia 语言初学笔记_第48张图片

内部构造器会抑制默认构造器:

Julia 语言初学笔记_第49张图片

 

自更新运算符

如在数组中使用自更新运算符,而所用数组来自其他数组的直接赋值,则原赋值数组的值不会改变;

而当自更新运算符配合向量化运算符(.)使用时,原赋值数组的值会一同改变。

Julia 语言初学笔记_第50张图片

Julia 语言初学笔记_第51张图片

 

 

参考资料:

Julia Documentation

 

你可能感兴趣的:(Julia)