Я знаю, что 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' (с добавлением имени ее пакета и двух двоеточий) и ее лексическим псевдонимом.
Источники: