0

我正在创建一个与我的 Python 项目等效的 Perl。

描述:我有一个基本模块“base.py”,我的所有脚本都通过“from base import *”使用该基本模块具有可以在脚本中执行的通用子例程/函数

我对 Perl 的尝试是放在每个脚本中“使用 base.pm”。然而,Perl 中的子程序并没有在本地导入到脚本中,所以每次我想执行子程序时都需要调用“基本”模块。什么是 Perl 等价于 Python 的“from base import *”?

4

3 回答 3

4

一些东西:

  • Local命名空间非常适合用于您的本地模块。Perl 专门Local为此保留。命名空间中永远不会有官方模块Local
  • Perl 不是 Python。Perl 会做一些不同的事情。有时有一个确切的等价物,有时没有。这没有确切的等价物。接近,但不准确。

方法#1:不要导出任何函数

如果您将完整的命名空间作为前缀,则您在模块中定义的所有函数都可用。这是定义和使用模块中的函数的最简单方法,也是最不可能引起问题的方法。很容易看出一个函数的来源,并且使用相同的函数名的两个模块不会有问题。

我有一个名为的模块Local::Base,其中有一个函数。我的程序可以使用此功能,只需将其称为Local::Base::foo

我的程序

use strict;
use warnings;
use feature qw(say);

use Local::Base;

my $foo_string = Local::Base::foo("string");
say "Foo: $foo_string";

本地/Base.pm

package Local::Base;

use strict;
use warnings;

sub foo {
    my $string = shift;

    return qq(I've foo'd "$string"!);
}

1;

方法 #2:使用ExporterPragma 指定要自动导出的内容

Perl 有一个名为Exporter的特殊编译指示,它允许我指定哪些模块将自动导入到我的程序中。

这不像 Python,我可以指定任何已定义的函数。相反,我必须列出我想要导出的那些。这与 Python 的方式相比有一个缺点:在 Python 中,如果我编写一个新函数,它会自动导入,而无需我做任何事情。与 Python 的方式相比,它还有一个很大的优势:在 Python 中,如果我编写一个新函数,它会自动导入,而无论我是否要导入它,我都无需做任何事情。你可以想象如果我写了一个我不想让人们使用的私有函数。在 Python 中,它将自动可用。在 Perl 中,除非我指定它,否则它不会是:

我的程序

use strict;
use warnings;
use feature qw(say);

use Local::Base;

my $foo_string = foo("string");
say "Foo: $foo_string";

本地/Base.pm

package Local::Base;
use strict;
use warnings;

use Exporter 'import';

our @EXPORT = qw(foo);

sub foo {
    my $string = shift;

    return qq(I've foo'd "$string"!);
}

1;

现在,每当我使用 时Local::Base,都会自动导入该foo功能。

请注意,我列出了要在@EXPORT数组中导出的所有函数。our(另请注意,我用 a而不是 a声明了该数组my。这our意味着 the@EXPORT是一个 PACKAGE 变量。)。还要注意qw(...)语法。这是引用词。所有单词都是数组的单独元素。您不使用逗号:

my @array = ("one", "two", "three");
my @array = qw(one two three);

这两者是等价的。你也可以这样看:

my @array = qw/one two three/;

我喜欢括号,但正斜杠往往是标准。

方法#3:导出时要好

不建议您再使用自动导出。较旧的模块File::Copy仍然可以这样做,但较新的模块会让您导入您的东西。这也使用了Exporter pragma,但我指定@EXPORT_OK而不是仅指定@EXPORT.

现在,当我指定要使用Local::Base时,我必须指定要导入程序的函数:

我的程序

use strict;
use warnings;
use feature qw(say);

use Local::Base qw(foo);

my $foo_string = foo("string");
say "Foo: $foo_string";

本地/Base.pm

package Local::Base;
use strict;
use warnings;

use Exporter 'import';

our @EXPORT_OK; = qw(foo);

sub foo {
    my $string = shift;

    return qq(I've foo'd "$string"!);
}

1;

这迫使用户记录他们想要使用的模块中的功能。这样,他们就知道导入函数的来源。它强制执行良好的编程实践。另外,如果您使用多个模块并且它们具有相似的函数名称,您可以确保使用您想要的模块中的一个。(记住,如果你想使用另一个,你仍然可以在函数前指定包名前缀)。

如果我是一名 Python 程序员并且我不关心良好的编程实践怎么办?(等等,结果不太对劲……)你仍然可以(在某种程度上)通过指定正则表达式(毕竟这是 Perl)以 Python 的方式来做:

use Local::Base '/.+/';

这将导出两者中列出@EXPORT@EXPORT_OK与此正则表达式匹配的所有模块。由于这匹配所有内容,因此它将导入您在@EXPORT和中列出的所有内容@EXPORT_OK。它不会导入所有功能。它只会导入@EXPORT@EXPORT_OK数组中的函数。当然,您可以指定任何正则表达式,甚至是 ant 正则表达式。这将导出所有可导出的函数,但名称中的函数除外bar

use Local::Base '!/bar/';

看看Exporter pragma,看看它还有什么其他好处。例如,您可以将函数分组到标签中。这样,用户只需一个标签就可以指定一组特定的功能。请参阅Math::Trig以获得一个很好的示例。

希望这可以帮助。

对不起,答案很长,但我已婚并有孩子。就像,我在新年前夜做其他事情。

于 2013-01-01T01:13:06.650 回答
3

您通常指定要导入的函数,就像名称列表一样:

use List::Util 'max', 'min';

大多数导出内容的模块将遵循以下语义:

use MyBase; # imports default exports (if any)
use MyBase 'baz'; # imports only baz
use MyBase (); # import nothing

在模块内部,调用了一个导入类方法,该方法可以选择要导出的内容,通常有一个默认列表,但如果有一个则使用传递的列表。导出器模块可以帮助您做到这一点:

package MyBase;
use Exporter 'import';
our @EXPORT = ( 'foo', 'bar' );
our @EXPORT_OK = ( 'baz', 'quux' );

还有一个按标签对导出进行分组并允许轻松导入整个组的工具,请参阅导出器文档。变量也可以导出,而不仅仅是 subs。

有了这个背景,最后回答你的问题:

对于使用 Exporter 的模块(并非所有模块都这样做),您可以使用包含在 // 中的正则表达式指定导入:

use List::Util '/./';
于 2012-12-31T22:04:39.577 回答
1

首先base.pm是一个非常糟糕的名字,因为它是一个核心模块。其次,可导出函数必须这样声明(通常),参见Exporter示例。

于 2012-12-31T21:51:22.903 回答