如何在 perl 的本地范围内访问导入模块中的变量?
how to access variables in imported module in local scope in perl?
我在创建 perl Moose 模块时卡住了。
我有一个全局 pm 模块。
package XYZ;
require Exporter;
our @ISA = qw(Exporter); ## EDIT missed this line
our @EXPORT_OK = qw($VAR);
my $VAR1 = 1;
our $VAR = {'XYZ' => $VAR1};
1;
我想在我正在创建的 Moose
模块中获得 $VAR
package THIS;
use Moose;
use YAML::XS;
sub get_all_blocks{
my ($self) = @_;
require $self->get_pkg(); # this returns the full path+name of the above package
# i cannot use use lib+use since the get_pkg starts complaining
our $VAR;
print YAML::XS::Dump($XYZ::VAR); # this works
print YAML::XS::Dump($VAR); # this does not work
# i cannot use the scope resolution since XYZ would keep changing.
}
1;
有人可以帮我访问变量吗?
编辑:package XYZ
代码中遗漏了一行。
我无法触摸 package XYZ
,因为它是其他人 owned/used,我可以使用它:(
您不希望 our $VAR;
在 THIS
的命名空间中。这创建了对 $THIS::VAR
的词法引用。不是你想要的。
相反,您需要 use
正确:
use XYZ qw($VAR);
但是,XYZ
在这里没有 import
到 运行,因此您需要更新它。有两种方法可以修复 XYZ
来执行此操作 - 一种是导入导入,例如 use Exporter qw(import);
,另一种是导出 Exporter
,例如 use parent qw(Exporter);
。这两个都会使 XYZ->import(...)
正常工作。
一旦 XYZ
use
ing Exporter
正确,那么 use XYZ qw($VAR);
行将导致 perl 隐式加载 XYZ 并调用 XYZ->import(qw($VAR))
,这将将该变量导入您的命名空间。
现在,在回答了您的问题后,我将与其他人一起建议导出变量是一种非常糟糕的代码味道,并且可能不是执行您想要的操作的最佳/最干净的方法。
导出变量容易出问题
为什么不
package XYZ;
use strict;
use warnings;
use Exporter qw(import);
our @EXPORT_OK = qw(get_var);
my $VAR = '...'; # no need for "our" now
sub get_var { return $VAR }
...
1;
然后
package THIS;
use warnings;
use strict;
use XYZ qw(get_var);
my $var = get_var();
...
1;
参见 Exporter。
至于你想做什么,有两个直接的问题
来自 XYZ
的 $VAR
永远不会导入到 THIS
。如果你需要来自其他包的符号,你需要导入它们。† 这些包必须首先使它们可用,所以你也需要将它添加到 @EXPORT_OK
。
与上面一样,但使用 $VAR
而不是 get_var()
package XYZ;
...
use Exporter qw(import);
our @EXPORT_OK = qw($VAR);
our $VAR = '...'; # need be "our" for this
与
package THIS;
...
use XYZ qw($VAR);
print "$VAR\n";
现在$VAR
可以直接使用,包括被写入(除非声明常量);它可以在其他代码的脚下改变它的值,而这些代码可能永远不知道其中的任何一个。
另一种方法是使用 @EXPORT
,然后将这些符号引入到每个显示 use Package;
的程序中。我强烈建议仅在调用者需要明确列出他们想要的内容时才使用 @EXPORT_OK
。这也很好地记录了正在使用的内容。
即使添加了它,THIS
中仍然有一个同名变量,它隐藏(遮罩、阴影)$XYZ::VAR
。所以删除 THIS
中的 our $VAR
。这是全局问题的一个很好的例子。一旦引入它们,我们就必须小心 always 和 everywhere.
但是跨模块共享变量存在更大的问题。
它使代码组件纠缠在一起,代码变得越来越难处理。它违背了明确定义的范围和模块化设计的原则,它支持远距离操作等。Perl 提供了许多用于构建代码的好工具,我们很少需要全局变量和共享变量。它告诉 Exporter
本身 warns against that.
请注意现在 XYZ
中的 my $VAR
在 XYZ
之外不可见; XYZ
之外的任何代码都无法知道或访问它。‡ 当它是 our
时,解释器中的任何代码都可以编写它就像 $XYZ::VAR
,甚至没有导入它;这就是我们不想要的。
当然可能需要或很好地使用导出变量,偶尔可以在模块中找到。不过这是一个例外,要谨慎谨慎地使用。
† 除非通过 our in their package 在词法别名下将它们声明为包全局变量,在这种情况下它们可以在 任何地方使用 作为 $TheirPackageName::varname
.
我在创建 perl Moose 模块时卡住了。
我有一个全局 pm 模块。
package XYZ;
require Exporter;
our @ISA = qw(Exporter); ## EDIT missed this line
our @EXPORT_OK = qw($VAR);
my $VAR1 = 1;
our $VAR = {'XYZ' => $VAR1};
1;
我想在我正在创建的 Moose
模块中获得 $VAR
package THIS;
use Moose;
use YAML::XS;
sub get_all_blocks{
my ($self) = @_;
require $self->get_pkg(); # this returns the full path+name of the above package
# i cannot use use lib+use since the get_pkg starts complaining
our $VAR;
print YAML::XS::Dump($XYZ::VAR); # this works
print YAML::XS::Dump($VAR); # this does not work
# i cannot use the scope resolution since XYZ would keep changing.
}
1;
有人可以帮我访问变量吗?
编辑:package XYZ
代码中遗漏了一行。
我无法触摸 package XYZ
,因为它是其他人 owned/used,我可以使用它:(
您不希望 our $VAR;
在 THIS
的命名空间中。这创建了对 $THIS::VAR
的词法引用。不是你想要的。
相反,您需要 use
正确:
use XYZ qw($VAR);
但是,XYZ
在这里没有 import
到 运行,因此您需要更新它。有两种方法可以修复 XYZ
来执行此操作 - 一种是导入导入,例如 use Exporter qw(import);
,另一种是导出 Exporter
,例如 use parent qw(Exporter);
。这两个都会使 XYZ->import(...)
正常工作。
一旦 XYZ
use
ing Exporter
正确,那么 use XYZ qw($VAR);
行将导致 perl 隐式加载 XYZ 并调用 XYZ->import(qw($VAR))
,这将将该变量导入您的命名空间。
现在,在回答了您的问题后,我将与其他人一起建议导出变量是一种非常糟糕的代码味道,并且可能不是执行您想要的操作的最佳/最干净的方法。
导出变量容易出问题
为什么不
package XYZ;
use strict;
use warnings;
use Exporter qw(import);
our @EXPORT_OK = qw(get_var);
my $VAR = '...'; # no need for "our" now
sub get_var { return $VAR }
...
1;
然后
package THIS;
use warnings;
use strict;
use XYZ qw(get_var);
my $var = get_var();
...
1;
参见 Exporter。
至于你想做什么,有两个直接的问题
-
来自
$VAR
永远不会导入到THIS
。如果你需要来自其他包的符号,你需要导入它们。† 这些包必须首先使它们可用,所以你也需要将它添加到@EXPORT_OK
。 与上面一样,但使用$VAR
而不是get_var()
package XYZ; ... use Exporter qw(import); our @EXPORT_OK = qw($VAR); our $VAR = '...'; # need be "our" for this
与
package THIS; ... use XYZ qw($VAR); print "$VAR\n";
现在
$VAR
可以直接使用,包括被写入(除非声明常量);它可以在其他代码的脚下改变它的值,而这些代码可能永远不知道其中的任何一个。另一种方法是使用
@EXPORT
,然后将这些符号引入到每个显示use Package;
的程序中。我强烈建议仅在调用者需要明确列出他们想要的内容时才使用@EXPORT_OK
。这也很好地记录了正在使用的内容。即使添加了它,
THIS
中仍然有一个同名变量,它隐藏(遮罩、阴影)$XYZ::VAR
。所以删除THIS
中的our $VAR
。这是全局问题的一个很好的例子。一旦引入它们,我们就必须小心 always 和 everywhere.
XYZ
的 但是跨模块共享变量存在更大的问题。
它使代码组件纠缠在一起,代码变得越来越难处理。它违背了明确定义的范围和模块化设计的原则,它支持远距离操作等。Perl 提供了许多用于构建代码的好工具,我们很少需要全局变量和共享变量。它告诉 Exporter
本身 warns against that.
请注意现在 XYZ
中的 my $VAR
在 XYZ
之外不可见; XYZ
之外的任何代码都无法知道或访问它。‡ 当它是 our
时,解释器中的任何代码都可以编写它就像 $XYZ::VAR
,甚至没有导入它;这就是我们不想要的。
当然可能需要或很好地使用导出变量,偶尔可以在模块中找到。不过这是一个例外,要谨慎谨慎地使用。
† 除非通过 our in their package 在词法别名下将它们声明为包全局变量,在这种情况下它们可以在 任何地方使用 作为 $TheirPackageName::varname
.