我知道my
Perl中有什么。它定义了一个变量,该变量仅存在于定义该变量的块的范围内。怎么our
办?
如何our
从不同my
?
我知道my
Perl中有什么。它定义了一个变量,该变量仅存在于定义该变量的块的范围内。怎么our
办?
如何our
从不同my
?
Answers:
伟大的问题:有什么our
不同my
和做our
什么?
综上所述:
从Perl 5开始可用,my
是一种声明非程序包变量的方法,它们是:
$package_name::variable
。另一方面,our
变量是包变量,因此会自动:
$package_name::variable
。使用声明变量our
使您可以预先声明变量,以便在use strict
不出现输入错误警告或编译时错误的情况下使用它们。从Perl 5.6开始,它已取代了过时的过时工具use vars
,后者仅是文件作用域,而没有按词法作用域our
。
例如,变量$x
inside 的正式限定名称package main
是$main::x
。声明our $x
允许您$x
在脚本使用use strict
或的情况下,在声明范围内使用裸变量而不会受到任何惩罚(即,不会导致任何错误)use strict "vars"
。作用域可能是一个或两个或多个包,或者一个小块。
local
不创建变量。它不涉及到my
和our
在所有。local
临时备份变量的值并清除其当前值。
our
变量不是包变量。它们不是全局范围的变量,而是像my
变量一样的词法范围变量。您可以在以下程序中看到它:package Foo; our $x = 123; package Bar; say $x;
。如果要“声明”包变量,则需要使用use vars qw( $x );
。our $x;
声明一个词法范围的变量,该变量别名为在其中our
编译的包中的同名变量。
cartman和Olafur的PerlMonks和PerlDoc链接是很好的参考-以下是我的总结:
my
{}
如果不在{}
s中,则变量按词法作用于由同一文件定义或在同一文件中定义的单个块内。不能从相同词法作用域/块之外定义的包/子例程访问它们。
our
变量包/文件中的作用域,并从任何代码访问use
或require
那个包/文件-名称冲突前面加上相应的命名空间包之间解决。
只是为了解决问题,local
变量是“动态”范围的,与my
变量的不同之处在于,也可以从同一块内调用的子例程访问变量。
my
如果不在{}
s中,则变量在同一个文件内按词法作用”。谢谢,这对我很有用。
一个例子:
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";
my
用于局部变量,而our
用于全局变量。
在Perl中的变量作用域:基础知识上有更多了解。
${^Potato}
是全球性的 无论您在何处使用它,它都引用相同的变量。
我曾经在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程序的开头添加的,这将迫使程序员显式声明词法变量,这样我们就不会为理所当然的一些错误所困扰。
该的perldoc有我们的一个很好的定义。
与my不同,后者既为变量分配存储空间,又将简单名称与该存储空间关联以供在当前范围内使用,而与my则将简单名称与当前包中的软件包变量相关联,以在当前范围内使用。换句话说,我们具有与my相同的作用域规则,但不一定创建变量。
这只是与问题有关,但是我发现了一些(对我而言)模糊的perl语法,您可以将其与“我们的”(包)变量一起使用,而不能将其与“ my”(本地)一起使用变量。
#!/usr/bin/perl
our $foo = "BAR";
print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";
输出:
BAR
BAZ
如果将“我们的”更改为“我的”,则此方法将无效。
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 :: {}的查找,它是主符号表,因此仅包含包范围的变量。
perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"
作品,因为在这种情况下,$ {“ foo”}现在等于$ {“ test :: foo”}。Symbol Tables and Globs的内容以及Advanced Perl编程书中都有一些信息。对不起,我以前的错误。
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";
#!/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;
our
和my
不同?这个例子如何显示呢?
让我们考虑一下解释器实际上是什么:这是一段代码,将值存储在内存中,并让解释它的程序中的指令通过它们的名称访问这些值,这些名称在这些指令中指定。因此,解释器的主要工作是制定规则,以决定如何使用这些指令中的名称来访问解释器存储的值。
遇到“我的”时,解释器会创建一个词法变量:解释器仅在执行一个块时才可以访问该命名值,并且只能从该语法块中访问。遇到“我们的”时,解释器会为包变量创建一个词法别名:它将一个名称(该解释器从那时起应该以词法变量的名称处理,直到块完成)绑定到包的值具有相同名称的变量。
结果是您可以假装您正在使用词法变量,并绕过对包变量进行完全限定的“严格使用”规则。由于解释器在首次使用时会自动创建包变量,因此使用“我们的”的副作用还可能是解释器也会创建包变量。在这种情况下,将创建两件事:一个包变量,解释器可以从任何地方访问该包变量,前提是它已按照“ use strict”(使用其包名和两个冒号的名称)的要求正确指定,并具有其词法别名。
资料来源: