我正在学习Perl并尝试理解变量范围。我知道my $name = 'Bob';
会在子中声明一个局部变量,但为什么要在全局范围内使用my
关键字?它只是一个好习惯,所以你可以安全地将代码移动到子?
我看到很多这样做的示例脚本,我想知道为什么。即使使用use strict
,我删除my
时也不会抱怨。我尝试过比较行为与否,我看不出有什么不同。
这里one example执行此操作:
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
my $dbfile = "sample.db";
my $dsn = "dbi:SQLite:dbname=$dbfile";
my $user = "";
my $password = "";
my $dbh = DBI->connect($dsn, $user, $password, {
PrintError => 0,
RaiseError => 1,
AutoCommit => 1,
FetchHashKeyName => 'NAME_lc',
});
# ...
$dbh->disconnect;
当我测试这种行为时,我似乎很不走运。这是我测试过的脚本:
use strict;
my $a = 5;
$b = 6;
sub print_stuff() {
print $a, $b, "\n"; # prints 56
$a = 55;
$b = 66;
}
print_stuff();
print $a, $b, "\n"; # prints 5566
我从这里的一些答案中了解到,$a
和$b
是已经声明的特殊变量,因此编译器不会抱怨。如果我将该脚本中的$b
更改为$c
,则会抱怨。
至于为什么在全局范围内使用my $foo
,似乎文件范围可能实际上不是全局范围。
答案 0 :(得分:3)
添加my
是关于Perl发生过的最好的事情,它解决的问题是错别字。
假设你有一个变量$variable
。您可以对此变量进行一些分配和比较。
$variable = 5;
# intervening assignments and calculations...
if ( $varable + 20 > 25 ) # don't use magic numbers in real code
{
# do one thing
}
else
{
# do something else
}
如果您不use strict;
并要求使用my
声明变量,您是否看到上述代码中的细微错误? # do one thing
案例永远不会发生。我在必须维护的生产代码中遇到过这几次。
答案 1 :(得分:2)
这只是一种很好的做法。作为个人规则,我尝试将变量保持在尽可能小的范围内。如果一行代码无法看到变量,那么它就不会以意想不到的方式搞乱它。
我很惊讶您发现该脚本在use strict
下没有my
的情况下工作。通常不允许这样做:
$ perl -E 'use strict; $db = "foo"; say $db'
Global symbol "$db" requires explicit package name at -e line 1.
Global symbol "$db" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.
$ perl -E 'use strict; my $db = "foo"; say $db'
foo
变量$a
和$b
可免除:
$ perl -E 'use strict; $b = "foo"; say $b'
foo
但我不知道如何让您发布的代码使用严格且缺少my
。
答案 2 :(得分:2)
几点:
strict
要求所有变量都使用my
(或state
)声明或安装到包中 - 使用our
语句声明或use vars
pragma(古老),或在编译时插入符号表。
他们是该文件的变量。对于使用该文件期间所需的任何模块,它们仍然无关紧要且无用。
它们可以跨包使用(虽然这是一个不太好的理由。)
词汇变量没有任何唯一替代方法的魔力。在更改范围时,不能“推”和“弹出”词法变量,就像使用任何包变量一样。没有魔法意味着更快更平稳的处理。
懒惰。声明my
没有括号,而不是通过特定的包围来集中范围,这更容易。
{ my $visible_in_this_scope_only;
...
sub bananas {
...
my $bananas = $visible_in_this_scope_only + 3;
...
}
} # End $visible_in_this_scope_only
(注意语法:在我的代码中,我从不使用裸支撑。它总是会告诉你,在标准循环之前或之后,即使它是“显而易见的”。
答案 3 :(得分:1)
sub
控制/限制定义其操作的大括号{}
之间的变量范围。当然,许多变量存在于特定函数之外,并使用词汇my
来表示"全局"变量可以让你更好地控制"动态"他们的行为在你的申请中。 Private Variables via my()
perlsub
的perlodoc
部分详细讨论了这样做的原因。
我要从elsewhere引用自己,这不是最好的事情,但这里有:
经典 perlmonks 节点 - Variable Scoping in Perl: the basics - 经常出现 咨询参考: - )
正如我在评论中所指出的,布鲁斯格雷在YAPC :: NA 2012的演讲 - The why of my()是一个很好的故事,关于一位非常专业的perl程序员如何围绕perl和命名空间。
我听说过人们将my
解释为Perl等同于Javascript' var
- 它实际上是必要的,但Perl是{{1}如果你坚持或努力去做,事情会在没有它的情况下发挥作用。
ps:实际上使用Javascript,我猜函数 用于控制"范围"与您在perl
中使用my
的描述类似的方式。