'my'和& # 39;我们的# 39;在Perl中?

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

ourmy有什么不同?

126213 次浏览

perldoc有一个很好的定义。

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

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

更多阅读请访问 Perl中的变量作用域:基础知识 . 0

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

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

our变量的作用域在包/文件中,并且可以从userequire的任何代码中访问,即包/文件名称冲突通过预先指定适当的命名空间来解决。

简单地说,local变量是“动态”限定的,与my变量不同的是,它们也可以从同一块内调用的子例程中访问。

处理范围是Perl作用域规则的一个很好的概述。它已经足够老了,所以our没有在正文中讨论。它在结尾的笔记部分中被处理。

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

< >强our < / >强< >强my < / >强有什么不同,our做什么?

总而言之:

自Perl 5起可用,< >强my < / >强是一种声明非包变量的方法,它们是:

  • 私人
  • 非全局
  • 与任何包分离,以便变量不能可以以$package_name::variable的形式访问。

另一方面,< >强our < / >强变量是包变量,因此自动:

  • 全球变量
  • 绝对不是私人
  • 不一定是新的
  • 可以可以在包(或词法作用域)之外使用 .限定的命名空间,如$package_name::variable

使用< >强our < / >强声明变量允许你预先声明变量,以便在use strict下使用它们,而不会得到拼写警告或编译时错误。自Perl 5.6以来,它取代了过时的use vars,后者只是文件作用域,而不像< >强our < / >强那样是词法作用域。

例如,package main内部变量$x的正式限定名是$main::x。当脚本使用use strictuse strict "vars"时,声明< >强our $x < / >强允许你在声明的范围内使用纯$x变量而不受惩罚(即,不会产生错误)。范围可以是一个、两个或多个包,或者一个小块。

一个例子:

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”,这就行不通了。

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

我曾经在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中,任何变量都默认声明为全局变量。

教训是总是在Perl程序的开头添加use strict; use warnings;,这将迫使程序员显式声明词法变量,这样我们就不会被一些想当然的错误搞得一团糟。

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.

试着使用下面的程序:

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

这样做的效果是,您可以假装使用词法变量,并绕过包变量完全限定的“严格使用”规则。由于解释器在第一次使用包变量时自动创建包变量,使用"our"的副作用也可能是解释器也创建了一个包变量。在这种情况下,创建了两个东西:一个包变量,解释器可以从任何地方访问它,只要它被'use strict'(前面加上它的包名和两个冒号)正确指定,而且它的词汇别名。

来源: