问题的背景:
在Perl中,可以通过操作符my(词法作用域)和local(动态临时重定义)来限制变量的作用域。local广泛用于重定义全局变量和特殊描述符(如$_,$/,$@,%ENV)。
问题:
主要问题是动态作用域和词法作用域之间的混淆。local并不创建新的变量,而是临时替换全局(或包)变量的值,直到代码块执行完。这在重定义诸如$/(行分隔符)、$_(默认变量)、$^W(警告标志)、%ENV、STDIN/STDOUT等变量时尤其重要。
解决方案:
代码示例:
our $Global = "Hello!"; sub change1 { my $Global = "Bye!"; print "$Global "; } sub change2 { local $Global = "Bye!"; print "$Global "; } print "$Global "; # Hello! change1(); # Bye! print "$Global "; # Hello! change2(); # Bye! print "$Global "; # Hello!
关键特点:
local可以用在通过my声明的词法变量上吗?
不行,local只作用于package全局变量。在my对象上是无效的。
如果对特殊描述符例如STDIN应用local,结果会怎样?
可以通过local临时重定义STDIN/STDOUT/stdin,例如,在子程序中替换输入/输出流而不影响全局。在退出块后,句柄会恢复原状。
在递归函数调用中,local和my有什么关键区别?
local提供值的“压入/弹出”栈——每次调用临时重新定义包的值,而嵌套调用获得这个被重定义的值。my则提供一个在块中唯一的词法值,不会向内继承。
在测试中使用local替换%ENV,退出块后在其他线程中意外的副作用,因为代码是多线程的,local使用不当。
优点:
缺点:
仅在调用需要的块期间替换特殊变量($/,$@,$SIG),之后更改会被正确回滚。
优点:
缺点: