- Julia機器學習核心編程:人人可用的高性能科學計算
- 朱紅慶
- 1632字
- 2020-07-28 11:01:35
3.4 理解函數中變量的作用域
當我們在Julia中定義函數時,也可以在函數體內定義變量。在這種情況下,該變量在該函數的局部范圍內有效,因此稱為局部變量。而未在函數體內聲明的變量在全局范圍內有效,因此稱為全局變量。
不同代碼塊中的變量可以使用相同的名稱,但引用的是不同的實體,這種特性就是由其范圍規則所定義的。
Julia有兩種主要的范圍類型:全局范圍和局部范圍。其中局部范圍可以被嵌套。除非另有說明,否則模塊和REPL中的變量通常在全局范圍內;循環、函數、宏、try-catch-finally塊中的變量在局部范圍內。
下面我們用一個例子來解釋局部范圍。
【范例3-14】變量的局部范圍
我們在for結構中定義了一個局部變量hello,并試圖在for結構外輸出它。
01 julia> for i= 1:100 02 hello = i 03 end 04 julia> hello 05 ERROR: UndefVarError: hello not defined
代碼01~03行定義了一個for結構,其中聲明了一個hello變量。在04行我們試圖輸出hello的值,但是卻得到了05行的報錯,報錯類型是未定義變量錯誤,提示hello并沒有被定義。這是為什么呢?
因為對于整個程序來說,for結構屬于一個局部,所以在for結構中聲明的hello僅在for循環的范圍內可用,在for循環的范圍外不可用。
我們修改上一個函數,使得在循環外部也可以訪問到hello。
01 julia> for i=1:100 02 global hello 03 hello = i 04 end 05 06 julia> hello 07 100
這段代碼和范例3-14的代碼幾乎完全一樣,唯一的區別在于添加了02行,用global關鍵字顯式聲明hello為全局變量,這樣就可以在06行要求顯示hello的值時,成功地將hello的值打印出來了。
Julia使用了一種稱為詞法作用域的機制,簡單來說,就是函數的作用域不會從其調用對象的作用域繼承,而是從函數定義的作用域繼承。為了更清楚地理解這一點,我們通過一個例子來說明。
【范例3-15】詞法作用域例子
本例定義了一個模塊,并在模塊外對其進行了調用。
01 julia> module Utility 02 name = "Julia" 03 tell_name() = name 04 end 05 Utility 06 07 julia> name = "Python" 08 "Python" 09 10 julia> Utility.tell_name() 11 "Julia"
代碼01~05行用module關鍵字創建了一個名為“Utility”的模塊,它包含一個name變量和一個tell_name()函數。我們將Utility模塊內的name變量的值設置為“Julia”。為了對比,07行我們在Utility模塊外聲明了另一個name變量,并將它的值設置為“Python”。
在代碼10行,當調用Utility.tell_name()時,我們得到的值是“Julia”。這表明該函數使用了在Utility模塊中定義的name變量的值,這是因為函數tell_name()本身被定義在Utility模塊中。所以,在Utility模塊外聲明的另一個name變量,不會影響函數的運行結果。
Julia還提供了對局部范圍的進一步分類,分為軟局部范圍和硬局部范圍,剛才的函數介紹的是硬局部范圍。我們將在接下來的章節中重新討論范圍,但是現在,我們繼續將注意力放在函數的范圍上。
假設有一個alpha()函數,它的作用是將參數傳遞給一個名為“x”的局部變量并返回x。同時,我們定義了另一個全局變量x,并將它的值設置為100。
【范例3-16】函數范圍
我們在函數內和函數外分別聲明了兩個不同的x變量。
01 julia> x = 100 02 100 03 04 julia> function alpha(n::Int64) 05 x = n 06 return x 07 end 08 alpha (generic function with 1 method) 09 10 julia> alpha(50) 11 50 12 13 # 全局變量x并沒有改變 14 julia> x 15 100
代碼01行定義了一個變量x。04~07行定義了一個函數,在其中定義了另一個變量x,并通過參數賦值的形式對x的值進行了更改。在代碼10行我們對該函數進行了調用,返回的x的值是50。代碼14行直接輸出x的值,輸出的x的值是100。
如果仔細觀察,就會發現x的值自始至終都是100,但是當我們調用alpha(50)函數時,函數返回的是50而不是100。這是因為在函數內部聲明的變量(即函數中的局部變量x)在函數內部被賦值為參數所傳遞的數值(即n),而全局變量x的值對函數內部的局部變量x卻無法直接造成影響。
如果想要在函數內部使用全局聲明的x,該怎么辦呢?我們可以使用global關鍵字。
【范例3-17】在函數內部使用全局變量
我們將函數中的x變量替換為全局的x,然后觀察調用函數后結果發生了怎樣的改變。
01 julia> x = 100 02 100 03 04 julia> function alpha(n::Int64) 05 global x = n 06 end 07 alpha (generic function with 1 method) 08 09 julia> alpha(50) 10 50 11 12 # 全局變量x的值現在被改變了 13 julia> x 14 50
這段代碼和范例3-16的代碼幾乎完全相同,只是在05行函數體內刪除了為局部變量x指定數值的代碼,取而代之的是為全局變量x指定n的值。結果很明顯,和我們所期望的一樣,全局變量x的值已經被改變為50,而不是原始值100了。因為在函數體中我們操作的不再是局部變量x,而是全局變量x。
- GAE編程指南
- C語言程序設計(第2 版)
- 深度學習經典案例解析:基于MATLAB
- 跟“龍哥”學C語言編程
- Learning Informatica PowerCenter 10.x(Second Edition)
- Python神經網絡項目實戰
- 精通網絡視頻核心開發技術
- Kivy Cookbook
- 計算機應用基礎教程(Windows 7+Office 2010)
- Python機器學習之金融風險管理
- 深入解析Java編譯器:源碼剖析與實例詳解
- TypeScript圖形渲染實戰:2D架構設計與實現
- Java程序設計教程
- Mastering Unreal Engine 4.X
- Distributed Computing with Python