my
Perlには何があるか知っています。変数が定義されているブロックのスコープ内にのみ存在する変数を定義します。何をしour
ますか?
どうour
違うのmy
?
my
Perlには何があるか知っています。変数が定義されているブロックのスコープ内にのみ存在する変数を定義します。何をしour
ますか?
どうour
違うのmy
?
回答:
すばらしい質問:とはどのようにour
違いmy
、何をしour
ますか?
要約すれば:
Perl 5以降で利用可能であり、my
非パッケージ変数を宣言する方法です。
$package_name::variable
。一方、our
変数はパッケージ変数であるため、自動的に次のようになります。
$package_name::variable
。で変数を宣言すると、入力ミスの警告やコンパイル時のエラーが発生することなく、変数our
を事前に宣言して使用できますuse strict
。Perl 5.6以降、use vars
ファイルスコープのみであり、レキシカルスコープのままではない、廃止されたを置き換えましたour
。
たとえば、$x
内部の変数の正式な修飾名package main
は$main::x
です。宣言をour $x
使用すると$x
、スクリプトがuse strict
またはを使用するときに、宣言のスコープ内でペナルティなし(つまり、エラーが発生しない)の裸の変数を使用できますuse strict "vars"
。スコープは、1つ、2つ、またはそれ以上のパッケージ、または1つの小さなブロックです。
local
変数を作成しません。それはに関連していないmy
とour
、すべてで。local
変数の値を一時的にバックアップし、現在の値をクリアします。
our
変数はパッケージ変数ではありません。それらはグローバルスコープではありませんが、レキシカルスコープ変数は変数と同じmy
です。次のプログラムで確認できますpackage Foo; our $x = 123; package Bar; say $x;
。パッケージ変数を「宣言」する場合は、を使用する必要がありますuse vars qw( $x );
。がコンパイルさour $x;
れたパッケージ内の同じ名前の変数にエイリアスされるレキシカルスコープの変数を宣言しますour
。
cartmanとOlafurからのPerlMonksとPerlDocのリンクは、優れたリファレンスです。以下は、私の要約です。
my
変数は{}
、{}
sにない場合、同じファイルによって定義された単一のブロック内または同じファイル内でレキシカルにスコープされます。同じ字句スコープ/ブロックの外部で定義されたパッケージ/サブルーチンからはアクセスできません。
our
変数のスコープはパッケージ/ファイル内にあり、そのパッケージまたはファイルuse
またはコードからアクセスできrequire
ます。名前の競合は、適切な名前空間を付加することによりパッケージ間で解決されます。
まとめると、local
変数は「動的に」スコープさmy
れ、同じブロック内で呼び出されたサブルーチンからもアクセスできるという点で変数とは異なります。
my
変数内の+1 は、{}
sにない場合、同じファイル内でレキシカルスコープ[...] です。」それは私にとって役に立ちました、ありがとう。
例:
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";
my
ローカル変数にour
使用され、グローバル変数に使用されます。
${^Potato}
グローバルです。どこで使用しても同じ変数を参照します。
私はめちゃくちゃになった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で事前に定義されたグローバル変数です。ソート機能を覚えていますか?
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では、すべての変数がデフォルトでグローバルとして宣言されています。
レッスンは、常にuse strict; use warnings;
Perlプログラムの先頭に追加することです。これにより、プログラマーは字句変数を明示的に宣言する必要があり、当然のことと誤解されないようになっています。
perldocのは、私たちの良い定義があります。
変数にストレージを割り当て、現在のスコープ内で使用するために単純な名前をそのストレージに関連付けるmyとは異なり、現在のスコープ内で使用するために単純な名前を現在のパッケージのパッケージ変数に関連付けます。言い換えると、私たちのスコープルールはmyと同じですが、必ずしも変数を作成するわけではありません。
これは質問にいくらか関連しているだけですが、「私」(ローカル)では使用できない「our」(パッケージ)変数で使用できる(私にとって)あいまいなperl構文を発見しました変数。
#!/usr/bin/perl
our $foo = "BAR";
print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";
出力:
BAR
BAZ
これを 'our'を 'my'に変更すると機能しません。
perl -e "my $foo = 'bar'; print $foo; ${foo} = 'baz'; pr int $foo"
出力:barbaz
perl -e "my $foo = 'bar'; print $foo; ${"foo"} = 'baz'; print $foo"
出力:barbaz
perl -e "my $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"
出力:barbar
したがって、私のテストでは同じ罠に陥りました。$ {foo}は$ fooと同じです。角かっこは補間時に役立ちます。$ {"foo"}は、実際にはメインシンボルテーブルである$ main :: {}までのルックアップです。パッケージスコープの変数のみが含まれているためです。
perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"
この文脈では$ {"foo"}が$ {"test :: foo"}と等しくなるので、省略表現はパッケージ依存の動作です。高度なPerlプログラミングブックと同様に、Symbol Tables and Globsにもいくつかの情報があります。以前の間違いでごめんなさい。
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";
#!/usr/bin/perl -l
use strict;
# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'
our $lol = eval {$lol} || 'lol' ;
print $lol;
our
とmy
違いますか?この例はそれをどのように示していますか?
インタプリタが実際に何であるかを考えてみましょう。これはメモリに値を格納し、プログラム内の命令がそれらの値内に指定されている名前でそれらの値にアクセスできるようにするコードの一部です。したがって、インタープリターの大きな仕事は、インタープリターが保管する値にアクセスするために、これらの命令で名前をどのように使用すべきかという規則を形作ることです。
「my」に遭遇すると、インタープリターはレキシカル変数を作成します。インタープリターは、ブロックの実行中にのみ、その構文ブロック内からのみアクセスできる名前付きの値です。「our」に遭遇すると、インタープリターはパッケージ変数の字句エイリアスを作成します。それは、インタープリターがそれ以降、字句変数の名前として処理すると想定される名前を、ブロックが完了するまでパッケージの値にバインドします。同じ名前の変数。
その結果、レキシカル変数を使用しているように見せかけ、パッケージ変数の完全修飾に対する「厳密な使用」のルールを回避できます。インタープリターは最初に使用されるときに自動的にパッケージ変数を作成するため、「our」を使用することの副作用として、インタープリターがパッケージ変数も作成することがあります。この場合、2つのものが作成されます。「use strict」(パッケージの名前と2つのコロンが前に付加されます)によって要求されたとおりにインタープリターが適切に指定されている場合、インタープリターがどこからでもアクセスできるパッケージ変数とその字句エイリアスです。
出典: