如何更改模块使用的包中的变量值,以便该模块中的子程序可以使用它?
这是我的测试用例:
testmodule.pm:
package testmodule;
use strict;
use warnings;
require Exporter;
our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
@ISA = qw(Exporter);
@EXPORT = qw(testsub);
my $greeting = "hello testmodule";
my $var2;
sub testsub {
printf "__PACKAGE__: %s\n", __PACKAGE__;
printf "\$main::greeting: %s\n", $main::greeting;
printf "\$greeting: %s\n", $greeting;
printf "\$testmodule::greeting: %s\n", $testmodule::greeting;
printf "\$var2: %s\n", $var2;
} # End testsub
1;
testscript.pl:
#!/usr/bin/perl -w
use strict;
use warnings;
use testmodule;
our $greeting = "hello main";
my $var2 = "my var2 in testscript";
$testmodule::greeting = "hello testmodule from testscript";
$testmodule::var2 = "hello var2 from testscript";
testsub();
输出:
Name "testmodule::var2" used only once: possible typo at ./testscript.pl line 11.
__PACKAGE__: testmodule
$main::greeting: hello main
$greeting: hello testmodule
$testmodule::greeting: hello testmodule from testscript
Use of uninitialized value $var2 in printf at testmodule.pm line 20.
$var2:
我希望$greeting
和$testmodule::greeting
相同,因为子例程的包是testmodule
。
我想这与use
d模块eval
d的方式有关,就好像在BEGIN
块中一样,但我想更好地理解它。
我希望从主脚本设置变量的值,并在模块的子例程中使用它,而不使用变量的完全限定名称。
答案 0 :(得分:11)
正如您所知,当您使用my
时,您正在创建一个本地范围的非包变量。要创建包变量,请使用our
而非my
:
my $foo = "this is a locally scoped, non-package variable";
our $bar = "This is a package variable that's visible in the entire package";
更好:
{
my $foo = "This variable is only available in this block";
our $bar = "This variable is available in the whole package":
}
print "$foo\n"; #Whoops! Undefined variable
print "$bar\n"; #Bar is still defined even out of the block
如果未在程序中放置use strict
,则定义的所有变量都是包变量。这就是为什么当你没有把它,它按照你认为的方式工作,并把它放在打破你的程序。
但是,正如您在以下示例中所看到的,使用our
将解决您的困境:
Local/Foo.pm
#! /usr/local/bin perl
package Local::Foo;
use strict;
use warnings;
use feature qw(say);
use Exporter 'import';
our @EXPORT = qw(testme);
our $bar = "This is the package's bar value!";
sub testme {
# $foo is a locally scoped, non-package variable. It's undefined and an error
say qq(The value of \$main::foo is "$main::foo");
# $bar is defined in package main::, and will print out
say qq(The value of \$main::bar is "$main::bar");
# These both refer to $Local::Foo::bar
say qq(The value of \$Local::Foo::bar is "$Local::Foo::bar");
say qq(The value of bar is "$bar");
}
1;
test.pl
#! /usr/local/bin perl
use strict;
use warnings;
use feature qw(say);
use Local::Foo;
my $foo = "This is foo";
our $bar = "This is bar";
testme;
say "";
$Local::Foo::bar = "This is the NEW value for the package's bar";
testme
而且,输出是:
Use of uninitialized value $foo in concatenation (.) or string at Local/Foo.pm line 14.
The value of $main::foo is ""
The value of $main::bar is "This is bar"
The value of $Local::Foo::bar is "This is the package's bar value!"
The value of bar is "This is the package's bar value!"
Use of uninitialized value $foo in concatenation (.) or string at Local/Foo.pm line 14.
The value of $main::foo is ""
The value of $main::bar is "This is bar"
The value of $Local::Foo::bar is "This is the NEW value for the package's bar"
The value of bar is "This is the NEW value for the package's bar"
您获得的错误消息是$foo
作为局部变量的结果,因此在包内不可见。同时,$bar
是一个包变量,可见。
有时,它可能有点棘手:
if ($bar -eq "one") {
my $foo = 1;
}
else {
my $foo = 2;
}
print "Foo = $foo\n";
这不起作用,因为$foo
仅在if
块内部有一个值。你必须这样做:
my $foo;
if ($bar -eq "one") {
$foo = 1;
}
else {
$foo = 2;
}
print "Foo = $foo\n"; #This works!
是的,最初可能会让你的脑袋缠绕起来,但use strict;
和use warnings;
的使用现在已经得到了充分的理由。使用use strict;
和use warnings;
可能已经消除了人们在Perl中犯下的90%的错误。您不能错误地在程序的一个部分中设置$foo
的值,并尝试在另一个部分中使用$Foo
。这是我在Python中真正想念的事情之一。
答案 1 :(得分:8)
在仔细阅读Variable Scoping in Perl: the basics后,我意识到用my
声明的变量不在当前包中。例如,如果我声明my $var = "hello"
$main::var
仍然没有值,则在没有模块的简单脚本中。
在这种情况下适用的方式是在模块中。由于my $greeting
在文件中声明,因此隐藏了包的版本$greeting
,这是子例程看到的值。如果我不首先声明变量,子程序将看到包变量,但它没有那么远,因为我use strict
。
如果我没有use strict
而且没有声明my $greeting
,那么它就像我预期的那样有效。获得预期值而不是中断use strict
的另一种方法是使用our $greeting
。不同之处在于my在当前 范围 中声明变量,而our在当前 包中声明变量< /强> 的