Perl에서 '나'와 '우리'의 차이점은 무엇입니까?


188

나는 myPerl에 무엇이 있는지 안다 . 정의 된 블록의 범위에만 존재하는 변수를 정의합니다. 무엇을 our합니까?

our와는 어떻게 다릅니 my까?

답변:


215

좋은 질문 : 어떻게 our다를 my무엇을 않습니다 our합니까?

요약해서 말하자면:

Perl 5부터 사용 가능 my하며 패키지가 아닌 변수를 선언하는 방법은 다음과 같습니다.

  • 은밀한
  • 새로운
  • 비전 역
  • 변수 를의 형식으로 액세스 할 없도록 패키지와 분리 하십시오 $package_name::variable.


반면에 our변수는 패키지 변수이므로 자동으로 다음과 같습니다.

  • 전역 변수
  • 확실히 비공개가 아닙니다
  • 반드시 새로운 것은 아니다
  • 정규화 된 네임 스페이스를 사용하여 패키지 외부 (또는 어휘 범위) 외부에서 액세스 할 수 있습니다 $package_name::variable.


변수 선언 our을 사용하면 use strict오타 경고 나 컴파일 타임 오류없이 변수를 사용하기 위해 변수를 미리 선언 할 수 있습니다. Perl 5.6부터는 use vars파일 범위 만 있고 어휘 범위가 없는 구식을 대체했습니다 our.

예를 들어, 변수 $xinside의 정규화 된 이름 package main$main::x입니다. 선언은 our $x당신이 베어 사용할 수 있습니다 $x선언, 스크립트 사용의 범위에서, (그 결과의 오류없이, 즉) 위약금없이 변수를 use strictuse strict "vars". 범위는 하나 또는 둘 이상의 패키지 또는 하나의 작은 블록 일 수 있습니다.


2
그렇다면 지역과 어떻게 다릅니 까?
Nathan Fellman

17
@Nathan Fellman local은 변수를 만들지 않습니다. 그것은 관련이 없습니다 myour전혀. local변수 값을 임시로 백업하고 현재 값을 지 웁니다.
ikegami

1
our변수는 패키지 변수가 아닙니다. 그것들은 전역 범위가 아니지만 변수와 같은 어휘 범위 my변수입니다. 다음 프로그램에서 볼 수 있습니다 package Foo; our $x = 123; package Bar; say $x;.. 패키지 변수를 "선언"하려면을 사용해야 use vars qw( $x );합니다. 컴파일 된 our $x;패키지에서 동일한 이름의 변수에 별명을 갖는 어휘 범위 변수를 선언합니다 our.
ikegami

60

cartman과 Olafur의 PerlMonks와 PerlDoc 링크는 훌륭한 참고 자료입니다-아래는 요약에서 내 균열입니다.

my변수는 s에 {}있지 않은 경우 동일한 파일에 의해 정의 되거나 동일한 파일 내에 정의 된 단일 블록 내에서 어휘 범위가 지정됩니다 {}. 동일한 어휘 범위 / 블록 외부에 정의 된 패키지 / 서브 루틴에서는 액세스 할 수 없습니다.

our변수는 패키지 / 파일 내에서 범위가 지정 되며 적절한 네임 스페이스를 앞에 추가하여 패키지간에 use또는 require패키지 / 파일 이름 충돌이 해결 되는 모든 코드에서 액세스 할 수 있습니다 .

반올림하기 위해 local변수는 "동적"범위를 가지며 my동일한 블록 내에서 호출되는 서브 루틴에서도 액세스 할 수 있다는 점 에서 변수와 다릅니다 .


" my변수가 {}s에 있지 않으면 같은 파일 내에서 어휘 범위 [...]로 +1 "입니다. 저에게 도움이되었습니다. 감사합니다.
Georg

48

예를 들면 :

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

11

범위 지정에 대처 하는 것은 Perl 범위 지정 규칙에 대한 좋은 개요입니다. our본문에서 다루지 않을 정도로 오래 되었습니다. 끝에 있는 참고 섹션에서 설명합니다.

이 기사에서는 패키지 변수 및 동적 범위와 어휘 변수 및 어휘 범위와의 차이점에 대해 설명합니다.


5

my지역 변수에 our사용되는 반면 전역 변수에 사용됩니다.

Perl의 변수 범위 지정에 대한 추가 정보 : 기본 사항 .


16
현지 및 세계의 단어를주의해서 던지십시오. 적절한 용어는 어휘와 패키지입니다. Perl에서 진정한 전역 변수를 만들 수는 없지만 $ _와 같은 일부 변수가 이미 존재하고 local은 어휘 변수 (my로 만든)가 아닌 지역화 된 값 (로컬로 만든)을 갖는 패키지 변수를 나타냅니다.
Chas. Owens

${^Potato}글로벌입니다. 사용 위치에 관계없이 동일한 변수를 나타냅니다.
MJD

5

나는 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";

두 번째 프로그램에서 오류가 발생합니다.

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 프로그램의 시작 부분에 추가 하는 것입니다. 프로그래머는 어휘 변수를 명시 적으로 선언해야합니다.


[ "[$ a 및 $ b in] 정렬 기억"에 대한 자세한 내용은 here] ( stackoverflow.com/a/26128328/1028230 ). 펄은 결코 놀라지 않았다.
ruffin

4

perldoc을은 우리의 좋은 정의를 가지고있다.

변수에 스토리지를 할당하고 현재 범위 내에서 사용하기 위해 간단한 이름을 해당 스토리지와 연관시키는 my와 달리, 현재 범위 내에서 사용하기 위해 단순 이름을 현재 패키지의 패키지 변수와 연관시킵니다. 다시 말해, 우리와 같은 범위 지정 규칙이 있지만 반드시 변수를 만들 필요는 없습니다.


2

이것은 질문과 다소 관련이 있지만, "my"(로컬)와 함께 사용할 수없는 "our"(패키지) 변수와 함께 사용할 수있는 펄 구문의 모호한 비트를 발견했습니다. 변수.

#!/usr/bin/perl

our $foo = "BAR";

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

산출:

BAR
BAZ

'our'를 'my'로 변경하면 작동하지 않습니다.


1
별로. $ foo $ {foo} $ { 'foo'} $ { "foo"}는 모두 변수 할당 또는 역 참조에 대해 동일하게 작동합니다. 스와핑 우리 를 위해 위의 예제를 않습니다 작동합니다. 아마도 당신이 경험 한 것은 $ foo를 $ main :: foo 또는 $ :: foo와 같은 패키지 변수로 역 참조하려고했는데, 이는 우리로 정의 된 것과 같은 패키지 전역에서만 작동합니다 .
Cosmicnet

방금 v5.20을 사용하여 다시 테스트 한 결과 내 것과 동일한 출력을 제공하지 않습니다 (BAR을 두 번 인쇄 함)
Misha Gale

1
내 테스트 (창에서) : 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 :: {}까지입니다. 패키지 범위 변수 만 포함합니다.
Cosmicnet

1
$ { "main :: foo"}, $ { ":: foo"} 및 $ main :: foo는 $ { "foo"}와 동일합니다. 속기는 패키지 민감한 perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"이 컨텍스트 $ { "foo는"}과 같이 일 현재 $ { "테스트 :: foo는"}와 같습니다. 심벌 테이블과 글로브 에 대한 정보는 Advanced Perl 프로그래밍 서적과 같습니다. 이전 실수로 죄송합니다.
Cosmicnet

0
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 

"엄격한 사용"을 사용하면 스크립트를 실행하는 동안이 오류가 발생합니다.

Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.

어떤 종류의 설명을 제공하십시오. 이와 같은 덤프 코드는 적절한 것으로 간주되지 않습니다.
Scott Solmer

간단히 말하면 : 우리의 이름은 sais라는 이름은 스크립트의 어느 곳에서나 (함수, 블록 등 ...) 변수를 사용하는 변수 편차입니다. 기본적으로 모든 변수는 (선언되지 않은 경우) "main"에 속합니다 스크립트에서 다른 패키지를 삭제 한 후에도 변수를 계속 사용할 수 있습니다. 블록 또는 함수에서 선언 된 경우 "my"변수는 해당 블록 / 함수에서만 사용할 수 있습니다. 경우에 "내"변수가 아니라, 또는 "우리"변수로 함수에 폐쇄 블록에 어디 scriot의 모든 사용할 수 있습니다 블록에 닫히지 않은 선언 만 변경하는 경우 패키지에서 사용할 수 없습니다
Lavi Buchnik

위의 스크립트는 기본적으로 "main"패키지에 있고 스크립트는 "main"패키지에서 "our"변수를 인쇄하고 (블록으로 닫히지 않음) 두 개의 "my"변수를 함수에 선언합니다. 해당 기능에서 인쇄하십시오. 그런 다음 다른 함수에서 "우리"변수를 인쇄하여 함수에서 사용할 수 있음을 보여줍니다. 그런 다음 패키지를 "changed"로 변경하고 ( "main"아님) 더 이상 "our"변수를 다시 인쇄합니다. 그런 다음 함수 외부에서 "my"변수를 인쇄하려고 시도했지만 실패했습니다. 스크립트는 "우리"와 "내"사용법의 차이점을 보여줍니다.
Lavi Buchnik

0

다음 프로그램을 사용하십시오.

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

이것은 나와 우리의 차이점을 설명합니다. 내 변수는 중괄호 밖에서 범위를 벗어나 가비지 수집되지만 변수는 여전히 유효합니다.
Yugdev

-1
#!/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;

이 코드의 의미를 설명 할 수 있습니까? 왜 ourmy의 차이점은 무엇입니까? 이 예는 어떻게 보여줍니까?
Nathan Fellman

-1

인터프리터가 실제로 무엇인지 생각해 보자. 메모리에 값을 저장하고 해석하는 프로그램의 명령이 이름으로 이러한 값에 액세스 할 수 있도록하는 명령이다. 따라서 통역사의 큰 임무는 통역사가 저장하는 값에 액세스하기 위해 해당 지시 사항의 이름을 사용하는 방법에 대한 규칙을 형성하는 것입니다.

"my"가 발생하면 인터프리터는 어휘 변수를 작성합니다. 인터프리터는 블록을 실행하는 동안에 만 해당 구문 블록 내에서만 액세스 할 수있는 명명 된 값입니다. "우리"를 만나면 인터프리터는 패키지 변수의 어휘 별명을 만듭니다. 인터프리터는 그 이후부터 블록이 완료 될 때까지 어휘 변수의 이름으로 처리하기 위해 인터프리터가 이름을 바인드하여 패키지의 값으로 바꿉니다. 같은 이름의 변수.

그 결과 어휘 변수를 사용하는 것처럼 가장하고 패키지 변수의 정규화에 대해 '엄격한 사용'규칙을 무시할 수 있습니다. 인터프리터는 패키지 변수가 처음 사용될 때 자동으로 패키지 변수를 작성하므로 "우리"를 사용하면 부작용으로 인해 패키지 변수도 작성 될 수 있습니다. 이 경우, 두 가지가 생성됩니다 : 패키지 변수, 인터프리터가 액세스 할 수 사방에서, (그 패키지와 두 개의 콜론의 이름 앞에 추가) '엄격한 사용'의 요청에 따라 제대로 지정된 것 제공 사전 적 별명.

출처 :

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.