我和我们在Perl中有什么区别?

我知道my在Perl中是什么。 它定义了一个只存在于其定义块的范围内的variables。 our做什么? ourmy什么不同?

好问题: ourmy什么不同? ourour什么?

综上所述:

从Perl 5开始可用, my是一种声明:

  • 非包variables,即
  • 私人的,
  • 新的
  • 非全局variables,
  • 与任何包裹分开。 所以variables不能$package_name::variable的forms被访问。

另一方面, ourvariables是:

  • 包variables,从而自动
  • 全局variables,
  • 绝对不是私人的
  • 也不一定是新的; 和他们
  • 可以使用合格的命名空间在包(或词法范围)之外访问,如$package_name::variable

使用our声明variables允许您预先声明variables,以便在use strict使用它们的情况下use strict它们,而不会发生错误警告或编译时错误。 自从Perl 5.6以来,它已经取代了过时的use vars ,这只是文件范围,而不是像our那样在词汇范围内。

例如, package mainvariables$x的forms,限定名是$main::x 。 声明our $x允许您在声明范围内使用纯正的$xvariables而不会受到惩罚(即不会产生错误),当脚本use strictuse strict "vars" 。 范围可能是一个或两个或更多包,或一个小块。

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

myvariables在{} s定义的单个块中的词汇范围内,如果不在{}则在同一个文件中。 它们不能从在同一个词法作用域/块之外定义的包/子程序访问。

ourvariables被限定在一个包/文件中,并且可以从任何userequire在包之间解决包/文件名冲突的代码中访问,通过预先join适当的名称空间。

只是为了完成它, localvariables是“dynamic”的作用域,不同于myvariables,因为它们也可以从同一块内调用的子例程访问。

一个例子:

 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=$om=$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=$om=$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范围规则的一个很好的概述。 这已经够老了, our没有在正文中讨论。 它在最后的注释部分被解决。

本文讨论包variables和dynamic范围,以及它与词法variables和词法范围的区别。

我用于局部variables,因为我们用于全局variables。 更多阅读Perl中的variables范围:基础知识 。

这是一个古老的问题,但是我遇到过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声明一个variables之前,请确保它之前被定义为一个全局variables。

但为什么这不会失败?

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

输出是: var: 42

这是因为$a$b是Perl中预先定义的全局variables。 记得sortingfunction?

2.词汇还是全球?

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

在C中,外部variables是在任何function块之外定义的variables。 另一方面,自动variables是在function块内定义的variables。 喜欢这个:

 int global; int main(void) { int local; } 

在Perl中,事情是微妙的:

 sub main { $var = 42; } &main; print "var: $var\n"; 

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

教训是总要加use strict; use warnings; use strict; use warnings; 在Perl程序开始的时候,这将迫使程序员明确地声明词法variables,这样我们就不会被一些理所当然的错误所迷惑。

perldoc对我们的定义很好。

与我不同,我为variables分配存储空间并将简单名称与该存储空间关联以用于当前范围,我们将当前包中的简单名称与包variables相关联,以便在当前范围内使用。 换句话说,我们和我有相同的范围规则,但不一定会创build一个variables。

这只是与这个问题有些相关,但是我刚刚发现了一个(对我而言)隐藏的Perl语法,你可以使用“我们的”(包)variables来使用你不能与“我的”(本地)variables。

 #!/usr/bin/perl our $foo = "BAR"; print $foo . "\n"; ${"foo"} = "BAZ"; print $foo . "\n"; 

输出:

 BAR BAZ 

如果您将“我们”更改为“我的”,这将不起作用。

 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 

如果使用“严格使用”将尝试运行该脚本时会出现此故障:

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

只要尝试使用以下程序:

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

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

在遇到“我的”时,解释器会创build一个词法variables:解释器只能在执行块时访问的命名值,并且只能从该语法块中访问。 在遇到“我们的”时,解释器会创build一个包variables的词汇别名:它绑定一个名称,解释器从此开始将该名称作为一个词汇variables的名称进行处理,直到块完成为止。variables名称相同。

结果是,你可以假装你正在使用一个词法variables,并绕过对packagevariables完全限定的'use strict'规则。 由于解释器在第一次使用时自动创build包variables,所以使用“我们”的副作用也可能是解释器也创build包variables。 在这种情况下,创build了两个东西:一个包variables,解释器可以从任何地方访问它,只要它按照'use strict'(包括它的包名和两个冒号前缀)及其词法别名的要求正确指定。

资料来源: