Julia 模塊

2018-08-12 21:25 更新

模塊

Julia 的模塊是一個(gè)獨(dú)立的全局變量工作區(qū)。它由句法限制在 module Name ... end 之間。在模塊內(nèi)部,你可以控制其他模塊的命名是否可見(jiàn)(通過(guò) import ),也可以指明本模塊的命名是否為 public(通過(guò) export)。

下面的例子展示了模塊的主要特征。這個(gè)例子僅為演示:

    module MyModule
    using Lib

    using BigLib: thing1, thing2

    import Base.show

    importall OtherLib

    export MyType, foo

    type MyType
        x
    end

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

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

注意上述例子沒(méi)有縮進(jìn)模塊體的代碼,因?yàn)檎w縮進(jìn)沒(méi)有必要。

這個(gè)模塊定義了類(lèi)型 MyType 和兩個(gè)函數(shù)。foo 函數(shù)和 MyType 類(lèi)型被 export ,因此可以被 import 進(jìn)其他模塊使用。 barMyModule 的私有函數(shù)。

語(yǔ)句 using Lib 表明,Lib 模塊在需要時(shí)可用來(lái)解析命名。若一個(gè)全局變量在當(dāng)前模塊中沒(méi)有被定義,系統(tǒng)會(huì)在 Lib export 的變量中搜索,并在找到后把它 import 進(jìn)來(lái)。在當(dāng)前模塊中凡是用到這個(gè)全局變量時(shí),都會(huì)去找 Lib 中變量的定義。

語(yǔ)句 using BigLib: thing1, thing2using BigLib.thing1, BigLib.thing2 的縮寫(xiě)。

import 關(guān)鍵字支持與 using 所有相同的語(yǔ)法,但只能在一個(gè)時(shí)間上對(duì)一個(gè)名稱(chēng)進(jìn)行操作。它不像 using 那樣會(huì)添加用于搜索的模塊。importusing 的不同之處還在于導(dǎo)入這一功能時(shí)必須使用新的方法擴(kuò)展后的 import。

在上述的 MyModule 中我們想向標(biāo)準(zhǔn)的 show 功能增加一個(gè)方法,所以我們必須寫(xiě)下 import Base.show

那些函數(shù)名只有通過(guò) using 功能才能看到的函數(shù)是不能被擴(kuò)展的。

importall 關(guān)鍵字顯式地導(dǎo)入導(dǎo)出指定模塊的所有名稱(chēng),其效果就像 import 單獨(dú)使用在它們的所有名稱(chēng)一樣。

一旦一個(gè)變量是通過(guò) usingimport 使其可見(jiàn)的,一個(gè)模塊就可能無(wú)法創(chuàng)建它自己的同名的變量了。輸入變量必須是只讀的;對(duì)全局變量賦值總是會(huì)影響當(dāng)前模塊所擁有的變量,否則就會(huì)引發(fā)錯(cuò)誤。

模塊使用方法的總結(jié)

我們要加載一個(gè)模塊時(shí),可以使用兩個(gè)主要關(guān)鍵字:usingimport。要了解他們的差異,可以考慮下面的例子:

    module MyModule

    export x, y

    x() = "x"
    y() = "y"
    p() = "p"

    end

在這個(gè)模塊中我們(使用關(guān)鍵字 export )導(dǎo)出 xy 功能,也包含了非導(dǎo)出函數(shù) p 。我們有幾個(gè)不同的方法來(lái)加載該模塊及其內(nèi)部功能到當(dāng)前工作區(qū),具體如下:

導(dǎo)入命令 導(dǎo)入變量 方法擴(kuò)展可用項(xiàng)
using MyModule All export ed names (x and y), MyModule.x, MyModule.y and MyModule.p MyModule.x, MyModule.y and MyModule.p
using MyModule .x, MyModule.p x and p
using MyModule: x, p x and p
import MyModule MyModule.x, MyModule.y and MyModule.p MyModule.x, MyModule.y and MyModule.p
import MyModule.x, MyModule.p x and p x and p
import MyModule: x, p x and p x and p
importall MyModule All export ed names (x and y) x and y

模塊和文件

大多數(shù)情況下,文件和文件名與模塊無(wú)關(guān);模塊只與模塊表達(dá)式有關(guān)。一個(gè)模塊可以有多個(gè)文件,一個(gè)文件也可以有多個(gè)模塊:

    module Foo

    include("file1.jl")
    include("file2.jl")

    end

在不同的模塊中包含同樣的代碼,會(huì)帶來(lái)類(lèi)似 mixin 的特征。可以利用這點(diǎn),在不同的環(huán)境定義下運(yùn)行同樣的代碼,例如運(yùn)行一些操作的“安全”版本來(lái)進(jìn)行代碼測(cè)試:

    module Normal
    include("mycode.jl")
    end

    module Testing
    include("safe_operators.jl")
    include("mycode.jl")
    end

標(biāo)準(zhǔn)模塊

有三個(gè)重要的標(biāo)準(zhǔn)模塊:Main, Core, 和 Base。

Main 是頂級(jí)模塊,Julia 啟動(dòng)時(shí)將 Main 設(shè)為當(dāng)前模塊。提示符模式下,變量都是在 Main 模塊中定義,whos() 可以列出 Main 中的所有變量。

Core 包含“內(nèi)置”的所有標(biāo)志符,例如部分核心語(yǔ)言,但不包括庫(kù)。每個(gè)模塊都隱含地調(diào)用了 using Core,因?yàn)闆](méi)有這些聲明,什么都做不了。

Base 是標(biāo)準(zhǔn)庫(kù)( 在 base/ 文件夾下)。所有的模塊都隱含地調(diào)用了 using Base,因?yàn)榇蟛糠智闆r下都需要它。

默認(rèn)頂級(jí)聲明和裸模塊

除了 using Base,模塊顯式引入了所有的運(yùn)算符。模塊還自動(dòng)包含 eval 函數(shù)的定義,這個(gè)函數(shù)對(duì)本模塊中的表達(dá)式求值。

如果不想要這些定義,可以使用 baremodule 關(guān)鍵字來(lái)定義模塊。使用 baremodule 時(shí),一個(gè)標(biāo)準(zhǔn)的模塊有如下格式:

    baremodule Mod

    using Base

    importall Base.Operators

    eval(x) = Core.eval(Mod, x)
    eval(m,x) = Core.eval(m, x)

    ...

    end

模塊的相對(duì)和絕對(duì)路徑

輸入指令 using foo, Julia 會(huì)首先在 Main 名字空間中尋找 Foo。如果模塊未找到, Julia 會(huì)嘗試 require("Foo")。通常情況下, 這會(huì)從已安裝的包中載入模塊。

然而,有些模塊還有子模塊,也就是說(shuō),有時(shí)候不能從 Main 中直接引用一些模塊。有兩種方法可以解決這個(gè)問(wèn)題:方法一,使用絕對(duì)路徑,如 using Base.Sort。方法二,使用相對(duì)路徑,這樣可以方便地載入當(dāng)前模塊的子模塊或者嵌套的模塊:

    module Parent

    module Utils
    ...
    end

    using .Utils

    ...
    end

模塊 Parent 包含子模塊 Utils。如果想要 Utils 中的內(nèi)容對(duì) Parent 可見(jiàn), 可以使用 using 加上英文句號(hào)。更多的句號(hào)表示在更下一層的命名空間進(jìn)行搜索。例如,using ..Utils 將會(huì)在 Parent 模塊的 子模塊內(nèi)尋找 Utils 。

模塊文件路徑

全局變量 LOAD_PATH 包含了調(diào)用 require 時(shí) Julia搜索模塊的目錄??梢杂?push! 進(jìn)行擴(kuò)展 :

    push!(LOAD_PATH, "/Path/To/My/Module/")

將這一段代碼放在 ~\.juliarc.jl 里能夠在每次 Julia啟動(dòng)時(shí)對(duì) LOAD_PATH 擴(kuò)展。此外,還可以通過(guò)定義環(huán)境變量 JULIA_LOAD_PATH 來(lái)擴(kuò)展 Julia 的模塊路徑。

小提示

如果一個(gè)命名是有許可的(qualified)(如 Base.sin),即使它沒(méi)被 export ,仍能被外部讀取。這在調(diào)試時(shí)非常有用。

import 或 export 宏時(shí),要在宏名字前添加 @ 符號(hào),例如 import Mod.@mac 。在其他模塊中的宏可以被調(diào)用為 Mod.@mac@Mod.mac 。

形如 M.x = y 的語(yǔ)法是錯(cuò)的,不能給另一個(gè)模塊中的全局變量賦值;全局變量的賦值都是在變量所在的模塊中進(jìn)行的。

直接在頂層聲明為 global x,可以將變量聲明為“保留”的。這可以用來(lái)防止加載時(shí),全局變量初始化遇到命名沖突。

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)