web-dev-qa-db-ja.com

Perlでの私と私たちの違いは何ですか?

Perlでmyが何であるかを知っています。定義されているブロックのスコープ内にのみ存在する変数を定義します。 ourは何をしますか? ourmyとどう違うのですか?

180
Nathan Fellman

CartmanとOlafurからのPerlMonksとPerlDocのリンクは素晴らしいリファレンスです-以下は要約の私のクラックです:

my変数は、{}で定義された単一ブロック内、または{}s内にない場合は同じファイル内で、字句的にスコープされます。同じレキシカルスコープ/ブロックの外側で定義されたパッケージ/サブルーチンからはアクセスできません。

our変数はパッケージ/ファイル内でスコープされ、useまたはrequireであるパッケージ/ファイルからアクセスできます。名前の競合は、適切なネームスペースを先頭に追加することでパッケージ間で解決されます。

簡単に説明すると、local変数のスコープは「動的」です。my変数とは異なり、同じブロック内で呼び出されるサブルーチンからもアクセスできます。

59
bubaker

例:

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";
48
FMc

スコープ付きスコープ は、Perlスコープルールの概要です。テキストの本文でourが説明されていないのは十分に古いです。最後にあるNotesセクションで説明されています。

この記事では、パッケージ変数と動的スコープ、およびそれが字句変数と字句スコープとどのように異なるかについて説明します。

12
daotoad

myはグローバル変数に使用されるローカル変数に使用されます。 Perlの変数スコープ:基本 をさらに読んでください。

6
ismail

それは古い質問ですが、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;を追加することです。これにより、プログラマーが字句変数を明示的に宣言するようになり、当然のように誤解されて混乱することはありません。

5
Xu Ding

perldoc には適切な定義があります。

変数にストレージを割り当て、現在のスコープ内で使用するためにそのストレージに単純な名前を関連付けるmyとは異なり、現在のスコープ内で使用するために、現在のパッケージ内のパッケージ変数に単純な名前を関連付けます。つまり、私たちはmyと同じスコープ規則を持っていますが、必ずしも変数を作成するわけではありません。

4
Ólafur Waage

これは質問に多少関連していますが、「私」(ローカル)では使用できない「私たち」(パッケージ)変数で使用できるPerl構文の(私にとって)不明瞭な部分を発見しました変数。

#!/usr/bin/Perl

our $foo = "BAR";

print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";

出力:

BAR
BAZ

「our」を「my」に変更すると、これは機能しません。

2
Misha Gale
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.
0
Lavi Buchnik

次のプログラムを使用してみてください。

#!/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";
0
Yugdev