В чем разница между моим и нашим в Perl? - PullRequest
176 голосов
/ 10 мая 2009

Я знаю, что такое my в Perl. Он определяет переменную, которая существует только в области действия блока, в котором она определена. Что делает our? Чем our отличается от my?

Ответы [ 12 ]

206 голосов
/ 20 мая 2009

Хороший вопрос: чем 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". Область может быть одним, двумя, несколькими пакетами или одним небольшим блоком.

59 голосов
/ 10 мая 2009

Ссылки PerlMonks и PerlDoc от Cartman и Olafur являются отличным справочным материалом. Ниже приведена краткая сводка:

my переменные лексически ограничены в пределах одного блока, определенного {} или в том же файле, если не в {} с. Они недоступны из пакетов / подпрограмм, определенных вне одной лексической области видимости / блока.

our переменные находятся в пределах пакета / файла и доступны из любого кода, который use или require разрешает конфликты имени пакета / файла между пакетами, добавляя соответствующее пространство имен.

Просто для округления, local переменные имеют «динамическую» область видимости, в отличие от my переменных тем, что они также доступны из подпрограмм, вызываемых в том же блоке.

48 голосов
/ 13 июня 2009

Пример:

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";
12 голосов
/ 10 мая 2009

Как справиться со Scoping - хороший обзор правил Perl. Он достаточно стар, чтобы our не обсуждалось в основной части текста. Он указан в конце раздела Примечания .

В статье рассказывается о переменных пакета и динамической области видимости, а также о том, чем они отличаются от лексических переменных и лексической области видимости.

6 голосов
/ 10 мая 2009

my используется для локальных переменных, где as используется для глобальных переменных. Подробнее ... Переменная Scoping в Perl: основы .

5 голосов
/ 07 ноября 2013

Это старый вопрос, но я когда-либо встречал некоторые подводные камни в лексических объявлениях в 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. Помните функцию sort ?

2. лексический или глобальный?

Я был программистом C до того, как начал использовать Perl, поэтому концепция лексических и глобальных переменных кажется мне простой: просто соответствует auto и внешним переменным в 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, что заставит программиста явно объявлять лексическую переменную, чтобы мы не ошиблись из-за некоторых ошибок, принимаемых как должное.

4 голосов
/ 10 мая 2009

perldoc имеет хорошее определение нашего.

В отличие от my, которое одновременно выделяет хранилище для переменной и ассоциирует простое имя с этим хранилищем для использования в текущей области, наши связывают простое имя с переменной пакета в текущем пакете для использования в текущей области. Другими словами, у наших правил те же, что и у my, но не обязательно создавать переменную.

2 голосов
/ 02 декабря 2011

Это только отчасти связано с вопросом, но я только что обнаружил (для меня) неясный бит синтаксиса perl, который вы можете использовать с «нашими» (пакетными) переменными, которые вы не можете использовать с «моим» (локальные) переменные.

#!/usr/bin/perl

our $foo = "BAR";

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

Выход:

BAR
BAZ

Это не сработает, если вы измените «наш» на «мой».

0 голосов
/ 27 января 2016

Давайте подумаем, что такое интерпретатор на самом деле: это кусок кода, который хранит значения в памяти и позволяет командам программы, которые он интерпретирует, получать доступ к этим значениям по их именам, которые указаны внутри этих инструкций. Итак, большая задача интерпретатора состоит в том, чтобы сформировать правила использования имен в этих инструкциях для доступа к значениям, которые хранит интерпретатор.

При обнаружении «my» интерпретатор создает лексическую переменную: именованное значение, к которому интерпретатор может получить доступ только во время выполнения блока и только из этого синтаксического блока. При обнаружении «нашего» интерпретатор создает лексический псевдоним переменной пакета: он связывает имя, которое интерпретатор должен с тех пор обрабатывать как имя лексической переменной, пока блок не будет завершен, со значением пакета. переменная с тем же именем.

В результате вы можете притворяться, что используете лексическую переменную, и обходить правила «строгого использования» при полной квалификации переменных пакета. Поскольку интерпретатор автоматически создает переменные пакета при их первом использовании, побочным эффектом использования «нашего» также может быть то, что интерпретатор также создает переменную пакета. В этом случае создаются две вещи: переменная пакета, к которой интерпретатор может получить доступ отовсюду, при условии, что она правильно обозначена в соответствии с запросом 'use strict' (с добавлением имени его пакета и двух двоеточий), и его лексический псевдоним.

Источники:

0 голосов
/ 05 ноября 2015

Просто попробуйте использовать следующую программу:

#!/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";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...