包与模块 #
一、包(Package) #
1.1 什么是包 #
包是Perl的命名空间机制,用于组织代码和避免命名冲突。
perl
package MyPackage;
sub greet {
print "Hello from MyPackage!\n";
}
1;
1.2 包切换 #
perl
package main;
$main::var = "main variable";
print $main::var;
package Other;
$Other::var = "other variable";
print $Other::var;
package main;
print $main::var;
1.3 包变量 #
使用 our 声明包变量:
perl
package Counter;
our $count = 0;
sub increment {
$count++;
return $count;
}
1;
1.4 完全限定名 #
perl
package main;
$MyPackage::variable = "value";
MyPackage::greet();
二、模块(Module) #
2.1 创建模块 #
创建文件 MyModule.pm:
perl
package MyModule;
use strict;
use warnings;
our $VERSION = '1.00';
sub new_function {
my ($arg) = @_;
print "Argument: $arg\n";
}
1;
2.2 使用模块 #
perl
use MyModule;
MyModule::new_function("test");
2.3 导出函数 #
使用 Exporter 导出函数:
perl
package MyModule;
use strict;
use warnings;
use Exporter 'import';
our @EXPORT_OK = qw(greet add);
our @EXPORT = qw(greet);
sub greet {
print "Hello!\n";
}
sub add {
my ($a, $b) = @_;
return $a + $b;
}
1;
使用导出的函数:
perl
use MyModule qw(greet add);
greet();
print add(3, 5);
2.4 导入标签 #
perl
package MyModule;
use strict;
use warnings;
use Exporter 'import';
our %EXPORT_TAGS = (
all => [qw(greet add subtract)],
math => [qw(add subtract)],
);
our @EXPORT_OK = (@{$EXPORT_TAGS{all}});
sub greet { print "Hello!\n"; }
sub add { return $_[0] + $_[1]; }
sub subtract { return $_[0] - $_[1]; }
1;
使用标签导入:
perl
use MyModule ':all';
use MyModule ':math';
三、use和require #
3.1 use #
use 在编译时加载模块:
perl
use strict;
use warnings;
use MyModule qw(func1 func2);
3.2 require #
require 在运行时加载模块:
perl
require MyModule;
MyModule::greet();
3.3 区别 #
| 特性 | use | require |
|---|---|---|
| 加载时机 | 编译时 | 运行时 |
| 自动导入 | 是 | 否 |
| 错误处理 | 编译错误 | 运行错误 |
3.4 条件加载 #
perl
if ($need_module) {
require MyModule;
MyModule->import(qw(func));
}
四、模块搜索路径 #
4.1 @INC #
@INC 存储模块搜索路径:
perl
print "$_\n" foreach @INC;
4.2 添加搜索路径 #
perl
use lib '/path/to/modules';
use MyModule;
或:
perl
BEGIN {
unshift @INC, '/path/to/modules';
}
4.3 相对路径 #
perl
use FindBin;
use lib "$FindBin::Bin/lib";
use MyModule;
五、BEGIN和END #
5.1 BEGIN块 #
BEGIN 在编译时执行:
perl
BEGIN {
print "This runs at compile time\n";
}
5.2 END块 #
END 在程序结束时执行:
perl
END {
print "This runs at program end\n";
}
5.3 执行顺序 #
perl
print "Main code\n";
BEGIN { print "BEGIN 1\n"; }
BEGIN { print "BEGIN 2\n"; }
END { print "END 1\n"; }
END { print "END 2\n"; }
输出:
text
BEGIN 1
BEGIN 2
Main code
END 2
END 1
六、模块示例 #
6.1 配置模块 #
perl
package Config;
use strict;
use warnings;
use Exporter 'import';
our @EXPORT_OK = qw(get_config set_config);
my %config = (
host => 'localhost',
port => 3306,
);
sub get_config {
my $key = shift;
return $key ? $config{$key} : %config;
}
sub set_config {
my %args = @_;
%config = (%config, %args);
}
1;
6.2 工具模块 #
perl
package Utils;
use strict;
use warnings;
use Exporter 'import';
our @EXPORT_OK = qw(trim capitalize);
sub trim {
my $str = shift;
$str =~ s/^\s+|\s+$//g;
return $str;
}
sub capitalize {
my $str = shift;
return ucfirst(lc($str));
}
1;
七、实践练习 #
练习1:创建数学模块 #
perl
package MathUtils;
use strict;
use warnings;
use Exporter 'import';
our @EXPORT_OK = qw(factorial fibonacci is_prime);
sub factorial {
my $n = shift;
return 1 if $n <= 1;
return $n * factorial($n - 1);
}
sub fibonacci {
my $n = shift;
return $n if $n <= 1;
return fibonacci($n - 1) + fibonacci($n - 2);
}
sub is_prime {
my $n = shift;
return 0 if $n < 2;
for my $i (2..int(sqrt($n))) {
return 0 if $n % $i == 0;
}
return 1;
}
1;
使用:
perl
#!/usr/bin/perl
use strict;
use warnings;
use MathUtils qw(factorial fibonacci is_prime);
print "5! = " . factorial(5) . "\n";
print "Fib(10) = " . fibonacci(10) . "\n";
print "Is 17 prime? " . (is_prime(17) ? "Yes" : "No") . "\n";
练习2:创建日志模块 #
perl
package Logger;
use strict;
use warnings;
use Exporter 'import';
our @EXPORT_OK = qw(log_info log_error log_debug);
my $LOG_LEVEL = 'INFO';
sub set_level {
$LOG_LEVEL = shift;
}
sub log_info {
my $msg = shift;
print "[INFO] $msg\n";
}
sub log_error {
my $msg = shift;
print "[ERROR] $msg\n";
}
sub log_debug {
return unless $LOG_LEVEL eq 'DEBUG';
my $msg = shift;
print "[DEBUG] $msg\n";
}
1;
八、总结 #
本章学习了:
- 包的概念和使用
- 模块的创建和使用
- use和require的区别
- Exporter导出函数
- BEGIN和END块
下一章将学习面向对象编程。
最后更新:2026-03-27