Perl中有兩種名字空間(namespace):符號(hào)表(symbol table)和詞法作用域(lexical scopes).在Perl中, 每個(gè)包(Package)有一個(gè)
符號(hào)表, 可以通過Packeagename::獲取包中的變量.
比如:
package A;
$test = 1;
可以通過$A::test訪問包A的變量test.
符號(hào)表是一個(gè)Hash表, 該Hash表的名字就是符號(hào)表所在包的名字.
比如你可以用下面的語句打印出在main包中的所有符號(hào):
foreach (keys %main::)
{
print $_, "\n";
}
又比如, 如果在程序中聲明了:
$test = 1;
可以通過$main::test來訪問該變量(假設(shè)變量是在main包中).
在同一個(gè)符號(hào)表中, 可以存在同樣名字的標(biāo)量變量, 數(shù)組變量, Hash變量, 函數(shù)變量等.Perl中采用*符號(hào)來表示一個(gè)typeglobs,意思
就是"所有名字為XX的變量",比如:
$type = *test;
此時(shí)變量type中存放的就是當(dāng)前包中所有名字為test的變量,
如果我們調(diào)用語句:
print $$type;
則將$type所指向的變量解釋為標(biāo)量, 類似的可以解釋為數(shù)組, Hash, 函數(shù)等等.
但是, 如果你僅僅想讓這個(gè)typeglobs作用于一個(gè)類型的變量, 也可以明確的指出來, 如:
*dick = \$richard;
這樣dick變量就只能訪問名為richard的標(biāo)量了.
可以把typeglobs想象為另一個(gè)typeglobs的別名, 當(dāng)寫下代碼
$type = *test;
的時(shí)候, type就是test這個(gè)typeglobs的別名了.
Perl中還支持符號(hào)引用, 它可以根據(jù)一個(gè)標(biāo)量存放的字符串去查找名為該字符串的typeglobs,如:
$test = 1;
$name = "test";
print $$name;
Perl解釋器首先去解釋變量$name, 發(fā)現(xiàn)是一個(gè)字符串, 再根據(jù)該字符串去解釋這個(gè)解引用, 也就是說:
$$name -> $test -> 1
在Perl中, 變量的名字是可以和Perl的關(guān)鍵字同名的, 只要在使用的時(shí)候有"足夠的辦法"讓Perl解釋器去明確辨別出來到底是哪種變量.
比如我寫了一個(gè)名為for的函數(shù), 一般而言, 在Perl中, 函數(shù)調(diào)用是可以省略掉前面的&符號(hào)的, 但是在這里對(duì)這個(gè)名為for的函數(shù)則不行,
Perl會(huì)把它解釋為for循環(huán).因此, 要明確的表示是在調(diào)用一個(gè)叫for的函數(shù), 需要在前面加上&符號(hào).對(duì)其它類型的變量, 這個(gè)例子同樣適用.
在<<Perl語言編程>>(大駱駝)中, 將$&%@這幾種分別作用在不同類型變量前面的特殊符號(hào)稱之為"funny character".
在Perl中, 有三種修飾符是修飾變量的作用域的:our, my, local,它們與前面提到的Perl中的作用域息息相關(guān).
our聲明的變量是包全局的, 也就是說, our聲明的變量會(huì)出現(xiàn)在這個(gè)包的符號(hào)表中;my聲明的變量?jī)H作用于一個(gè)塊(block), 在Perl中,
一對(duì){}包起來的部分稱之為一個(gè)塊, 比如一個(gè)函數(shù)是一個(gè)塊, 一個(gè)循環(huán)是一個(gè)塊,等等,my修飾的變量普遍作用于這些地方, 如果沒有在哪一個(gè)
塊中, 那么就僅作用于當(dāng)前文件, 但是,無論如何, my修飾的變量都不會(huì)進(jìn)入一個(gè)包的符號(hào)表中, 這也就意味著my聲明的變量不能使用typeglobs
進(jìn)行訪問, 如:
my $test = 1;
$type = *test;
print $$type;
這段代碼是沒有任何效果的, 因?yàn)樵诋?dāng)前包中找不到名字是test的變量.把上面代碼中修飾變量test的my去掉, 再試試就知道區(qū)別了.
local是作用于那些在符號(hào)表中出現(xiàn)的變量的, 它讓對(duì)這些變量的修改局限在一個(gè)塊(block)中, 比如:
our $var;
$var = 1;
{
local $var;
$var = 2;
print $var, "\n";
}
print $var, "\n";
打印的結(jié)果是
2
1
local的出現(xiàn)讓塊中對(duì)變量var的修改僅僅局限在這個(gè)塊中了.
總結(jié):
1. Perl中有兩個(gè)作用域:符號(hào)表和詞法作用域, 每個(gè)包都有自己的符號(hào)表, 這樣可以避免名字污染問題的出現(xiàn), 類似于C++中的
namespace, 全局變量, 以及用our修飾的變量都屬于這個(gè)作用域, 可以通過:包名稱::變量名稱來訪問一個(gè)包中的全局變量.而詞法作用域
是指的一個(gè)塊, 或者一個(gè)文件, 凡是由my修飾的變量都是詞法作用域中的變量, 它們不會(huì)出現(xiàn)在包中的符號(hào)表中, 在包之外不可見,
更甚者, 如果一個(gè)由my修飾的變量在一個(gè)塊中, 它就僅僅在這個(gè)塊中可見了.
2. 如果想讓對(duì)某個(gè)全局變量的修改局部化, 那么就使用local修飾符, 在出了這個(gè)塊之后, 自動(dòng)恢復(fù)為全局變量原來的數(shù)據(jù).