В чем разница между моим и локальным в Perl?

StackOverflow https://stackoverflow.com/questions/129607

  •  02-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

В основном подумайте 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

Другие советы

Короткий ответ заключается в том, что my помечает переменную как частную в лексической области видимости и 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 действительно удобно делать крутые вещи.

Цитата из Изучение Перла:

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

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

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

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

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

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

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

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

Локальный изменяет свои перечисленные переменные, чтобы быть «локальными» в блок -блоке, Eval или Do -и любую подпрограмму, вызванную изнутри этого блока.Местный локальный дает временные значения глобальным переменным (означающим пакет).Это не создает локальную переменную.Это известно как динамическая область.Lexical Scoping выполняется с моим, что больше похоже на автоматические объявления C.

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

Что ж, Google действительно помогает вам в этом: http://www.perlmonks.org/?node_id=94007

По ссылке:

Краткое резюме:«Мой» создает новую переменную, «локально» временно изменяет значение переменной.

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

Обычно используйте my, это быстрее и не делает ничего странного.

От man perlsub:

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

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

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

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

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

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

Более подробное описание см. в статье Марка Джейсона Доминуса. Как справиться с определением объема.

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

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

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

На практике вам почти всегда нужно «мой», а не «локальный».

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

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

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

&s;

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

sub b()
{
    $s++;
}

Приведенный выше скрипт печатает 6.

Но если мы изменим local на my, он напечатает 5.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top