Опубликован: 17.08.2006 | Доступ: свободный | Студентов: 5388 / 708 | Оценка: 4.49 / 3.94 | Длительность: 20:58:00
ISBN: 978-5-9556-0078-9
Лекция 12:

Подпрограммы

Области видимости переменных

В Perl переменные по умолчанию видимы в пределах всей программы (точнее, в пределах пакета, но об этом будет рассказано позднее). Практика доказала, что использование глобальных переменных противоречит принципу модульности, поскольку связывает части программы зависимостями от глобальных данных. Поэтому во всех языках программирования предусмотрены средства ограничения видимости переменных. Как уже упоминалось в "лекции 2" , в Perl это делается с помощью объявления переменных. Чтобы ограничить видимость переменных рамками блока или подпрограммы, нужно объявить для них лексическую область видимости с помощью функции my(), как это уже делалось в приводимых ранее примерах. Когда при помощи my объявляется несколько переменных, то все они должны заключаться в круглые скобки, как показано ниже:

my ($var1, $var2, $var3) = (1, 2, 3); # правильно
# запись my ($var1=1, $var2=2, $var3=3) ошибочна
my $var4 = 4, $var5 = 5; # $var5 - глобальная, а не my

Чтобы проследить, как изменяются значения переменных, объявленных в главной программе и подпрограммах, внимательно прочитайте следующий пример (скучный, но полезный для понимания):

use strict;
my $var = 'm';            # лексическая $var в main
print "1(main)='$var'\n"; # выведет: 1(main)='m'
sub1();
print "7(main):'$var'\n"; # выведет: 7(main):'z'

sub sub1 {
   print "2(sub1)='$var'";
   $var = 's';               # изменяется $var из main!
   print "-->'$var'\n";      # выведет: 2(sub1)='m'-->'s'
   my $var = '1';            # изменена $var из sub1
   print "3(sub1)='$var'\n"; # выведет: 3(sub1)='1'  
   sub2();
                             # снова видима $var из sub1
   print "6(sub1):'$var'\n"; # выведет: 6(sub1):'1'  
}
sub sub2 { # снова видима $var из main
   print "4(sub2):'$var'"; 
   $var = 'z';               # изменяется $var из main!!
   print "-->'$var'\n";      # выведет: 4(sub2):'s'-->'z'
   my $var = '2';            # изменена $var1 из sub2
   print "5(sub2)='$var'\n"; # выведет: 5(sub2)='2'
}

Обратите внимание, что лексическая переменная $var, объявленная в главной программе, видима в обеих подпрограммах sub1 и sub2, поскольку они статически объявлены в рамках той же программы. Но при выполнении программы в подпрограмме sub2 не видима переменная $var, объявленная в процедуре sub1. Из приведенного примера видно, что после объявления в подпрограмме лексических переменных с помощью my(), изменения этих переменных не затрагивают других переменных с теми же именами. Поэтому, чтобы избежать нежелательного изменения значений переменных в других частях программы, рекомендуется всегда объявлять для переменных лексическую область видимости. Проконтролировать наличие объявлений для переменных в программе поможет прагма use strict. Другая разновидность лексических переменных, описываемых с помощью функции our, будет рассмотрена в следующей лекции.

Временные значения переменных с помощью local

В Perl имеется функция local(), также влияющая на область видимости переменных. Многие считают, что более удачным названием для нее было бы save(), потому что ее основное назначение - скрыть текущее значение глобальных переменных. Эта функция не создает локальных переменных, а делает "локальными" значения существующих глобальных переменных в текущей подпрограмме, блоке, eval или программном файле. Это значит, что после выполнения local текущие значения указанных переменных сохраняются в скрытом стеке, и новые значения переменных будут видимы вплоть до выхода из выполняемой подпрограммы, блока или файла, после чего восстанавливаются сохраненные значения переменных. На время действия local переменные остаются глобальными, поэтому новые временные значения переменных будут видимы и в вызываемых подпрограммах. Из-за временного характера действия функции local иногда говорят, что она описывает динамическую область видимости. Несколько переменных, чьи значения делаются временно скрытыми при помощи local, должны заключаться в круглые скобки, как показано ниже:

local $_; # временно скрыть значение буферной переменной 
local ($global1, $equant) = (1, 2); # правильно

Посмотрите, как изменится результат, если переписать предыдущий пример с использованием local вместо my в подпрограмме sub1:

$var = 'm'; # ГЛОБАЛЬНУЮ $var можно скрыть через local
print "1[main]='$var'\n"; # выведет: 1[main]='m'
sub1();
print "7[main]:'$var'\n"; # выведет: 7[main]:'s'
   
sub sub1 {
   print "2[sub1]='$var'";
   $var = 's';               # изменена $var из main!
   print "-->'$var'\n";      # выведет: 2[sub1]='m'-->'s'
   local $var = '1'; # значение ГЛОБАЛЬНОЙ $var скрывается
   print "3[sub1]#'$var'\n"; # выведет: 3[sub1]#'1'   
   sub2();
   print "6[sub1]:'$var'\n"; # выведет: 6[sub1]:'z'   
}
sub sub2 { # видна ГЛОБАЛЬНАЯ $var из sub1
   print "4[sub2]:'$var'";
   $var = 'z';               # изменена $var из sub1!
   print "-->'$var'\n";      # выведет: 4[sub2]:'1'-->'z'
   my $var = '2';            # изменена $var из sub2
   print "5[sub2]='$var'\n"; # выведет: 5[sub2]='2'
}

Сравнивая эту программу с предыдущим примером, можно отметить следующие отличия.

  1. Переменную $var в главной программе пришлось сделать глобальной, так как local не может скрывать лексические переменные.
  2. Действие local распространяется до конца подпрограммы sub1, а также на вызываемую подпрограмму sub2.
  3. При выходе из подпрограммы sub1 действие local заканчивается и восстанавливается значение, которое содержала глобальная переменная $var до применения к ней local.

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

  1. Временное скрытие значения глобальных переменных, в том числе у специальных переменных.
  2. Временная модификация отдельных элементов массивов и хэшей, даже имеющих лексическую область видимости.
  3. Создание локальных файловых манипуляторов в версиях Perl до 5.6, не поддерживающих использование лексических переменных для хранения файловых манипуляторов.
Сергей Крупко
Сергей Крупко

Добрый день.

Я сейчас прохожу курс  повышения квалификации  - "Профессиональное веб-программирование". Мне нужно получить диплом по этому курсу. Я так полагаю нужно его оплатить чтобы получить диплом о повышении квалификации. Как мне оплатить этот курс?

 

Галина Башкирова
Галина Башкирова

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

Системный администратор информационно-коммуникационных» систем.
Мне нужно самой найти тему? или делать по высланным темам