我对Perl中的local/our
作用域没有什么疑问。我读了很多文档,但我仍然感到困惑。以下是困惑之处
1.什么是local
作用域?
我读到的是-〉local复制全局变量的值,更改该值,用户将使用它,在块之外,它将保留全局值
混乱-〉my
做了同样的事情。我看到的唯一好处是一些变量,如$package::var
,不能用我的作用域声明,但可以用局部作用域声明。
1.什么是“全局”变量?
我读到的是-〉它的作用域在包内,基本上我们把全局变量放在@EXPORT
数组中,然后使用它,或者把它附加到命名空间中,以便在其他包中使用。
我怀疑-〉如果我们只在main中声明my
作用域的变量,那么我们就可以在整个包中访问该变量。是这样吗?有没有可能在@EXPORT
数组中添加my
作用域的变量,然后在其他包中使用它?
我认为全局变量是用our
关键字声明的。有没有其他的方法可以这样做?
这个问题可能看起来重复,但我很困惑。
4条答案
按热度按时间bzzcjhmw1#
就作用域而言,Perl中有三种类型的变量。
$Foo::x
),并且它们可以由共享变量包的任何代码在没有限定的情况下使用。@ARGV
和STDOUT
。例如,$x
在程序包Foo
中表示$Foo::x
,在程序包Bar
中表示$Bar::x
(假设作用域中没有名为$x
的词法变量),但$_
始终引用$::_
。当不再引用变量时,变量将被销毁。
以下是创建变量的几种方法。
my
和state
创建词法变量。our
创建一个词法变量,该变量的别名与当前包中的变量同名。换句话说,our $x;
等效于包Foo
中的my \$x = \$Foo::x;
。local
不会创建任何变量,它只是备份一个变量,直到当前词法作用域被破坏为止,它会从此时的备份值中恢复。my
执行相同的操作。local
并不改变变量的作用域。虽然词法变量只在词法作用域中可见,但本地化包变量在整个解释器中仍然可见。local
还有什么local
主要用于近似my
的功能,以用于无法以其他方式以词法方式声明的变量。从Python 5.6开始,只有标点符号变量不能用词法声明。
什么是“全局”变量?
全局变量是可以全局看到的变量。
所有包变量都可以被解释器中的任何代码看到,因此它们都是全局变量。
要从其他软件包中查看它们,您需要限定它们。
$x
和$Foo::x
是同一个变量吗?对某些人来说,全局变量指的是你可以使用的包变量的集合。这意味着
package
改变了全局变量的集合。由于package
指令通常是在文件的基础上使用的,这意味着文件级的词法也是有效的全局定义。有时候它们确实被称为全局变量。但是如果
package
改变了全局变量的集合,那么它们就不是真正的全局变量了,对吗?有些人也是这样想的,他们只认为标点变量(例如$_
)和少数可以在任何地方非限定使用的命名变量(*::STDOUT
)是全局变量。简而言之,这是一个相当无用的术语。
有没有可能在@EXPORT数组中添加我的作用域变量,并在其他包中使用它?
不可以。
@EXPORT
是由Exporter使用的。Exporter除了包符号之外什么都找不到(因为文件是在fresh lexical scope中编译的),所以@EXPORT
必须只包含包符号。rlcwz9us2#
有两种类型的变量:词法作用域变量和全局作用域变量。
在Perl版本5之前,只有全局作用域。这些变量是包变量。如果使用包前缀,这些变量在程序中的任何地方都可用。
关键字
local
的引入是为了提供一种在有限的作用域(例如子例程)内改变这些包全局变量的值的方法。当使用local
语句进入作用域时,它会将旧值保存在堆栈中,而在退出时,它会恢复旧值。这些仍然是包全局变量。这意味着它们仍然在任何地方都可用。如果你在一个带有local
变量的作用域中,并且你调用了一个子例程,那么这个变量在那个子例程中仍然是可见的。my
关键字是在版本5中引入的,它提供了词法作用域变量。这些变量只存在于声明它们的作用域中。这意味着如果你调用一个子例程,my
变量是不可见的。一旦退出一个作用域,my
变量就消失了。如果可能的话,你应该更喜欢使用my
变量。因为您不希望您的变量在您调用的子程序中可见。您不能在@EXPORT
列表中使用这些类型的变量,因为这些变量在其作用域之外不可见。最后,
our
关键字是两者的结合,因为它提供了一个包全局变量,但该变量是词法作用域的。这意味着它在程序的任何地方都可用,但在封闭块的末尾,您不能再引用该变量。vdgimpew3#
下面是我对变量作用域的发现:
如果在块内部使用,
my
声明是非常清楚和直接的。如果在任何块外部的main中使用,它们会有一点不同,这意味着在块外部声明的my
变量即使在从同一文件中的任何位置调用的函数内部也是可见的,只要这些函数是在同一文件中定义的。如果在块内部声明,尽管,即使从同一个块中调用,它们对函数也是不可见的。所有my
变量似乎都位于堆栈中。并且:不能使用local
对它们进行本地化。our
变量存在于堆中。即使你有一个同名的my
变量,我们的变量仍然可以通过${'var'}
访问,它在符号表中查找一个同名的变量并取消引用它。另一方面,my
变量没有符号表条目。在我看来,
local
变量就像是以前Perl版本的遗物。它们只是块作用域的全局(our
)变量的重新赋值,并在块终止后恢复它们以前的值。我看不出使用它们有什么真实的意义。我下面的小程序展示了这一切,它展示了除了众所周知的defined()测试之外,如何严重地缺少declared()测试来识别未声明的变量。
wxclj1h54#
示例1:
示例2:
范例1会打印
20
,因为mess_with_foo()
无法看见my $foo
。它无法变更它。my $foo
只能在myfunc()
的范围内看见。范例2会打印
0
,因为mess_with_foo()
可以看见my $foo
并加以变更。local $foo
可以在其myfunc()
的范围AND中看见,而且可以在从其myfunc()
的范围内呼叫的任何函式范围中看见。这是唯一的区别。
my $foo
和local $foo
都不会出现在它们的myfunc()
范围之外。