Perlでmy
が何であるかを知っています。定義されているブロックのスコープ内にのみ存在する変数を定義します。 our
は何をしますか? our
はmy
とどう違うのですか?
CartmanとOlafurからのPerlMonksとPerlDocのリンクは素晴らしいリファレンスです-以下は要約の私のクラックです:
my
変数は、{}
で定義された単一ブロック内、または{}
s内にない場合は同じファイル内で、字句的にスコープされます。同じレキシカルスコープ/ブロックの外側で定義されたパッケージ/サブルーチンからはアクセスできません。
our
変数はパッケージ/ファイル内でスコープされ、use
またはrequire
であるパッケージ/ファイルからアクセスできます。名前の競合は、適切なネームスペースを先頭に追加することでパッケージ間で解決されます。
簡単に説明すると、local
変数のスコープは「動的」です。my
変数とは異なり、同じブロック内で呼び出されるサブルーチンからもアクセスできます。
例:
use strict;
for (1 .. 2){
# Both variables are lexically scoped to the block.
our ($o); # Belongs to 'main' package.
my ($m); # Does not belong to a package.
# The variables differ with respect to newness.
$o ++;
$m ++;
print __PACKAGE__, " >> o=$o m=$m\n"; # $m is always 1.
# The package has changed, but we still have direct,
# unqualified access to both variables, because the
# lexical scope has not changed.
package Fubb;
print __PACKAGE__, " >> o=$o m=$m\n";
}
# The our() and my() variables differ with respect to privacy.
# We can still access the variable declared with our(), provided
# that we fully qualify its name, but the variable declared
# with my() is unavailable.
print __PACKAGE__, " >> main::o=$main::o\n"; # 2
print __PACKAGE__, " >> main::m=$main::m\n"; # Undefined.
# Attempts to access the variables directly won't compile.
# print __PACKAGE__, " >> o=$o\n";
# print __PACKAGE__, " >> m=$m\n";
# Variables declared with use vars() are like those declared
# with our(): belong to a package; not private; and not new.
# However, their scoping is package-based rather than lexical.
for (1 .. 9){
use vars qw($uv);
$uv ++;
}
# Even though we are outside the lexical scope where the
# use vars() variable was declared, we have direct access
# because the package has not changed.
print __PACKAGE__, " >> uv=$uv\n";
# And we can access it from another package.
package Bubb;
print __PACKAGE__, " >> main::uv=$main::uv\n";
スコープ付きスコープ は、Perlスコープルールの概要です。テキストの本文でour
が説明されていないのは十分に古いです。最後にあるNotesセクションで説明されています。
この記事では、パッケージ変数と動的スコープ、およびそれが字句変数と字句スコープとどのように異なるかについて説明します。
myはグローバル変数に使用されるローカル変数に使用されます。 Perlの変数スコープ:基本 をさらに読んでください。
それは古い質問ですが、Perlの字句宣言に関する落とし穴に出会ったことがありますが、これもこの質問に関連しているので、ここに要約を追加します。
1。定義または宣言?
local $var = 42;
print "var: $var\n";
出力はvar: 42
です。ただし、local $var = 42;
が定義または宣言であるかどうかはわかりません。しかし、これはどうですか:
use strict;
use warnings;
local $var = 42;
print "var: $var\n";
2番目のプログラムはエラーをスローします。
Global symbol "$var" requires explicit package name.
$var
は定義されていません。つまり、local $var;
は単なる宣言です! local
を使用して変数を宣言する前に、以前にグローバル変数として定義されていることを確認してください。
しかし、なぜこれが失敗しないのでしょうか?
use strict;
use warnings;
local $a = 42;
print "var: $a\n";
出力はvar: 42
です。
これは、$a
と$b
がPerlで事前定義されたグローバル変数であるためです。 sort 関数を覚えていますか?
2。レキシカルまたはグローバル?
私はPerlを使い始める前はCプログラマーだったので、字句変数とグローバル変数の概念は簡単に思えます。Cの自動変数と外部変数に対応しています。しかし、小さな違いがあります。
Cでは、外部変数は関数ブロックの外部で定義された変数です。一方、自動変数は関数ブロック内で定義された変数です。このような:
int global;
int main(void) {
int local;
}
Perlでは、物事は微妙です:
sub main {
$var = 42;
}
&main;
print "var: $var\n";
出力はvar: 42
で、$var
は関数ブロックで定義されていてもグローバル変数です!実際、Perlでは、変数はデフォルトでグローバルとして宣言されています。
教訓は、Perlプログラムの先頭に常にuse strict; use warnings;
を追加することです。これにより、プログラマーが字句変数を明示的に宣言するようになり、当然のように誤解されて混乱することはありません。
perldoc には適切な定義があります。
変数にストレージを割り当て、現在のスコープ内で使用するためにそのストレージに単純な名前を関連付けるmyとは異なり、現在のスコープ内で使用するために、現在のパッケージ内のパッケージ変数に単純な名前を関連付けます。つまり、私たちはmyと同じスコープ規則を持っていますが、必ずしも変数を作成するわけではありません。
これは質問に多少関連していますが、「私」(ローカル)では使用できない「私たち」(パッケージ)変数で使用できるPerl構文の(私にとって)不明瞭な部分を発見しました変数。
#!/usr/bin/Perl
our $foo = "BAR";
print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";
出力:
BAR
BAZ
「our」を「my」に変更すると、これは機能しません。
print "package is: " . __PACKAGE__ . "\n";
our $test = 1;
print "trying to print global var from main package: $test\n";
package Changed;
{
my $test = 10;
my $test1 = 11;
print "trying to print local vars from a closed block: $test, $test1\n";
}
&Check_global;
sub Check_global {
print "trying to print global var from a function: $test\n";
}
print "package is: " . __PACKAGE__ . "\n";
print "trying to print global var outside the func and from \"Changed\" package: $test\n";
print "trying to print local var outside the block $test1\n";
これを出力します:
package is: main
trying to print global var from main package: 1
trying to print local vars from a closed block: 10, 11
trying to print global var from a function: 1
package is: Changed
trying to print global var outside the func and from "Changed" package: 1
trying to print local var outside the block
「use strict」を使用すると、スクリプトを実行しようとしたときにこのエラーが発生します。
Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.
次のプログラムを使用してみてください。
#!/usr/local/bin/Perl
use feature ':5.10';
#use warnings;
package a;
{
my $b = 100;
our $a = 10;
print "$a \n";
print "$b \n";
}
package b;
#my $b = 200;
#our $a = 20 ;
print "in package b value of my b $a::b \n";
print "in package b value of our a $a::a \n";