Я знаю, что my
есть в Perl. Он определяет переменную, которая существует только в области действия блока, в котором она определена. Что делает our
?
Чем our
отличается от my
?
Я знаю, что my
есть в Perl. Он определяет переменную, которая существует только в области действия блока, в котором она определена. Что делает our
?
Чем our
отличается от my
?
Ответы:
Большой вопрос: чем 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"
. Область действия может быть одним, двумя или несколькими пакетами или одним небольшим блоком.
local
не создает переменных. Это не относится my
и our
вообще. local
временно создает резервную копию значения переменной и очищает ее текущее значение.
our
переменные не являются пакетными переменными. Они не глобальные, а переменные лексического масштаба, как my
переменные. Вы можете видеть , что в следующей программе: package Foo; our $x = 123; package Bar; say $x;
. Если вы хотите «объявить» переменную пакета, вам нужно использовать use vars qw( $x );
. our $x;
объявляет переменную с лексической областью, которая связывается с переменной с тем же именем в пакете, в котором она our
была скомпилирована.
Ссылки PerlMonks и PerlDoc от Cartman и Olafur являются отличным справочным материалом. Ниже приведена моя краткая сводка:
my
переменные лексически ограничены в пределах одного блока, определенного {}
или внутри одного и того же файла, если не в {}
s. Они не доступны из пакетов / подпрограмм, определенных вне одной лексической области видимости / блока.
our
переменные в области видимости пакета / файл и доступны из любого кода, use
или require
что пакет / файл - конфликты имен разрешаются между пакетами, предваряя соответствующее пространство имен.
Просто для округления, local
переменные «динамически» ограничены, отличаясь от my
переменных тем, что они также доступны из подпрограмм, вызываемых в одном и том же блоке.
my
переменных лексически ограничены [...] в одном и том же файле, если не в {}
s". Это было полезно для меня, спасибо.
Пример:
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";
Справиться со Scoping - хороший обзор правил Perl. Это достаточно старое, что our
не обсуждается в основной части текста. Он рассматривается в разделе « Примечания » в конце.
В статье рассказывается о переменных пакета и динамической области видимости, а также о том, чем они отличаются от лексических переменных и лексической области видимости.
my
используется для локальных переменных, тогда our
как используется для глобальных переменных.
Подробнее читайте в Variable Scoping в Perl: основы .
${^Potato}
является глобальным. Он ссылается на одну и ту же переменную независимо от того, где вы ее используете.
Я когда-либо встречал некоторые подводные камни в лексических декларациях в 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. Помните функцию сортировки ?
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-программу, что заставит программиста явно объявлять лексическую переменную, чтобы мы не ошиблись из-за некоторых ошибок, принимаемых как должное.
У perldoc есть хорошее определение нашего.
В отличие от my, который одновременно выделяет хранилище для переменной и ассоциирует простое имя с этим хранилищем для использования в текущей области, наши связывают простое имя с переменной пакета в текущем пакете для использования в текущей области. Другими словами, у наших правил те же, что и у my, но необязательно создавать переменную.
Это только отчасти связано с вопросом, но я только что обнаружил (для меня) непонятный бит синтаксиса perl, который вы можете использовать с «нашими» (пакетными) переменными, которые вы не можете использовать с «моим» (локальным) переменные.
#!/usr/bin/perl
our $foo = "BAR";
print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";
Вывод:
BAR
BAZ
Это не сработает, если вы измените «наш» на «мой».
perl -e "my $foo = 'bar'; print $foo; ${foo} = 'baz'; pr int $foo"
output: barbaz
perl -e "my $foo = 'bar'; print $foo; ${"foo"} = 'baz'; print $foo"
output: barbaz
perl -e "my $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"
output: barbar
Таким образом, в моем тестировании я попал в ту же ловушку. $ {foo} аналогично $ foo, скобки полезны при интерполяции. $ {"foo"} на самом деле выглядит как $ main :: {}, который является главной таблицей символов, так как он содержит только переменные области видимости пакета.
perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"
работам, так как в этом контексте $ {"foo"} теперь равно $ {"test :: foo"}. О символьных таблицах и глобусах есть некоторая информация об этом, как и книга по программированию на Advanced Perl. Извините за мою предыдущую ошибку.
print "package is: " . __PACKAGE__ . "\n";
our $test = 1;
print "trying to print global var from main package: $test\n";
package Changed;
{
my $test = 10;
my $test1 = 11;
print "trying to print local vars from a closed block: $test, $test1\n";
}
&Check_global;
sub Check_global {
print "trying to print global var from a function: $test\n";
}
print "package is: " . __PACKAGE__ . "\n";
print "trying to print global var outside the func and from \"Changed\" package: $test\n";
print "trying to print local var outside the block $test1\n";
Будет выводить это:
package is: main
trying to print global var from main package: 1
trying to print local vars from a closed block: 10, 11
trying to print global var from a function: 1
package is: Changed
trying to print global var outside the func and from "Changed" package: 1
trying to print local var outside the block
В случае использования «use strict» вы получите этот сбой при попытке запустить скрипт:
Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.
Просто попробуйте использовать следующую программу:
#!/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";
#!/usr/bin/perl -l
use strict;
# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'
our $lol = eval {$lol} || 'lol' ;
print $lol;
our
и my
разные? Как этот пример показывает это?
Давайте подумаем, что такое интерпретатор на самом деле: это кусок кода, который хранит значения в памяти и позволяет командам в программе, которые он интерпретирует, получать доступ к этим значениям по их именам, которые указаны внутри этих инструкций. Таким образом, большая задача интерпретатора состоит в том, чтобы сформировать правила использования имен в этих инструкциях для доступа к значениям, которые хранит интерпретатор.
При обнаружении «my» интерпретатор создает лексическую переменную: именованное значение, к которому интерпретатор может получить доступ только во время выполнения блока и только из этого синтаксического блока. При обнаружении «нашего» интерпретатор создает лексический псевдоним переменной пакета: он связывает имя, которое интерпретатор должен с тех пор обрабатывать как имя лексической переменной, пока блок не будет завершен, со значением пакета. переменная с тем же именем.
В результате вы можете притворяться, что используете лексическую переменную, и обходить правила «строгого использования» при полной квалификации переменных пакета. Поскольку интерпретатор автоматически создает переменные пакета при их первом использовании, побочным эффектом использования «нашего» также может быть то, что интерпретатор также создает переменную пакета. В этом случае создаются две вещи: переменная пакета, к которой интерпретатор может получить доступ отовсюду, при условии, что она правильно обозначена в соответствии с запросом 'use strict' (с добавлением имени ее пакета и двух двоеточий) и ее лексическим псевдонимом.
Источники: