Perl中的“我的”和“我们的”有什么区别?


Answers:


215

伟大的问题:有什么our不同my和做our什么?

综上所述:

从Perl 5开始可用,my是一种声明非程序包变量的方法,它们是:

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


另一方面,our变量是包变量,因此会自动:

  • 全局变量
  • 绝对不是私人的
  • 不一定是新的
  • 可以使用限定的名称空间(如)在包(或词法范围)之外访问$package_name::variable


使用声明变量our使您可以预先声明变量,以便在use strict不出现输入错误警告或编译时错误的情况下使用它们。从Perl 5.6开始,它已取代了过时的过时工具use vars,后者仅是文件作用域,而没有按词法作用域our

例如,变量$xinside 的正式限定名称package main$main::x。声明our $x允许您$x在脚本使用use strict或的情况下,在声明范围内使用裸变量而不会受到任何惩罚(即,不会导致任何错误)use strict "vars"。作用域可能是一个或两个或多个包,或者一个小块。


2
那么我们与当地有何不同?
内森·费尔曼

17
@Nathan Fellman,local不创建变量。它不涉及到myour在所有。local临时备份变量的值并清除其当前值。
ikegami

1
our变量不是包变量。它们不是全局范围的变量,而是像my变量一样的词法范围变量。您可以在以下程序中看到它:package Foo; our $x = 123; package Bar; say $x;。如果要“声明”包变量,则需要使用use vars qw( $x );our $x;声明一个词法范围的变量,该变量别名为在其中our编译的包中的同名变量。
ikegami,

60

cartman和Olafur的PerlMonks和PerlDoc链接是很好的参考-以下是我的总结:

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

our变量包/文件中的作用域,并从任何代码访问userequire那个包/文件-名称冲突前面加上相应的命名空间包之间解决。

只是为了解决问题,local变量是“动态”范围的,与my变量的不同之处在于,也可以从同一块内调用的子例程访问变量。


+1为“ my如果不在{}s中,则变量在同一个文件内按词法作用”。谢谢,这对我很有用。
Georg

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

11

应对作用域是Perl作用域规则的良好概述。它已经足够老了,our本文正文中没有讨论。最后在“ 注释”部分中进行了介绍。

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


5

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

在Perl中的变量作用域:基础知识上有更多了解


16
小心折腾本地和全球一词。适当的术语是词汇和包。您不能在Perl中创建真正的全局变量,但是有些已经像$ _这样存在,并且local引用具有局部化值的包变量(由local创建),而不是词法变量(由my创建)。
Chas。欧文斯(Owens)2009年

${^Potato}是全球性的 无论您在何处使用它,它都引用相同的变量。
MJD

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中预定义的全局变量。还记得排序功能吗?

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中,默认情况下任何变量都声明为全局变量。

该课程始终是use strict; use warnings;在Perl程序的开头添加的,这将迫使程序员显式声明词法变量,这样我们就不会为理所当然的一些错误所困扰。


有关[“在这里记住[$ a和$ b排序]”的更多信息](stackoverflow.com/a/26128328/1028230)。Perl永远不会停止,令我惊讶。
鲁芬,2015年

4

的perldoc有我们的一个很好的定义。

与my不同,后者既为变量分配存储空间,又将简单名称与该存储空间关联以供在当前范围内使用,而与my则将简单名称与当前包中的软件包变量相关联,以在当前范围内使用。换句话说,我们具有与my相同的作用域规则,但不一定创建变量。


2

这只是与问题有关,但是我发现了一些(对我而言)模糊的perl语法,您可以将其与“我们的”(包)变量一起使用,而不能将其与“ my”(本地)一起使用变量。

#!/usr/bin/perl

our $foo = "BAR";

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

输出:

BAR
BAZ

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


1
不是这样 $ foo $ {foo} $ {'foo'} $ {“ foo”}在变量赋值或取消引用时都相同。交换了我们在上面的例子中做的工作。什么,你可能经历过试图取消引用$ foo的一个包变量,如$主:: foo的或$ :: foo的将仅用于包全局变量,比如那些定义的工作我们
Cosmicnet,2014年

只需使用V5.20重新测试,它肯定不能给予相同的输出我的(它打印BAR两次。)
米沙大风

1
我的测试(在Windows上): perl -e "my $foo = 'bar'; print $foo; ${foo} = 'baz'; pr int $foo"输出:barbaz perl -e "my $foo = 'bar'; print $foo; ${"foo"} = 'baz'; print $foo"输出:barbaz perl -e "my $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"输出:barbar 因此,在测试中,我陷入了同一个陷阱。$ {foo}与$ foo相同,括号在插值时很有用。$ {“ foo”}实际上是对$ main :: {}的查找,它是主符号表,因此仅包含包范围的变量。
Cosmicnet,2014年

1
$ {“ main :: foo”},$ {“ :: foo”}和$ main :: foo与$ {“ foo”}相同。速记是软件包敏感的perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"作品,因为在这种情况下,$ {“ foo”}现在等于$ {“ test :: foo”}。Symbol Tables and Globs的内容以及Advanced Perl编程书中都有一些信息。对不起,我以前的错误。
Cosmicnet,2014年

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.

请提供某种解释。这样的转储代码很少被认为是适当的。
Scott Solmer 2014年

简而言之:我们的名称(如sais)是一个变量斜率,可以在脚本中的任何位置(函数,块等)使用该变量,默认情况下,每个变量(如果未声明)都属于“ main”包,即使脚本中的另一个包被废弃后,我们的变量仍然可以使用。如果在块或函数中声明了“ my”变量,则只能在该块/函数中使用。万一声明“ my”变量未在某个块中关闭,则可以在脚本中的任何地方,在一个封闭的块中或在“我们”变量的函数中使用它,但不能在更改包的情况下使用
Lavi Buchnik 2014年

上面的脚本显示默认情况下,我们位于“ main”包中,然后该脚本从“ main”包中打印“ our”变量(未在块中关闭),然后在函数中声明两个“ my”变量,从该功能打印它们。然后我们从另一个函数中打印一个“我们的”变量,以表明它可以在一个函数中使用。然后我们将包更改为“ changed”(不再更改为“ main”),然后再次成功打印“ our”变量。然后尝试在函数外部打印“ my”变量,但失败。该脚本仅显示“我们”和“我”用法之间的区别。
Lavi Buchnik 2014年

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

这解释了我和我们之间的区别。my变量超出了花括号之外的范围,并被垃圾回收,但我们的变量仍然有效。
Yugdev 2015年

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

您能解释一下此代码演示的意思吗?为什么ourmy不同?这个例子如何显示呢?
弥敦道·费尔曼

-1

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

遇到“我的”时,解释器会创建一个词法变量:解释器仅在执行一个块时才可以访问该命名值,并且只能从该语法块中访问。遇到“我们的”时,解释器会为包变量创建一个词法别名:它将一个名称(该解释器从那时起应该以词法变量的名称处理,直到块完成)绑定到包的值具有相同名称的变量。

结果是您可以假装您正在使用词法变量,并绕过对包变量进行完全限定的“严格使用”规则。由于解释器在首次使用时会自动创建包变量,因此使用“我们的”的副作用还可能是解释器也会创建包变量。在这种情况下,将创建两件事:一个包变量,解释器可以从任何地方访问该包变量,前提是它已按照“ use strict”(使用其包名和两个冒号的名称)的要求正确指定,具有其词法别名。

资料来源:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.