以类似Python的Perl导入';导入为';
Perl是否有类似python的以类似Python的Perl导入';导入为';,perl,Perl,Perl是否有类似python的导入为 如果模块没有指定包,那么这个黑客小解决方案可以工作: # mod1.pm sub routine{ return "I'm from mod1\n"; } 如果模块具有自己的名称空间,则这不起作用: # ABC.pm package ABC; sub routine{ return "I'm from ABC\n"; } 是否可以导入文件,并将其内容强制放入特定的命名空间?如果要加载DEF.pm并以bar访问它,可以通过typeglob执行此操
导入为
如果模块没有指定包,那么这个黑客小解决方案可以工作:
# mod1.pm
sub routine{ return "I'm from mod1\n"; }
如果模块具有自己的名称空间,则这不起作用:
# ABC.pm
package ABC;
sub routine{ return "I'm from ABC\n"; }
是否可以导入文件,并将其内容强制放入特定的命名空间?如果要加载DEF.pm
并以bar
访问它,可以通过typeglob执行此操作:
这将适用于包中的单个子包,以更改符号表
但我会问你为什么要这么做?你有两个互相冲突的名称空间吗?这是一个让代码更混乱而不是更干净的好方法,所以我一般不认为这是一个好主意
否则-您可以使用代码引用:
my $ref_to_routine = \&DEF::routine;
$ref_to_routine->();
&$ref_to_routine();
您的模块实际上不导出任何内容
ABC.pm
:
package ABC;
use Exporter qw( import );
our @EXPORT = qw( routine );
sub routine { return __PACKAGE__ }
package DEF;
use Exporter qw( import );
our @EXPORT_OK = qw( routine );
sub routine { return __PACKAGE__ }
DEF.pm
:
package ABC;
use Exporter qw( import );
our @EXPORT = qw( routine );
sub routine { return __PACKAGE__ }
package DEF;
use Exporter qw( import );
our @EXPORT_OK = qw( routine );
sub routine { return __PACKAGE__ }
脚本
:
package foo;
use ABC qw( routine );
package bar;
use DEF qw( routine );
package main;
print foo::routine(), "\n"; # ABC
print bar::routine(), "\n"; # DEF
您还可以使用类似以下内容:
use ABC qw( );
use DEF qw( );
BEGIN {
*foo_routine = \&ABC::routine; # Could use foo::routine if you wanted.
*bar_routine = \&DEF::routine;
}
print foo_routine(), "\n"; # ABC
print bar_routine(), "\n"; # DEF
use Module()
和use Module qw()
防止调用模块的import
。这里的模块没有定义任何默认导出,但我想明确说明我导入的内容。根据描述,我假设您既不控制ABC
也不控制foo
因为这两个包中都没有import
sub,所以它们的所有sub都生活在各自的包中。因此,如果加载foo
,ABC
也将被加载,并且代码将可供Perl使用。但是,ABC
中的sub只能通过其完全限定名ABC::routine
访问
事实上,这与LWP::UserAgentrequire
s HTTP::Request时相同。现在,您可以在代码中使用HTTP::Request,而无需使用use HTTP::Request
。您只将use LWP::UserAgent
放在那里,因为它加载了另一个,所以它现在可用
当然,这些不出口东西,所以有点不同,但这基本上就是这里发生的事情
但是,如果不控制至少foo.pm
就没有办法解决这个问题。您不能覆盖package
语句或声明程序的某个部分,其中package
不起任何作用
更进一步说,您可能已经习惯了遗留代码,其中存在需要其他.pl
文件的.pl
文件,并且没有包。现在一个包成了一个问题,因为如果通常没有,也没有导出器,那么东西就会变得奇怪
我经常需要在包中包含带有大量全局变量的遗留代码,以将它们隐藏在我的main
命名空间之外
package DoNotPutGlobalsInMyMain { require 'legacy.pl' };
但是,如果在legacy.pl
中有另一个包的显式定义,这将中断。因此,我的上述声明仍然有效。您需要控制该代码来修复它,或者知道哪个包真正包含要调用的sub
然后您可以使用
或自己要求
该软件包。只要foo.pm
已经加载了它,就不会再加载它(因为Perl在%INC
中记下它已经加载了它)。但是如果他们将它从foo.pm
中删除,它仍然可用。您的维护程序员也了解您的依赖关系。您在这里想要实现什么?这感觉像是XY问题。你能控制ABC.pm
和foo.pm
吗?是的,我不擅长问XY问题。。我喜欢他们帮助我理解东西是如何工作的,即使这不是一个很好的实践来真正使用答案。社区似乎不喜欢他们,所以我想我应该改掉这个习惯。社区已经在很多情况下因为追逐假设性的问题而被烧掉了,这些假设性的问题为非问题提供了糟糕的解决方案。问东西是如何工作的并没有错,但要清楚这就是你正在做的事情——作为一个关于perl的符号表是如何工作的问题,这很好。然而,乱搞符号表通常是一种疯狂的方式,对于一个特定的问题,通常有更好的解决方案。我同意@Sobrique。我也被标题所左右。在Perl中,确实有一种方法可以将某些内容作为其他内容导入,使用。这是我读了标题后首先回答的问题。然而,这个问题要求的完全是另外一件事我想OP还有别的意思。我也这么想,并发布了一个我已经删除的答案。但是如果你检查问题的最后一部分,你会看到包里面有包。这是另外一回事。
package foo;
use ABC qw( routine );
package bar;
use DEF qw( routine );
package main;
print foo::routine(), "\n"; # ABC
print bar::routine(), "\n"; # DEF
use ABC qw( );
use DEF qw( );
BEGIN {
*foo_routine = \&ABC::routine; # Could use foo::routine if you wanted.
*bar_routine = \&DEF::routine;
}
print foo_routine(), "\n"; # ABC
print bar_routine(), "\n"; # DEF
package DoNotPutGlobalsInMyMain { require 'legacy.pl' };