这是命令 perlmod,可以使用我们的多个免费在线工作站之一在 OnWorks 免费托管服务提供商中运行,例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器
程序:
您的姓名
perlmod - Perl 模块(包和符号表)
商品描述
Is Free Introduction 这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 文件 为 后?
还有其他文档可能包含您要查找的信息:
这个文档
Perl 的包、命名空间和一些关于类的信息。
新模式
制作新模块的教程。
样式
制作新模块的最佳实践。
Perl 提供了一种替代命名空间的机制来保护包不被践踏
彼此的变数。 事实上,真的没有全局变量这样的东西
珀尔。 package 语句将编译单元声明为在给定的
命名空间。 包声明的范围是从声明本身到
封闭块、“eval”或文件的结尾,以先到者为准(与
这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 我的() 和 当地的() 运营商)。 不合格的动态标识符将在此
命名空间,除了少数标识符,如果不合格,默认为主
包而不是如下所述的当前包。 一个包语句只影响
动态变量——包括你使用过的那些 当地的() 在--但是 而不去 词汇变量
用...创造 我的(). 通常,它是包含在文件中的第一个声明
“do”、“require”或“use”运算符。 您可以在多个包中切换
地方; 它仅影响编译器在其余部分使用哪个符号表
那个块。 您可以通过前缀来引用其他包中的变量和文件句柄
带有包名和双冒号的标识符:$Package::Variable。 如果包
name 为 null,则假定为“main”包。 也就是说,$::sail 等价于
$main::sail。
旧的包分隔符是单引号,但现在首选双冒号
分隔符,部分是因为它对人类更具可读性,部分是因为它更
可读 emacs的 宏。 它还让 C++ 程序员觉得他们知道发生了什么
on--而不是使用单引号作为分隔符,这是为了让 Ada
程序员觉得他们知道发生了什么。 因为老式的语法是
仍然支持向后兼容,如果您尝试使用像“This is
$owner's house”,您将访问 $owner::s;即包中的 $s 变量
“所有者”,这可能不是您的意思。 使用大括号来消除歧义,如“这是
${owner} 的房子”。
包本身可能包含包分隔符,如在 $OUTER::INNER::var 中。 这个
然而,没有暗示名称查找的顺序。 没有相关的包:
所有符号要么是当前包的本地符号,要么必须完全符合
外包装名倒。 例如,包“OUTER”中没有任何地方可以
$INNER::var 指的是 $OUTER::INNER::var。 “INNER”指的是一个完全独立的全局
包。
仅以字母(或下划线)开头的标识符存储在包的符号中
桌子。 所有其他符号都保存在包“main”中,包括所有标点变量,
像$_。 此外,当不合格时,标识符 STDIN、STDOUT、STDERR、ARGV、
ARGVOUT、ENV、INC 和 SIG 被强制包含在包“main”中,即使用于其他
目的而不是它们的内置目的。 如果您有一个名为“m”、“s”或“y”的包,则
你不能使用标识符的限定形式,因为它会被解释
作为模式匹配、替换或音译。
下划线开头的变量曾经被强制放入包 main,但我们决定这样做
对于包编写者能够使用前导下划线来表示更有用
私有变量和方法名称。 但是,变量和函数以单个命名
“_”,例如 $_ 和“sub _”,仍然被强制放入包“main”中。 另见“
perlvar 中的变量名语法”。
“eval”ed 字符串被编译在包中 评估() 被编译。
(然而,对 $SIG{} 的赋值假定指定的信号处理程序在“main”中
包裹。 如果您希望在一个信号处理程序中有一个信号处理程序
包。)例如,检查 数据库文件 在 Perl 库中。 它最初切换
到“DB”包,以便调试器不会干扰程序中的变量
您正在尝试调试。 然而,在不同的时刻,它会暂时切换回
“main”包在“main”包的上下文中评估各种表达式(或
无论你来自哪里)。 请参阅 perldebug。
特殊符号“__PACKAGE__”包含当前包,但不能(容易)使用
构造变量名。
请参阅 perlsub 以了解与 我的() 和 当地的(),和 perlref 关于
关闭。
图形符号 表
包的符号表恰好存储在该名称的散列中,其中包含两个
冒号附加。 因此,主符号表的名称是 %main::,或简称 %::。
同样,前面提到的嵌套包的符号表被命名为
%外部::内部::。
散列的每个条目中的值就是您在使用 *name 时所指的值
typeglob 表示法。
本地 *main::foo = *main::bar;
例如,您可以使用它来打印出包中的所有变量。 标准
但过时 转储变量 库和 CPAN 模块 Devel::Symdump 就利用了这一点。
直接创建新符号表条目或修改任何条目的结果
还没有 typeglobs 是未定义的,并且可能会在 perl 的发行版之间发生变化。
对 typeglob 赋值执行别名操作,即,
*迪克 = *理查德;
导致变量、子例程、格式以及文件和目录句柄可通过
标识符“richard”也可以通过标识符“dick”访问。 如果你想
仅对特定变量或子程序进行别名,改为分配引用:
*迪克 = \$理查德;
这使 $richard 和 $dick 成为相同的变量,但将 @richard 和 @dick 保留为
单独的阵列。 棘手,嗯?
以下陈述之间有一个细微的区别:
*富 = *酒吧;
*foo = \$bar;
"*foo = *bar" 使 typeglobs 本身成为同义词,而 "*foo = \$bar" 使
两个不同类型团的标量部分引用相同的标量值。 这意味着
以下代码:
$酒吧 = 1;
*foo = \$bar; # 将 $foo 设为 $bar 的别名
{
本地 $bar = 2; # 限制更改为block
打印 $foo; # 打印“1”!
}
将打印 '1',因为 $foo 持有对 原版的 $酒吧。 那个是
被“local()”塞满,当块结束时会恢复。 因为
变量通过typeglob访问,可以使用“*foo = *bar”创建别名
可以本地化。 (但请注意,这意味着您不能拥有单独的 @foo 和
@bar 等)
使所有这一切变得重要的是,Exporter 模块使用全局别名作为
导入/导出机制。 您是否可以正确本地化一个已经被
从模块导出取决于它的导出方式:
@EXPORT = qw($FOO); # 普通形式,不能本地化
@EXPORT = qw(*FOO); # 可以本地化
您可以使用完全限定名称 ($Package::FOO) 来解决第一种情况,其中
你需要一个本地值,或者通过在你的文件中说“*FOO = *Package::FOO”来覆盖它
脚本。
"*x = \$y" 机制可用于传入或返回廉价引用
如果您不想复制整个内容,请使用子程序。 它仅在分配给
动态变量,而不是词法。
%some_hash = (); # 不能是我的()
*some_hash = fn(\%another_hash);
子 fn {
本地 *hashsym = shift;
# 现在正常使用 %hashsym,然后你
# 会影响调用者的 %another_hash
我的 %nhash = (); #做你想做的事
返回 \%nhash;
}
返回时,引用将覆盖由指定的符号表中的哈希槽
*some_hash typeglob。 这是一种廉价地传递引用的有点棘手的方式
当您不想记住显式取消引用变量时。
符号表的另一个用途是制作“常数”标量。
*PI = \3.14159265358979;
现在您无法更改 $PI,这可能是一件好事。 这不一样
作为一个常量子程序,在编译时进行优化。 一个常数
子例程是一个原型,不带参数并返回一个常量表达式。
有关这些的详细信息,请参阅 perlsub。 “使用常量”pragma 是一个方便的简写
这些。
你可以说 *foo{PACKAGE} 和 *foo{NAME} 来找出什么名字并打包 *foo 符号
表条目来自。 这在传递 typeglobs 的子例程中可能很有用
参数:
子标识_typeglob {
我的 $glob = shift;
打印“你给了我”,*{$glob}{PACKAGE},
'::', *{$glob}{NAME}, "\n";
}
识别类型glob *foo;
recognize_typeglob *bar::baz;
这打印
你给了我 main::foo
你给了我酒吧::baz
*foo{THING} 符号也可用于获取对单个元素的引用
*foo. 参见 perlref。
子程序定义(和声明,就此而言)不一定是
位于它们占用的符号表的包中。 你可以定义一个子程序
通过显式限定子例程的名称在其包之外:
包主;
sub Some_package::foo { ... } # Some_package 中定义的 &foo
这只是编译时 typeglob 赋值的简写:
开始 { *Some_package::foo = sub { ... } }
提供美容纤体, 而不去 和写一样:
{
包 Some_package;
子 foo { ... }
}
在前两个版本中,子程序的主体在词法上位于主包中,
而不去 在 Some_package 中。 所以像这样:
包主;
$Some_package::name = "fred";
$main::name = "barney";
子 Some_package::foo {
打印 "in ", __PACKAGE__, ": \$name is '$name'\n";
}
Some_package::foo();
打印:
主要内容:$name 是“barney”
而不是:
在 Some_package 中:$name 是 'fred'
这也对 SUPER:: 限定符的使用有影响(请参阅 perlobj)。
开始, 联检, 查看, INIT 和 END
五个特别命名的代码块在运行的开始和结束时执行
Perl 程序。 它们是“BEGIN”、“UNITCHECK”、“CHECK”、“INIT”和“END”块。
这些代码块可以以“sub”为前缀,以提供子程序的外观
(虽然这不被认为是好的风格)。 应该注意这些代码块
并不真正作为命名子程序存在(尽管它们出现)。 给予的东西
这就是你可以拥有的事实 更多 比 一种 程序中的这些代码块,
他们会得到 所有 在适当的时候执行。 所以你不能执行任何
这些代码块按名称。
一个“BEGIN”代码块尽快执行,也就是在它完全执行完的那一刻
定义,甚至在解析包含文件(或字符串)的其余部分之前。 你可能有
文件中的多个“BEGIN”块(或经过评估的字符串); 他们将按顺序执行
定义。 因为“BEGIN”代码块会立即执行,所以它可以引入定义
来自其他文件的子程序等及时对编译的其余部分可见
和运行时间。 一旦“BEGIN”运行,它立即是未定义的,它使用的任何代码都是
返回到 Perl 的内存池。
一个“END”代码块尽可能晚地执行,也就是在 perl 完成之后
运行程序并在解释器即将退出之前,即使它正在退出
作为一个结果 模具() 功能。 (但如果它通过
“exec”,或者被信号吹出水面——你必须自己捕捉它(如果
你可以))你可能在一个文件中有多个“END”块——它们将反向执行
定义顺序; 即:后进先出(LIFO)。 不执行“END”块
当您使用“-c”开关运行 perl 时,或者编译失败时。
请注意,“END”代码块是 而不去 在字符串“eval()”的末尾执行:如果有“END”
代码块是在字符串“eval()”中创建的,它们将像任何其他
就在解释器被执行之前,以 LIFO 顺序的那个包的“END”代码块
退出。
在“END”代码块中,$? 包含程序要传递给的值
“出口()”。 你可以修改 $? 更改程序的退出值。 小心改变
$? 意外(例如通过“系统”运行某些东西)。
在“END”块内,“${^GLOBAL_PHASE}”的值将是“END”。
“UNITCHECK”、“CHECK”和“INIT”代码块有助于捕捉
主程序的编译阶段和执行阶段。
“UNITCHECK”块在定义它们的单元被编译之后运行。 这
主程序文件和它加载的每个模块都是编译单元,字符串“eval”也是如此,
使用正则表达式中的“(?{ })”构造编译的运行时代码,调用“do FILE”,
“require FILE”,以及命令行上“-e”开关后的代码。
“BEGIN”和“UNITCHECK”块与解释器的阶段没有直接关系。
它们可以在任何阶段创建和执行。
“CHECK”代码块在 初始 Perl 编译阶段结束之前
运行时间以 LIFO 顺序开始。 Perl 编译器套件中使用了“CHECK”代码块
保存程序的编译状态。
在“CHECK”块内,“${^GLOBAL_PHASE}”的值将是“CHECK”。
“INIT”块在 Perl 运行时开始执行之前运行,在“先进先出”中
出”(先进先出)顺序。
在“INIT”块内,“${^GLOBAL_PHASE}”的值将是“INIT”。
由“require”、字符串“do”或字符串“eval”编译的代码中的“CHECK”和“INIT”块
如果它们发生在主编译阶段结束之后,则不会被执行; 这样可以
在 mod_perl 和其他使用这些函数的持久环境中是一个问题
在运行时加载代码。
当您使用 -n 和 -p 切换到 Perl,“BEGIN”和“END”就像它们在
AWK,作为一个退化的情况。 “BEGIN”和“CHECK”块在您使用 -c
切换到仅编译语法检查,尽管您的主代码不是。
- 开始检查 程序使一切都清楚,最终:
#!/usr/bin/perl
# 开始检查
print "10. 普通代码在运行时运行。\n";
END { print "16. 所以这就是故事的结尾。\n" }
INIT { print " 7. INIT 块在运行前运行 FIFO。\n" }
单选{
打印 " 4. 因此在任何 CHECK 块之前。\n"
}
CHECK { print " 6. 所以这是第六行。\n" }
print "11. 当然是按顺序运行的。\n";
BEGIN { print " 1. BEGIN 块在编译期间运行 FIFO。\n" }
END { print "15. 阅读 perlmod 以了解故事的其余部分。\n" }
CHECK { print " 5. CHECK 块在所有编译后运行 LIFO。\n" }
INIT { print " 8. 再次运行,使用 Perl 的 -c 开关。\n" }
print "12. 这是反混淆代码。\n";
END { print "14. END 块在退出时运行 LIFO。\n" }
BEGIN { print " 2. 所以这行第二次出现。\n" }
单选{
print " 3. UNITCHECK 块在编译每个文件后运行 LIFO。\n"
}
INIT { print " 9. 你会马上看到不同之处。\n" }
打印“13。它只是_看起来_应该令人困惑。\n”;
__结尾__
Perl的 精品团课
Perl 中没有特殊的类语法,但如果包提供了类,则它可以充当类
子程序作为方法。 这样的包也可以从
另一个类(包)通过在其全局 @ISA 数组中列出其他包名称
(必须是全局包,而不是词法包)。
有关更多信息,请参阅 perlootut 和 perlobj。
Perl的 模块
一个模块只是一个库文件中的一组相关函数,即一个 Perl 包
与文件同名。 它专门设计为可被其他模块重用或
程式。 它可以通过提供一种机制来将它的一些符号导出到
使用它的任何包的符号表,或者它可以作为类定义和
通过对类及其对象的方法调用,使其语义隐式可用,
无需明确导出任何内容。 或者它可以同时做一点。
例如,要启动一个名为 Some::Module 的传统非 OO 模块,请创建一个文件
被称为 一些/模块.pm 并从这个模板开始:
封装一些::模块; # 假设 Some/Module.pm
用严格;
使用警告;
开始 {
要求出口商;
# 设置用于版本检查的版本
我们的 $VERSION = 1.00;
# 从Exporter继承导出函数和变量
我们的@ISA = qw(Exporter);
# 默认导出的函数和变量
我们的@EXPORT = qw(func1 func2);
# 可以选择导出的函数和变量
我们的@EXPORT_OK = qw($Var1 %Hashit func3);
}
# 导出的包全局变量到这里
我们的 $Var1 = '';
我们的 %Hashit = ();
# 未导出的包全局变量放在这里
# (它们仍然可以作为 $Some::Module::stuff 访问)
我们的@more = ();
我们的 $stuff = '';
# file-private 词法放在这里,在任何使用它们的函数之前
我的 $priv_var = '';
我的 %secret_hash = ();
# 这里有一个文件私有函数作为闭包,
# 可调用为 $priv_func->();
我的 $priv_func = sub {
...
};
# 制作所有功能,无论是否导出;
# 记得在 {} 存根中放一些有趣的东西
子功能1 { ... }
子功能2 { ... }
# 这个没有导出,可以直接调用
# 作为 Some::Module::func3()
子功能3 { ... }
END { ... } # 模块清理代码在这里(全局析构函数)
1; # 不要忘记从文件中返回一个真值
然后继续在函数中声明和使用您的变量,无需任何限定。 看
导出器和 perlmodlib 以获取有关模块创建中的机制和样式问题的详细信息。
通过说 Perl 模块包含在您的程序中
使用模块;
or
使用模块列表;
这完全等同于
开始{需要'Module.pm'; '模块'->导入; }
or
开始{需要'Module.pm'; '模块'->导入(列表); }
作为特例
使用模块();
完全等同于
开始{需要'Module.pm'; }
所有 Perl 模块文件都有扩展名 。下午. “使用”运算符假设这一点,所以你
不必拼出“模块.pm" 在引号中。这也有助于区分新的
旧模块 特等 和 .PH 文件。 模块名称也大写,除非它们是
作为 pragma 使用; pragma 实际上是编译器指令,有时是
称为“语用模块”(如果您是古典主义者,甚至可以称为“语用学”)。
两种说法:
需要 SomeModule;
需要“SomeModule.pm”;
在两个方面彼此不同。 在第一种情况下,模块中的任何双冒号
名称,例如“Some::Module”,被翻译成您系统的目录分隔符,
通常 ”/”。 第二种情况没有,并且必须从字面上指定。 这
另一个区别是在使用的编译器中看到第一个“需要”线索
涉及“SomeModule”的间接对象符号,如“$ob = purge SomeModule”,是
方法调用,而不是函数调用。 (是的,这确实可以有所作为。)
因为“use”语句暗示了一个“BEGIN”块,语义的导入发生在
编译“use”语句后,在编译文件的其余部分之前。 这是
它如何能够作为 pragma 机制发挥作用,以及模块如何能够声明
子例程然后作为列表或一元运算符对于当前的其余部分可见
文件。 如果您使用“require”而不是“use”,这将不起作用。 使用“需要”,您可以
进入这个问题:
需要 Cwd; # 使 Cwd:: 可访问
$这里 = Cwd::getcwd();
使用 Cwd; # 从 Cwd 导入名称::
$这里 = getcwd();
需要 Cwd; # 使 Cwd:: 可访问
$here = getcwd(); #哎呀! 没有 main::getcwd()
一般来说,“use Module()”比“require Module”更推荐,因为它决定了
编译时的模块可用性,而不是在程序执行过程中。 一个
例外情况是,如果两个模块每个都试图“使用”彼此,并且每个模块也称为
来自该其他模块的功能。 在这种情况下,使用“require”很容易。
Perl 包可能嵌套在其他包名中,所以我们可以有包名
包含“::”。 但是如果我们直接使用那个包名作为文件名,它会使得
对于某些系统上笨拙或不可能的文件名。 因此,如果模块的名称是,
说,“Text::Soundex”,那么它的定义其实是在库文件中找到的
文本/Soundex.pm.
Perl 模块总是有一个 。下午 文件,但也可能有动态链接的可执行文件
(通常以 。所以) 或自动加载的子程序定义(通常以 .al)
与模块相关联。 如果是这样,这些对用户来说将是完全透明的
模块。 它的责任是 。下午 文件加载(或安排自动加载)任何
附加功能。 例如,虽然 POSIX 模块碰巧做到了这两点
动态加载和自动加载,用户可以说“使用 POSIX”来获得这一切。
制作 您的 模块 线程安全
Perl 支持一种称为解释器线程(ithreads)的线程。 这些线程可以
显式和隐式使用。
Ithreads 通过克隆数据树来工作,因此不同的线程之间不会共享数据。
线程。 这些线程可以通过使用“线程”模块或通过执行 叉子() on
win32(假的 叉子() 支持)。 当一个线程被克隆时,所有 Perl 数据都被克隆,但是非
Perl 数据无法自动克隆。 Perl 5.8.0 以后支持“CLONE”
特殊子程序。 在“克隆”中,您可以做任何您需要做的事情,例如
如有必要,处理非 Perl 数据的克隆。 “CLONE”将作为一个类被调用一次
定义(或继承它)的每个包的方法。 它将在
新线程的上下文,因此所有修改都在新区域中进行。 当前克隆
除了调用包名称之外没有其他参数调用,但代码不应
假设这将保持不变,因为很可能在未来的额外参数
将传入以提供有关克隆状态的更多信息。
如果您想克隆所有对象,您将需要跟踪每个包。 这是
简单地使用散列和 标量::Util::weaken().
5.8.7 之后的 Perl 支持“CLONE_SKIP”特殊子程序。 像“克隆”一样,
每个包调用一次“CLONE_SKIP”; 然而,它在克隆开始之前被调用,
并且在父线程的上下文中。 如果它返回真值,则没有对象
该类将被克隆; 或者更确切地说,它们将被复制为 unbless, undef 值。 为了
例如:如果在父级中有两个对单个祝福哈希的引用,则在
child 将有两个对单个未定义标量值的引用。 这个
提供了一种使模块线程安全的简单机制; 只需添加“子 CLONE_SKIP { 1
}" 在类的顶部,而 "DESTROY()" 现在每个对象只会被调用一次。
当然,如果子线程需要使用对象,那么一个更复杂的
方法是需要的。
与“CLONE”一样,“CLONE_SKIP”当前被调用时除了调用者之外没有其他参数
包名,虽然这可能会改变。 同样,为了将来的扩展,
返回值应该是单个 0 或 1 值。
使用 onworks.net 服务在线使用 perlmod