Локальные и глобальные переменные в perl

У меня мало сомнений по поводу объема local/our в Perl. Я прочитал много документации, но я все еще в замешательстве. ниже приведены недоразумения

  1. Что такое область действия local?

    то, что я прочитал, → local копирует значение глобальной переменной, изменяет значение, пользователь будет использовать его, и вне блока оно сохранит глобальное значение

    Путаница → my делает то же самое. Единственное преимущество, которое я вижу, состоит в том, что некоторые переменные, такие как $package::var, не могут быть объявлены с моей областью, но могут быть объявлены с локальной областью. Что еще для локального

  2. Что такое "глобальная" переменная?

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

сомнения → Опять же, если мы объявим переменную с областью действия my только в main, тогда мы сможем получить доступ к переменной во всем пакете. Это правильно? Можно ли добавить переменные области my в массив @EXPORT и использовать его в других пакетах?

Я думаю, что глобальные переменные объявляются с ключевым словом our. Есть ли другой способ сделать это?

Этот вопрос может выглядеть повторяющимся, но я в замешательстве.

Ответ 1

В терминах определения области обзора в Perl существует два вида переменных.

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

Вот способы создания переменной.

  • my создает лексическую переменную.
  • our создает лексическую переменную, которая сглажена для переменной с тем же именем в текущем пакете. Другими словами, our $foo; совпадает с alias my $foo = $The::Current::Package::foo;.
  • Глобальные переменные создаются при использовании.

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


my делает то же самое.

Нет. local не изменяет область действия переменной. Хотя лексическая переменная видна только в лексической области видимости, локальная глобальная переменная по-прежнему отображается во всем интерпретаторе.

$x = 123;
sub foo { print "$x\n"; }
{ local $x = 456; foo(); }  # 456
foo();                      # 123

$x = 123;
sub foo { print "$x\n"; }
{ my $x = 456; foo(); }   # 123
foo();                    # 123

Что еще для local

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

(Исторически это были все переменные. Начиная с 5.6, только слова препинания не могут быть объявлены лексически.)


Что такое глобальная переменная?

Переменная, которая может отображаться глобально, т.е. любым кодом в интерпретаторе.


Возможно ли добавить мои измененные переменные в массив @EXPORT и использовать их в других пакетах?

Нет. @EXPORT используется экспортером. Экспортер не сможет найти ничего, кроме глобальных символов (поскольку файлы скомпилированы в свежих лексических областях), поэтому @EXPORT должен содержать только глобальные символы.

Ответ 2

Существует два вида переменных, лексически охваченные и глобально охваченные.

В Perl перед версией 5 был только глобальный охват. Эти переменные являются переменными пакета. Эти переменные доступны повсюду в программе, если вы используете префикс пакета.

Было введено ключевое слово local, чтобы предоставить способ изменить значение одной из этих глобальных переменных пакета внутри ограниченной области, например внутри одной подпрограммы. Он сохранит старое значение в стеке при вводе области с помощью оператора local, и после выхода он восстановит старое значение. Это все еще глобальные пакеты пакетов, что означает, что они все еще доступны повсюду. Если вы находитесь внутри области с переменной local, и вы вызываете подпрограмму, эта переменная все еще отображается внутри этой подпрограммы.

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

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

Ответ 3

Пример 1:

sub mess_with_foo {
      $foo=0;
 }

 sub myfunc {
      my $foo=20;
      mess_with_foo();
      print $foo;
 }
 myfunc();

Пример 2:

 sub mess_with_foo {
      $foo=0;
 }

 sub myfunc {
      local $foo=20;
      mess_with_foo();
      print $foo;
 }
 myfunc();

Пример 1 печатает 20, потому что mess_with_foo() не может видеть my $foo. Он не мог ее изменить. my $foo можно увидеть только в области myfunc().

Пример 2 печатает 0, потому что mess_with_foo() может видеть my $foo и изменять его. local $foo можно увидеть в области myfunc() И в объеме любой функции, вызванной из ее области myfunc().

Это единственное различие. Ни my $foo, ни local $foo не будут отображаться вне области myfunc().

Ответ 4

Вот что я узнал о переменных областях: мои декали довольно четкие и понятные, если их использовать внутри блоков. Если они используются в main вне любого блока, они немного отличаются, это означает, что переменная my, объявленная вне блока, видна даже внутри функций, вызываемых из любого места в одном файле, если эти функции определены в одном и том же файле. Однако, если они объявлены внутри блока, они не видны функциям, даже если они вызваны из одного и того же блока. Кажется, все мои переменные живут в стеке. И: вы не можете локализовать их с местными.

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

локальные переменные кажутся мне реликвией из предыдущих версий Perl. Они являются просто переназначением глобальных (наших) переменных с областью действия блока и возобновляют свои прежние значения после завершения блока. Я не вижу смысла в их использовании.

Моя небольшая программа ниже показывает все это и показывает, насколько сильно пропущен объявленный() тест, помимо хорошо известного теста define(), для выявления необъявленных переменных как таковых.

  1 #!/usr/bin/perl
  2
  3 use strict;
  4
  5 ### This is about variable scoping with my, our and local
  6 my $fsv = "file scope";                 # visible for all code in this file
  7 our $gsv = "global scope";              # not different from my $fsv, except in packages
  8 our $lsv = "global";                    # global scope, but localized in subsequent block
  9
 10 {
 11    my $bsv = "lex scope";               # visible only inside this block, not even in subs called from here
 12    $gsv = "visible everywhere";
 13    local $lsv = "global, but localized val";
 14
 15    print "This is variable \$bsv with value $bsv inside block\n";
 16    print "This is variable \$fsv with value $fsv inside block\n";
 17    print "This is variable \$lsv with value $lsv inside block\n\n";
 18    print_vars("calledfromblock");
 19 }
 20
 21 print_vars("calledfromoutside");
 22
 23
 24 no strict 'vars';                       # needed if testing variable for declaredness rather than definedness
 25 if ( defined $bsv ) {
 26    print "\$bsv as defined outside braces: $bsv\n"
 27 } else {
 28    print "\$bsv not defined outside braces\n";
 29 }
 30 print "This is variable \$lsv with value $lsv outside block\n";
 31 # use strict 'vars';                    # no strict 'vars' effective even in sub print_vars unless switched back on
 32
 33 sub print_vars
 34 {
 35    my $whence = shift;
 36    my $gsv = "my variable";
 37    no strict 'refs';                    # needed to access the global var $gsv using ${'gsv'} despite the my decaration
 38
 39    if ( $whence eq "calledfromblock" ) {
 40       print "\t print_vars called from within the block:\n";
 41       ( defined $bsv )     ? print "\$bsv is $bsv inside sub\n"     : print "\$bsv not defined inside sub\n";
 42       ( defined $fsv )     ? print "\$fsv is $fsv inside sub\n"     : print "\$fsv not defined inside sub\n";
 43       ( defined ${'gsv'} ) ? print "\$gsv is ${'gsv'} inside sub\n" : print "\$gsv not defined inside sub\n";
 44       ( defined ${'lsv'} ) ? print "\$lsv is ${'lsv'} inside sub\n" : print "\$lsv not defined inside sub\n";
 45    } else {
 46       print "\t print_vars called from outside the block:\n";
 47       ( defined $bsv ) ? print "\$bsv is $bsv inside sub\n" : print "\$bsv not defined inside sub\n";
 48       ( defined $fsv ) ? print "\$fsv is $fsv inside sub\n" : print "\$fsv not defined inside sub\n";
 49       ( defined $gsv ) ? print "\$gsv is $gsv inside sub\n" : print "\$gsv not defined inside sub\n";
 50       ( defined $lsv ) ? print "\$lsv is $lsv inside sub\n" : print "\$lsv not defined inside sub\n";
 51    }
 52    print "\n";
 53 }