gpt4 book ai didi

perl - Perl 包变量什么时候超出范围?

转载 作者:行者123 更新时间:2023-12-05 08:44:50 26 4
gpt4 key购买 nike

在我的主程序中,我需要一个包含包的文件,然后从该包中调用一个子例程:

while($somecondition){
require( 'people.pm' );
my $result = PERSON::stuff($args);
}

PERSON 包有多个子包和一些声明的“我们的”变量:

package PERSON;
our $name;
our ...
sub stuff {
...
}

根据我对其他更面向对象的语言的理解,您需要声明一个新的对象实例,可能使用其自己的构造函数/初始化函数来使用“包”变量。 Perl 似乎不是这种情况。

我处理的是遗留代码所以不想改动太多,只想从main的角度了解包变量($name)是什么时候出现的,什么时候返回内存的程序。

在 while 循环之后调用 PERSON::stuff() 会不会有新的包变量?在包内调用单个函数后,包变量是否一直存在到程序结束?

最佳答案

这个问题混淆了一些概念,所以让我们首先解决似乎是主要问题的问题:如果一个包在某个范围内需要,那么在该范围之外呢?

简而言之,包中的(动态全局)符号可以通过它们的完全限定名称在需要的单元中的任何地方访问。/p>

举个例子吧

use warnings;
use strict;
use feature 'say';

TEST_SCOPE: {
say "In scope, in ", __PACKAGE__;
require TestPack;
#hi(); # "Undefined subroutine &main::hi called..."
TestPack::hi(); # ok
#say $global; # $global ... who??
say $TestPack::global; # ok
say "Leaving scope\n";
};

say "--- in ", __PACKAGE__;
TestPack::hi(); # ok
say $TestPack::global; # ok

文件TestPack.pm:

package TestPack;

use warnings;
use strict;
use feature 'say';

#use Exporter qw(import); # This is normally done to export symbols
#our @EXPORT_OK = qw(hi); # (unless the package is a class)

our $global = 7;

sub hi { say "hi from ", __PACKAGE__ }

1;

人们需要为这些符号使用完全限定的名称,因为它们不是导入的。如果包导出符号,而我们导入一些,那么它们会进入调用包的命名空间,因此在上面的示例中,它们将在 main:: 中可用,因此它们可以解释器中的任何代码都可以通过它们的导出名称访问它们(hi,不需要 TestPack::hi)。无法从该包(使用 myourstate 创建)访问词法变量§

如果我们引入另一个包而不是单纯的 block (名为 TEST_SCOPE),并且 require 我们的 TestPack 在其中,这也有效。

...    
package AnotherPack {
require TestPack;
...
1;
};
...
TestPack::hi(); # ok
...

(那个 package 应该在 BEGIN block 中,这并没有改变这里的要点。)来自 TestPack 的全局符号仍然可以在 main:: 中通过它们的完全限定名称访问。我们与 require 一起导入的导出名称随后可在 此包 中使用,但不能在 main:: 中使用。

对问题的评论

  • 包名 (PERSON) 和它的文件名 (person.pm) 必须一致。例如,命名空间 (==package) Person 在文件 Person.pm

    中定义
  • 这是关于 require 的基础知识-ing package ;它与面向对象的概念无关。 (尽管如此,类 首先是 一个包。参见 perlootutperlobj。)另请参见 Packages in perlmodour .

  • 如果你要使用一个包bless -es,返回的对象(实例)被(分配给)一个lexical多变的。因此,它不存在于范围之外。尽管包本身如上所示是可见的,但在面向对象的工作中,我们不想戳包的内部,而是通过对象使用方法。

    所以是的,要在 require 范围之外使用该包,您还需要在其他范围内实例化一个对象。这仍然会像上面的示例一样工作——我们可以在需要它的范围之外使用包名称来实例化一个对象(试试!),即使我会提出问题这种设计(见下)

  • 这暗示了一个复杂的设计,在运行时(通过 require)将包引入范围内;上下文是什么? (我希望它不是真的在 while 循环中。)


打印出 main 的符号表,%main::(例如使用 Data::Dumper),我们发现

"TestPack::" => *main::TestPack:: 

以及来自 TestPack 命名空间的所有其他符号。


如果一个包导出符号并且我们需要包然后我们可以导入

require Pack::Name;
Pack::Name->import( qw(subname anothername ...) );

§ 请注意,我们的 创建了一个词法,它是包变量的别名, 可访问。

关于perl - Perl 包变量什么时候超出范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75317862/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com