Je sais ce qu'il my
y a en Perl. Il définit une variable qui n'existe que dans la portée du bloc dans lequel elle est définie. Que fait our
-on?
En quoi our
diffère- my
t-il de ?
Je sais ce qu'il my
y a en Perl. Il définit une variable qui n'existe que dans la portée du bloc dans lequel elle est définie. Que fait our
-on?
En quoi our
diffère- my
t-il de ?
Réponses:
Grande question: en quoi our
diffère- t -il my
et que fait our
-il?
En résumé:
Disponible depuis Perl 5, my
est un moyen de déclarer des variables non-package, qui sont:
$package_name::variable
.D'autre part, les our
variables sont des variables de package, et donc automatiquement:
$package_name::variable
.Déclarer une variable avec our
vous permet de prédéclarer des variables afin de les utiliser sous use strict
sans recevoir d'avertissements de frappe ou d'erreurs de compilation. Depuis Perl 5.6, il a remplacé le use vars
périmètre obsolète , qui était uniquement défini par fichier, et non lexicalement tel quel our
.
Par exemple, le nom formel et qualifié de la variable à l' $x
intérieur package main
est $main::x
. La déclaration our $x
vous permet d'utiliser la $x
variable nue sans pénalité (c'est-à-dire sans erreur résultante), dans le cadre de la déclaration, lorsque le script utilise use strict
ou use strict "vars"
. La portée peut être un, deux ou plusieurs packages, ou un petit bloc.
local
ne crée pas de variables. Cela ne concerne pas my
et our
du tout. local
sauvegarde temporairement la valeur de la variable et efface sa valeur actuelle.
our
les variables ne sont pas des variables de package. Ce ne sont pas des variables à portée globale, mais des variables à portée lexique, tout comme des my
variables. Vous pouvez voir que dans le programme suivant: package Foo; our $x = 123; package Bar; say $x;
. Si vous souhaitez "déclarer" une variable de package, vous devez utiliser use vars qw( $x );
. our $x;
déclare une variable de portée lexicale qui a un alias sur la variable du même nom dans le package dans lequel a our
été compilé.
Les liens PerlMonks et PerlDoc de cartman et Olafur sont une excellente référence - voici ma fissure en un résumé:
my
les variables ont une portée lexicale dans un seul bloc défini par {}
ou dans le même fichier si ce n'est pas dans {}
s. Ils ne sont pas accessibles à partir des packages / sous-programmes définis en dehors du même champ / bloc lexical.
our
les variables sont étendues dans un package / fichier et sont accessibles à partir de tout code qui use
ou de require
ce package / fichier - les conflits de nom sont résolus entre les packages en ajoutant l'espace de noms approprié.
Pour arrondir, les local
variables ont une portée «dynamique», ce qui diffère des my
variables en ce qu'elles sont également accessibles à partir de sous-programmes appelés dans le même bloc.
my
variables ont une portée lexicale [...] dans le même fichier sinon dans {}
s". Cela m'a été utile, merci.
Un exemple:
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";
Faire face à la portée est un bon aperçu des règles de portée de Perl. Il est assez ancien pour our
ne pas être abordé dans le corps du texte. Il est abordé dans la section Notes à la fin.
L'article parle des variables de package et de la portée dynamique et en quoi cela diffère des variables lexicales et de la portée lexicale.
my
est utilisé pour les variables locales, alors qu'il our
est utilisé pour les variables globales.
Plus de lecture sur la portée variable en Perl: les bases .
${^Potato}
est mondial. Il fait référence à la même variable quel que soit l'endroit où vous l'utilisez.
J'ai déjà rencontré des pièges sur les déclarations lexicales en Perl qui m'ont dérangé, qui sont également liés à cette question, alors j'ajoute simplement mon résumé ici:
1. Définition ou déclaration?
local $var = 42;
print "var: $var\n";
La sortie est var: 42
. Cependant, nous ne pouvons pas dire s'il local $var = 42;
s'agit d'une définition ou d'une déclaration. Mais que diriez-vous de ceci:
use strict;
use warnings;
local $var = 42;
print "var: $var\n";
Le deuxième programme lancera une erreur:
Global symbol "$var" requires explicit package name.
$var
n'est pas défini, ce qui signifie local $var;
est juste une déclaration! Avant d'utiliser local
pour déclarer une variable, assurez-vous qu'elle est préalablement définie comme une variable globale.
Mais pourquoi cela n'échouera pas?
use strict;
use warnings;
local $a = 42;
print "var: $a\n";
La sortie est: var: 42
.
C'est parce $a
que, ainsi que $b
, est une variable globale prédéfinie en Perl. Vous vous souvenez de la fonction de tri ?
2. Lexique ou global?
J'étais programmeur C avant de commencer à utiliser Perl, donc le concept de variables lexicales et globales me semble simple: il correspond juste aux variables auto et externes en C.Mais il y a de petites différences:
En C, une variable externe est une variable définie en dehors de tout bloc fonctionnel. D'autre part, une variable automatique est une variable définie à l'intérieur d'un bloc fonction. Comme ça:
int global;
int main(void) {
int local;
}
En Perl, les choses sont subtiles:
sub main {
$var = 42;
}
&main;
print "var: $var\n";
La sortie est var: 42
. $var
est une variable globale même si elle est définie dans un bloc fonction! En fait, en Perl, toute variable est déclarée globale par défaut.
La leçon est de toujours ajouter use strict; use warnings;
au début d'un programme Perl, ce qui forcera le programmeur à déclarer la variable lexicale explicitement, afin que nous ne soyons pas dérangés par certaines erreurs prises pour acquises.
Le perldoc a une bonne définition de notre.
Contrairement à my, qui alloue à la fois du stockage pour une variable et associe un nom simple à ce stockage pour une utilisation dans la portée actuelle, notre associe un nom simple à une variable de package dans le package actuel, à utiliser dans la portée actuelle. En d'autres termes, notre a les mêmes règles de portée que mon, mais ne crée pas nécessairement une variable.
Ceci n'est que quelque peu lié à la question, mais je viens de découvrir un peu (pour moi) obscur de syntaxe Perl que vous pouvez utiliser avec "nos" variables (package) que vous ne pouvez pas utiliser avec "my" (local) variables.
#!/usr/bin/perl
our $foo = "BAR";
print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";
Production:
BAR
BAZ
Cela ne fonctionnera pas si vous remplacez «notre» par «mon».
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
Donc, lors de mes tests, j'étais tombé dans le même piège. $ {foo} est identique à $ foo, les crochets sont utiles lors de l'interpolation. $ {"foo"} est en fait une recherche vers $ main :: {} qui est la table de symboles principale, en tant que telle ne contient que des variables de portée du package.
perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"
, car dans ce contexte $ {"foo"} est maintenant égal à $ {"test :: foo"}. Of Symbol Tables and Globs contient des informations à ce sujet, tout comme le livre de programmation Advanced Perl. Désolé pour mon erreur précédente.
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";
Sortira ceci:
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
Dans le cas où l'utilisation de "use strict" obtiendra cet échec lors de la tentative d'exécution du script:
Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.
Essayez simplement d'utiliser le programme suivant:
#!/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
et my
différent? Comment cet exemple le montre-t-il?
Pensons à ce qu'est réellement un interpréteur: c'est un morceau de code qui stocke des valeurs en mémoire et laisse les instructions d'un programme qu'il interprète accéder à ces valeurs par leurs noms, qui sont spécifiés dans ces instructions. Ainsi, le gros travail d'un interprète est de façonner les règles sur la façon dont nous devrions utiliser les noms dans ces instructions pour accéder aux valeurs stockées par l'interpréteur.
En rencontrant "mon", l'interpréteur crée une variable lexicale: une valeur nommée à laquelle l'interpréteur ne peut accéder que pendant qu'il exécute un bloc, et uniquement à partir de ce bloc syntaxique. En rencontrant "notre", l'interpréteur crée un alias lexical d'une variable de package: il lie un nom, que l'interpréteur est supposé désormais traiter comme le nom d'une variable lexicale, jusqu'à ce que le bloc soit terminé, à la valeur du package variable avec le même nom.
L'effet est que vous pouvez alors prétendre que vous utilisez une variable lexicale et contourner les règles de «use strict» sur la qualification complète des variables de package. Puisque l'interpréteur crée automatiquement des variables de package lors de leur première utilisation, l'effet secondaire de l'utilisation de "notre" peut également être que l'interpréteur crée également une variable de package. Dans ce cas, deux choses sont créées: une variable de package, à laquelle l'interpréteur peut accéder de partout, à condition qu'elle soit correctement désignée comme demandé par 'use strict' (précédée du nom de son package et de deux deux-points), et son alias lexical.
Sources: