我正在阅读O'Reilly的Perl Objects, References&Modules,更具体地说是关于模块的部分。它指出,使用use Some::Module
时,您可以指定导入列表。从它的解释来看,使用此列表的唯一好处似乎是为了保持命名空间干净。换句话说,如果您的main
包中有一个子例程some_sub
,并且加载的模块具有同名的子,则您的子例程将被覆盖。但是,如果指定导入列表并从此列表中省略some_sub
,则不会发生此冲突。然后,您仍然可以从模块运行some_sub,方法是像这样声明它:Some::Module::some_sub
.
除了我上面描述的好处之外,还有其他好处吗?我之所以问这个问题,是因为在某些情况下,即使您只对它的某些方法感兴趣,您也会加载具有大量功能的模块。起初,我认为通过指定导入列表,您只加载这些方法,而不会使用您无论如何都不会使用的方法来膨胀内存。但是,从上面的解释来看,情况似乎并非如此。您是否可以通过仅加载模块的某些部分来有选择地节省资源?或者 Perl 是否足够聪明,可以在编译时做到这一点,而不需要程序员的干预?
从使用中看到use Module LIST;
的意思正是
BEGIN { require Module; Module->import( LIST ); }
另一方面,从要求
否则,如果尚未包含库文件,
require
会要求包含该文件。该文件通过do-FILE机制包含在内,[...]
do 'file'
'file'
作为 Perl 脚本执行。因此,通过use
我们加载整个模块。
"导入"sub 意味着它的名称被包的import
函数添加到(或覆盖)调用方的符号表中(通过 typeglob 的CODE
槽,通常为别名)。子的代码不会被复制。现在,import
可以按照作者想要的任何方式编写,但通常use
语句中的导入列表仅控制将哪些符号带入命名空间。在模块中提供import
的首选方法是使用导出器的import
方法。
选择性导入减轻了符号表(也许还有一些相关机制)的负担,但我不知道这样做的实际好处。好处与编程有关,通过减少碰撞的机会。
另一个明显的好处是,它很好地记录了代码中使用的内容。
请注意,"导入列表"只是一个约定。模块的import
功能可以自由地做任何它喜欢的这个列表,你可以看到它(ab)被许多所谓的编译指示模块使用。因此,部分加载不受任何约束use
。例如,模块可以在您导入或不导入它们的任何地方加载繁重的函数存根,并在实际的第一次调用时动态加载繁重的实现。
因此,带有部分导入列表的use
可能会或可能不会实际节省任何资源 - 这完全取决于use
d模块的实际实现。
虽然require
和use
确实加载了整个.pm
文件,但该文件可能只是一个轻量级的存根和加载器,用于位于其他地方的实际代码。还有另一种约定将这些模块称为::Heavy
。
模块也可以以任何他们喜欢的方式自由实现部分加载。以下是模块如何节省资源的一些可能性:
自动加载- (带有免费的自动加载器,自动拆分和自动加载器模块)。
- 使用加载必要子模块的存根。 在
- 首次按名称访问大量数据(即字典或编码映射)时动态加载这些数据。
- 如果您依赖于其他繁重的模块,请在运行时在依赖于它们的函数中动态
require
它们,而不是在开始时use
编译时。
此列表中的所有内容都可以在后台自动工作,通过导入列表公开use
或者以其他完全任意的方式工作/调用。再一次,这完全取决于模块的实现。