我知道my在Perl中是什么。它定义了一个只存在于定义它的块范围内的变量。我们该怎么做?

我们的和我的有什么不同?


当前回答

print "package is: " . __PACKAGE__ . "\n";
our $test = 1;
print "trying to print global var from main package: $test\n";

package Changed;

{
        my $test = 10;
        my $test1 = 11;
        print "trying to print local vars from a closed block: $test, $test1\n";
}

&Check_global;

sub Check_global {
        print "trying to print global var from a function: $test\n";
}
print "package is: " . __PACKAGE__ . "\n";
print "trying to print global var outside the func and from \"Changed\" package:     $test\n";
print "trying to print local var outside the block $test1\n";

输出:

package is: main
trying to print global var from main package: 1
trying to print local vars from a closed block: 10, 11
trying to print global var from a function: 1
package is: Changed
trying to print global var outside the func and from "Changed" package: 1
trying to print local var outside the block 

如果使用"use strict"会在试图运行脚本时失败:

Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.

其他回答

处理作用域是对Perl作用域规则的一个很好的概述。它已经足够古老了,所以我们没有在正文中讨论。在最后的Notes一节中讨论了这个问题。

本文讨论包变量和动态作用域,以及它们与词法变量和词法作用域的区别。

我曾经在Perl中遇到过一些关于词汇声明的陷阱,这些陷阱也与这个问题有关,所以我在这里添加了我的总结:

1. 定义还是声明?

local $var = 42;
print "var: $var\n";

输出为var: 42。但是我们不知道local $var = 42;定义或声明。但是这个怎么样:

use strict;
use warnings;

local $var = 42;
print "var: $var\n";

第二个程序将抛出一个错误:

Global symbol "$var" requires explicit package name.

$var没有定义,这意味着本地的$var;只是一个宣言!在使用local声明变量之前,请确保之前已将其定义为全局变量。

但为什么这不会失败呢?

use strict;
use warnings;

local $a = 42;
print "var: $a\n";

输出为:var: 42。

这是因为$a和$b都是在Perl中预定义的全局变量。还记得排序函数吗?

2. 词汇的还是全局的?

在开始使用Perl之前,我是一名C程序员,所以词法变量和全局变量的概念对我来说似乎很简单:它只对应于C中的自动变量和外部变量,但有一些小的区别:

在C语言中,外部变量是定义在任何函数块之外的变量。另一方面,自动变量是在函数块中定义的变量。是这样的:

int global;

int main(void) {
    int local;
}

而在Perl中,事情是微妙的:

sub main {
    $var = 42;
}

&main;

print "var: $var\n";

输出为var: 42。$var是一个全局变量,即使它是定义在函数块中!实际上,在Perl中,任何变量都默认声明为全局变量。

教训是要时刻加用严;使用警告;在Perl程序的开始,这将迫使程序员显式地声明词法变量,这样我们就不会被一些想当然的错误弄乱。

perldoc对我们的。

与我的方法不同,我的方法既为变量分配存储空间,又将一个简单的名称与该存储空间关联起来,以便在当前作用域内使用,而我们的方法则将一个简单的名称与当前包中的一个包变量关联起来,以便在当前作用域内使用。换句话说,our具有与my相同的作用域规则,但不一定创建变量。

print "package is: " . __PACKAGE__ . "\n";
our $test = 1;
print "trying to print global var from main package: $test\n";

package Changed;

{
        my $test = 10;
        my $test1 = 11;
        print "trying to print local vars from a closed block: $test, $test1\n";
}

&Check_global;

sub Check_global {
        print "trying to print global var from a function: $test\n";
}
print "package is: " . __PACKAGE__ . "\n";
print "trying to print global var outside the func and from \"Changed\" package:     $test\n";
print "trying to print local var outside the block $test1\n";

输出:

package is: main
trying to print global var from main package: 1
trying to print local vars from a closed block: 10, 11
trying to print global var from a function: 1
package is: Changed
trying to print global var outside the func and from "Changed" package: 1
trying to print local var outside the block 

如果使用"use strict"会在试图运行脚本时失败:

Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.

让我们思考一下解释器到底是什么:它是一段在内存中存储值的代码,并让它所解释的程序中的指令通过指令中指定的名称访问这些值。因此,解释器的主要工作是制定规则,规定我们应该如何在这些指令中使用名称来访问解释器存储的值。

在遇到“my”时,解释器创建一个词法变量:解释器只能在执行块时访问一个命名值,而且只能从该语法块中访问。在遇到“our”时,解释器会为包变量创建一个词法别名:它将一个名称绑定到具有相同名称的包变量的值上,从那时起解释器就应该将其作为词法变量的名称处理,直到块完成。

The effect is that you can then pretend that you're using a lexical variable and bypass the rules of 'use strict' on full qualification of package variables. Since the interpreter automatically creates package variables when they are first used, the side effect of using "our" may also be that the interpreter creates a package variable as well. In this case, two things are created: a package variable, which the interpreter can access from everywhere, provided it's properly designated as requested by 'use strict' (prepended with the name of its package and two colons), and its lexical alias.

来源:

http://perldoc.perl.org/functions/our.html http://perldoc.perl.org/perlsub.html Private-Variables-via-my ()