我和Perl之间的区别是什么?

时间:2009-05-10 10:24:54

标签: perl scope

我知道Perl中的my是什么。它定义了一个仅存在于定义它的块范围内的变量。 our做了什么? ourmy的区别如何?

12 个答案:

答案 0 :(得分:205)

很棒的问题: our my 的区别是什么? our 吗?

摘要:

从Perl 5开始提供, my 是一种声明方式:

  • 非包裹变量,即
  • 私有,
  • new
  • 非全局变量,
  • 与任何包裹分开。因此,不能以$package_name::variable
  • 的形式访问变量


另一方面, our 变量是:

  • 包变量,因而自动
  • 全球变量,
  • 绝对不私有
  • 也不一定是新的;他们
  • 可以使用
  • 在包(或词法范围)之外访问 限定名称空间,为$package_name::variable


使用 our 声明变量可让您预先声明变量,以便在 use strict 下使用它们获取拼写错误警告或编译时错误。从Perl 5.6开始,它已经取代了过时的 use vars ,它只是文件作用域,而不是像 our 那样的词法作用域。

例如,$x中变量package main的正式限定名称为$main::x。声明 our $x 允许您在声明范围内使用裸$x变量而不会受到惩罚(即没有产生错误),当脚本使用 use strict use strict "vars" 时。范围可能是一个,两个或更多个包,或一个小块。

答案 1 :(得分:59)

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

my变量在{}定义的单个块内或在同一文件中(如果不在{} s内)在词法范围内。无法从相同词法范围/块之外定义的包/子例程访问它们。

our变量的范围在一个包/文件中,并且可以通过预先添加适当的命名空间从userequire可以在包之间解析包/文件名冲突的任何代码访问。

为了完善它,local变量是“动态”范围的,与my变量不同,因为它们也可以从同一个块中调用的子程序访问。

答案 2 :(得分:48)

一个例子:

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";

答案 3 :(得分:12)

Coping with Scoping是对Perl范围规则的一个很好的概述。它足够古老,our未在文本正文中讨论。它在最后的注释部分中进行了解决。

本文讨论了包变量和动态范围,以及它与词法变量和词法范围的区别。

答案 4 :(得分:6)

my用于局部变量,其中我们用于全局变量。更多阅读Variable Scoping in Perl: the basics

答案 5 :(得分:5)

这是一个古老的问题,但我遇到了一些关于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未定义,这意味着local $var;只是一个声明!在使用local声明变量之前,请确保先前将其定义为全局变量。

但为什么这不会失败?

use strict;
use warnings;

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

输出为:var: 42

这是因为$a以及$b是Perl中预定义的全局变量。还记得sort功能吗?

<强> 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程序的开头添加use strict; use warnings;,这将迫使程序员明确声明词法变量,这样我们就不会因为某些错误而搞砸了理所当然的。

答案 6 :(得分:4)

perldoc对我们的定义很好。

  

与我分别为变量分配存储并将简单名称与该存储关联以在当前范围内使用的情况不同,我们将简单名称与当前包中的包变量相关联,以便在当前范围内使用。换句话说,我们具有与我相同的范围规则,但不一定会创建变量。

答案 7 :(得分:2)

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

#!/usr/bin/perl

our $foo = "BAR";

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

输出:

BAR
BAZ

如果您将“我们的”更改为“我的”,则无效。

答案 8 :(得分:0)

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.

答案 9 :(得分:0)

尝试使用以下程序:

#!/usr/local/bin/perl
use feature ':5.10';
#use warnings;
package a;
{
my $b = 100;
our $a = 10;


print "$a \n";
print "$b \n";
}

package b;

#my $b = 200;
#our $a = 20 ;

print "in package b value of  my b $a::b \n";
print "in package b value of our a  $a::a \n";

答案 10 :(得分:-1)

#!/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;

答案 11 :(得分:-1)

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

在遇到&#34; my&#34;时,解释器会创建一个词法变量:解释器只能在执行块时才能访问的命名值,并且只能从该语法块中访问。在遇到&#34;我们的&#34;时,解释器会创建一个包变量的词法别名:它绑定一个名称,解释器从那时起应该处理为一个词汇变量的名称,直到块为止完成后,使用相同名称的包变量的值。

效果是你可以假装你正在使用词汇变量并绕过“使用严格”的规则。关于包变量的完全限定。由于解释器在首次使用时会自动创建包变量,因此使用&#34;我们的&#34;也可能是解释器也创建了一个包变量。在这种情况下,创建了两件事:一个包变量,解释器可以从任何地方访问它,只要它被正确地指定为使用严格的&#39; (前面加上它的包名和两个冒号),它的词汇别名。

来源: