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

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


当前回答

#!/usr/bin/perl -l

use strict;

# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'

our $lol = eval {$lol} || 'lol' ;

print $lol;

其他回答

一个例子:

use strict;

for (1 .. 2){
    # Both variables are lexically scoped to the block.
    our ($o);  # Belongs to 'main' package.
    my  ($m);  # Does not belong to a package.

    # The variables differ with respect to newness.
    $o ++;
    $m ++;
    print __PACKAGE__, " >> o=$o m=$m\n";  # $m is always 1.

    # The package has changed, but we still have direct,
    # unqualified access to both variables, because the
    # lexical scope has not changed.
    package Fubb;
    print __PACKAGE__, " >> o=$o m=$m\n";
}

# The our() and my() variables differ with respect to privacy.
# We can still access the variable declared with our(), provided
# that we fully qualify its name, but the variable declared
# with my() is unavailable.
print __PACKAGE__, " >> main::o=$main::o\n";  # 2
print __PACKAGE__, " >> main::m=$main::m\n";  # Undefined.

# Attempts to access the variables directly won't compile.
# print __PACKAGE__, " >> o=$o\n";
# print __PACKAGE__, " >> m=$m\n";

# Variables declared with use vars() are like those declared
# with our(): belong to a package; not private; and not new.
# However, their scoping is package-based rather than lexical.
for (1 .. 9){
    use vars qw($uv);
    $uv ++;
}

# Even though we are outside the lexical scope where the
# use vars() variable was declared, we have direct access
# because the package has not changed.
print __PACKAGE__, " >> uv=$uv\n";

# And we can access it from another package.
package Bubb;
print __PACKAGE__, " >> main::uv=$main::uv\n";

这只是与问题有点相关,但我刚刚发现了一个(对我来说)模糊的perl语法,你可以使用“我们的”(包)变量,而不能使用“我的”(本地)变量。

#!/usr/bin/perl

our $foo = "BAR";

print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";

输出:

BAR
BAZ

如果你把“our”改成“my”,这就行不通了。

我曾经在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程序的开始,这将迫使程序员显式地声明词法变量,这样我们就不会被一些想当然的错误弄乱。

来自cartman和Olafur的PerlMonks和PerlDoc链接是一个很好的参考-下面是我的总结:

我的变量在词法上是在一个由{}定义的块中,如果不在{}s中,则在同一个文件中。它们不能从同一词法作用域/块之外定义的包/子例程中访问。

变量的作用域在包/文件内,可以从任何使用或要求包/文件名称冲突通过预挂适当的名称空间来解决的代码中访问。

只是为了完善它,局部变量是“动态”范围的,与我的变量不同的是,它们也可以从同一块中调用的子例程中访问。

My用于局部变量,而our用于全局变量。

更多内容请参阅Perl中的变量作用域:基础知识。