В чем разница между моим и местным в Perl?

56

Я вижу, что оба они используются в этом script Я пытаюсь отладить, и литература просто не ясна. Может кто-то демистифицировать это для меня?

Теги:
scoping

14 ответов

31
Лучший ответ

Динамическое масштабирование. Это опрятная концепция. Многие люди не используют его или не понимают.

В основном думать о my как о создании и привязке переменной к одному блоку {}, A.K.A. сфера.

my $foo if (true); # $foo lives and dies within the if statement.

Итак, переменная my - это то, к чему вы привыкли. тогда как при динамическом охвате $var можно объявить где угодно и использовать где угодно. Таким образом, при local вы в основном приостанавливаете использование этой глобальной переменной и используете для этого "локальное значение". Таким образом, local создает временную область для временной переменной.

$var = 4;
print $var, "\n";
&hello;
print $var, "\n";

# subroutines
sub hello {
     local $var = 10;
     print $var, "\n";
     &gogo; # calling subroutine gogo
     print $var, "\n";
}
sub gogo {
     $var ++;
}

Это должно печатать:

4
10
11
4
  • 0
    Вы не вызывали подпрограммы.
  • 7
    Не объявляйте условно лексические переменные: он имеет неопределенное поведение.
45

Короткий ответ: my помещает переменную как private в лексической области, а local помещает переменную как конфиденциальную в динамической области.

Легче понять my, поскольку это создает локальную переменную в обычном смысле. Существует новая переменная, созданная и доступная только внутри закрывающего лексического блока, который обычно помечен фигурными фигурными скобками. Существуют некоторые исключения из правила фигурной фигуры, например:

foreach my $x (@foo) { print "$x\n"; }

Но это просто Perl делает то, что вы имеете в виду. Обычно у вас есть что-то вроде этого:

sub Foo {
   my $x = shift;

   print "$x\n";
}

В этом случае $x является закрытым для подпрограммы, и область видимости заключена в фигурные скобки. Следует отметить, что это отличие от local заключается в том, что область действия переменной my определена в отношении вашего кода, поскольку она записана в файле. Это явление компиляции.

Чтобы понять local, вам нужно подумать о терминальном стеке вашей программы, когда она запущена. Когда переменная local, она переопределяется с той точки, в которой оператор local выполняется для всего ниже, чем в стеке, пока вы не вернете резервную копию стека вызывающему блоку, содержащему local.

Вначале это может сбивать с толку, поэтому рассмотрим следующий пример.

sub foo { print "$x\n"; }
sub bar { local $x; $x = 2; foo(); }

$x = 1;
foo(); # prints '1'
bar(); # prints '2' because $x was localed in bar
foo(); # prints '1' again because local from foo is no longer in effect

Когда foo вызывается в первый раз, он видит глобальное значение $x, которое равно 1. Когда вызывается bar и local $x, это переопределяет глобальный $x в стеке. Теперь, когда foo вызывается из bar, он видит новое значение 2 для $x. Пока что это не очень особенное, потому что одно и то же произошло бы без вызова local. Магия заключается в том, что когда bar возвращается, мы выходим из динамической области, созданной local $x, а предыдущий глобальный $x возвращается в область видимости. Итак, для окончательного вызова foo, $x равно 1.

Вы почти всегда хотите использовать my, так как это дает вам локальную переменную, которую вы ищете. Когда-то в синей луне local действительно удобнее делать классные вещи.

16

Я не могу поверить, что никто не связывал с Джеймсом Домином исчерпывающие трактаты по этому вопросу:

  • 3
    Предупреждение: обе эти статьи довольно старые, а вторая (по собственному предупреждению автора) устарела. Он демонстрирует методы локализации файловых дескрипторов, которые были заменены лексическими файловыми дескрипторами в современных версиях Perl.
  • 0
    Как в Клинтоне был Президентом (США), когда был написан первый
16

Цитата из Изучение Perl:

Но местное имя называется или, по крайней мере, вводит в заблуждение. Наш друг Чип Зальценберг говорит, что если он когда-нибудь получит шанс вернуться в машину времени до 1986 года и даст Ларри один совет, он скажет Ларри позвонить местному по имени "сохранить". [14] Это потому, что локальный на самом деле сохранит заданное значение глобальной переменной, поэтому он будет автоматически автоматически восстановлен для глобальной переменной. (Это право: эти так называемые "локальные" переменные на самом деле являются глобальными!) Этот механизм сохранения и восстановления является тем же, который мы уже видели дважды, в контрольной переменной цикла foreach и в @_ массив параметров подпрограммы.

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

my $file_content;
{
    local $/;
    open IN, "foo.txt";
    $file_content = <IN>;
} 

Вызов local $/ устанавливает разделитель входных записей (значение, которое Perl перестает читать строку) at) до пустого значения, заставляя оператора космического корабля читать весь файл, поэтому он никогда не попадает в разделитель входных данных.

8

http://perldoc.perl.org/perlsub.html#Private-Variables-via-my()

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

http://perldoc.perl.org/perlsub.html#Temporary-Values-via-local()

Локальная изменяет перечисленные переменные быть "локальным" к охватывающему блоку, eval или сделать ФАЙЛ - и любой подпрограмма, вызванная изнутри блок. Местный просто дает временные значения для глобальных (это означает пакет) переменные. Он не создает локальный переменная. Это называется динамическим обзорное. Лексическое определение my, который больше похож на C auto деклараций.

Я не думаю, что это совсем неясно, кроме как сказать, что "локальным для закрывающего блока" означает, что исходное значение восстанавливается при выходе из блока.

7

Хорошо Google действительно работает для вас на этом: http://www.perlmonks.org/?node_id=94007

Из ссылки:

Краткое резюме: 'my' создает новый переменная, "локальная" временно изменяет значение переменной.

т.е. "локальный" временно изменяет значение переменной, но только в пределах объема, в котором он существует.

Как правило, используйте мой, он быстрее и не делает ничего странного.

  • 0
    Хотя это может быть правдой, это в основном побочный эффект того факта, что «локальные» предназначены для того, чтобы быть видимыми в стеке вызовов, а «мои» - нет. И хотя переопределение значения global может быть основной причиной использования «local», нет никаких причин, по которым вы не можете использовать «local» для определения новой переменной.
  • 0
    local на самом деле не определяет новую переменную. Например, попробуйте использовать local, чтобы определить переменную, когда включен явный параметр. Вам нужно использовать «наш» или «мой» для определения новой глобальной или локальной переменной. «local» правильно используется, чтобы дать переменной новое значение
Показать ещё 1 комментарий
6

От man perlsub:

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

Таким образом, упрощение, my делает вашу переменную видимой только там, где она была объявлена. local делает его видимым и в стеке вызовов. Обычно вы хотите использовать my вместо local.

3

local - более старый метод локализации, начиная с того времени, когда Perl имел только динамическое масштабирование. Лексическая область обзора гораздо более естественна для программиста и намного безопаснее во многих ситуациях. мои переменные относятся к области (блоку, пакету или файлу), в котором они объявлены.

локальные переменные вместо этого фактически принадлежат глобальному пространству имен. Если вы ссылаетесь на переменную $x с локальной, вы на самом деле ссылаетесь на $main:: x, которая является глобальной переменной. Вопреки тому, что подразумевается в названии, все локальные значения нажимают новое значение на стек значений $main:: x до конца этого блока, после чего старое значение будет восстановлено. Это полезная функция сама по себе, но это не очень хороший способ иметь локальные переменные по целому ряду причин (подумайте, что происходит, когда у вас есть потоки!) И подумайте, что происходит, когда вы вызываете рутину, которая действительно хочет использовать глобальную вы локализовались!). Тем не менее, это был единственный способ иметь переменные, которые выглядели как локальные переменные в плохие старые дни до Perl 5. Мы все еще придерживаемся этого.

3

Ваше замешательство понятно. Лексическое определение области зрения довольно легко понять, но динамическое исследование - необычная концепция. Ситуация усугубляется тем, что имена my и local являются несколько неточными (или, по крайней мере, неинтуитивными) по историческим причинам.

my объявляет лексическую переменную - ту, которая видна с точки объявления до конца закрывающего блока (или файла). Он полностью не зависит от других переменных с таким же именем в остальной части программы. Он закрыт для этого блока.

local, с другой стороны, объявляет временное изменение значения глобальной переменной. Изменение заканчивается в конце охватывающей области, но переменная - глобальная - видна в любом месте программы.

Как правило, используйте my для объявления ваших собственных переменных и local для управления воздействием изменений на встроенные переменные Perl.

Более подробное описание см. в статье Марка Джейсона Доминиса "Скоринг с показом" .

2

Посмотрите на следующий код и его вывод, чтобы понять разницу.

our $name = "Abhishek";

sub sub1
{
    print "\nName = $name\n";
    local $name = "Abhijeet";

    &sub2;
    &sub3;
}

sub sub2
{
    print "\nName = $name\n";
}

sub sub3
{
    my $name = "Abhinav";
    print "\nName = $name\n";
}


&sub1;

Выход:

Name = Abhishek

Name = Abhijeet

Name = Abhinav
2

Мои переменные видны только в текущем блоке кода. "Местные" переменные также видны там, где раньше они были видны. Например, если вы скажете "my $x;" и вызывать подфункцию, она не может видеть эту переменную $x. Но если вы скажете "local $/;" (чтобы исключить значение разделителя записей), вы изменяете способ работы с файлами в любых функциях, которые вы вызываете.

На практике вы почти всегда хотите "мой", а не "локальный".

0

Я думаю, что самый простой способ запомнить это так. MY создает новую переменную. LOCAL временно изменяет значение существующей переменной.

0
&s;

sub s()
{
    local $s="5";
    &b;
    print $s;
}

sub b()
{
    $s++;
}

Вышеупомянутый script печатает 6.

Но если мы изменим локальный на мой, он напечатает 5.

В этом разница. Простой.

0

dinomite пример использования local для переопределения разделителя записей - это единственный раз, когда я столкнулся во множестве программирования perl. Я живу в нишевой среде perl [программирование безопасности], но это действительно редко используется в моем опыте.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню