例如
out.pl:
(my|our|local|global|whatever???) var = "test";
require("inside.pm");
inside.pm:
print $var;
我不想使用包 - 它压倒了我的需求:) 谢谢!
答案 0 :(得分:5)
即使您不使用package
声明,您总是使用包。默认情况下,您正在使用包main
。
您使用our
声明的所有变量都是包变量,并且应该在包范围内可用。这是一个例子:
#! /usr/bin/env perl
# test2.pl
use strict;
use warnings;
our $foo = "bar";
1;
由于$foo
被声明为包变量,因此它将在其他程序中可用:
#! /usr/bin/env perl
use strict;
use warnings;
require "test2.pl";
our $foo;
print "The value of \$foo is $foo\n";
现在我给了你足够的绳子,我要告诉你不要把它挂起来。
这是 非常糟糕,非常糟糕的想法 。请注意$foo
从一种几乎不可能弄清楚的某种神秘机制中获取值?
包太复杂?真?这并不难!看看这个例子:
#! /usr/bin/env perl
# test2.pm
package test2;
use strict;
use warnings;
our $foo = "bar";
1;
除了我添加package
声明并现在调用我的计划test2.pm
而不是test2.pl
之外,与之前没有太大的不同。
以下是我访问它的方式:
#! /usr/bin/env perl
use strict;
use warnings;
use test2;
print "The value of \$foo from package test2 is $test2::foo\n";
我所要做的就是在变量中使用包名。这是一个 BAD IDEA ,但它比上面显示的 REALLY,REALLY BAD IDEA 更好。
至少,你知道价值来自哪里。它来自test2.pm
。并且,如果在子例程中设置变量,则可以访问该变量。
#! /usr/bin/env perl
# test2.pm
package test2;
use strict;
use warnings;
sub fooloader {
our $foo = "bar";
}
1;
请注意,$foo
在子例程fooloader
中设置。而且,这是我的另一个访问它的程序:
#! /usr/bin/env perl
use strict;
use warnings;
use test2;
&test2::fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";
现在,您可以使用导出器导出子例程(甚至是变量),但这不再是您看得太多的东西了。主要是因为它是 非常糟糕的想法 。没有原来的 非常糟糕的想法 那么糟糕,但比上面的 BAD IDEA 更糟糕:
#! /usr/bin/env perl
# test2.pm
package test2;
use base qw(Exporter);
our @EXPORT = qw(fooloader);
use strict;
use warnings;
sub fooloader {
our $foo = "bar";
}
1;
现在,我可以使用没有包名称的子例程fooloader
:
#! /usr/bin/env perl
use strict;
use warnings;
use test2;
fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";
问题当然是你不知道子程序fooloader
的来源。如果您使用的是@EXPORT_OK
而不是@EXPORT
,则可以使用use test2 qw(fooloader);
并记录fooloader
函数的来源。它还可以帮助您了解不要在自己的程序中创建自己的fooloader
函数并覆盖您导入的函数。然后,想知道为什么你的程序不再有效。
顺便说一下,您还可以导出变量而不仅仅是函数。然而,这变成了 真的,真的,真的很糟糕 - 没有可怕的想法 ,因为它违反了你首先使用包裹的所有原因。如果你打算这样做,为什么要打扰包裹呢?为什么不简单地拿枪并用脚射击自己?
最好和首选的方法是使用面向对象的Perl并在 THOROUGHLY CORRECT WAY 中执行此操作。一种让您确切了解正在发生的事情以及原因的方法。并且,可以很容易地弄清楚您的代码在做什么。一种将错误保持在最低限度的方法。
看看彻底面向对象的Test2类:
#! /usr/bin/env perl
# Test2.pm
package Test2;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub FooValue {
return "bar";
}
1;
并使用Test2
类:
#! /usr/bin/env perl
use strict;
use warnings;
use Test2;
my $tester = Test2->new;
print "The value of foo from package test2 is " . $tester->FooValue . "\n";
这是最好的方法,因为即使您使用包,您也可以操纵$test2::foo
的值,它将在整个程序中更改。想象一下,如果这是$constants::pi
,而你在某处将其从3.14159更改为3.从那时起,使用$constants::pi
会给你错误的值。如果使用面向对象的方法,则无法更改方法Constant-> Pi的值。它总是3.14159。
那么,我们今天学到了什么?
我们了解到Perl很容易做一些 真的,非常糟糕的想法 ,但使用包不需要太多工作,所以它只是一个 BAD IDEA 。而且,如果你开始学习一些面向对象的Perl,你可以毫不费力地在 THOROUGHLY CORRECT WAY 中完成所有工作。
您可以选择。记住你拍的脚可能是你自己的。
答案 1 :(得分:4)
它适用于our
。
$ cat out.pl
our $var = "test";
require("inside.pm");
$ cat inside.pm
print "Testing...\n";
print "$var\n";
$ perl out.pl
Testing...
test
这是有效的,因为our
使$var
全局,inside.pm
正在定义$var
的范围内执行。不确定它是推荐的技术,但它仍然是一个有趣的问题!
编辑:需要根据评论澄清(好补丁)答案:
来自the documentation on the Perl function our
:
our
将一个简单名称与当前包中的包(读取:全局)变量相关联,以便在当前词法范围内使用。换句话说,our
具有与my
或state
相同的范围规则,但不一定会创建变量。
所以使用our
,我们得到$var
当前包(这里可能是main
),我们可以在其范围内使用它。实际上,它对于您要求的文件中的代码是“全局的”。
在没有our
的情况下引入真正的全局,因为变量默认为全局。但我不认识任何推荐他们的人。