web-dev-qa-db-fra.com

Quelle est la difference entre my et notre in Perl?

Je sais ce que my est 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? En quoi our diffère-t-il de my?

180
Nathan Fellman

Grande question: comment our diffère-t-il de my et que fait our?

En résumé:

Disponible depuis Perl 5, my est un moyen de déclarer:

  • variables non-paquet, qui sont
  • privé,
  • new ,
  • variables non globales ,
  • séparé de tout colis. Pour que la variable ne puisse pas être accessible sous la forme de $package_name::variable.


D'autre part, our les variables sont:

  • variables de package, et donc automatiquement
  • variables globales ,
  • définitivement pas privé ,
  • ils ne sont pas nécessairement nouveaux non plus; et ils
  • peut être accessible en dehors du paquet (ou de la portée lexicale) avec l'espace de nom qualifié, comme $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 obtenir des avertissements de frappe ou des erreurs de compilation. Depuis Perl 5.6, il a remplacé le obsolète use vars _ , qui n’était que périmé par fichier, et non par périmètre lexical tel quel _ our.

Par exemple, le nom formel et qualifié de la variable $x à l'intérieur package main est $main::x. Déclarant our $x vous permet d’utiliser le nu $x variable sans pénalité (c'est-à-dire sans erreur résultante) dans le champ 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.

210
Fran Corpier

Les liens PerlMonks et PerlDoc de cartman et Olafur constituent une excellente référence. Voici un résumé de mon résumé:

my les variables ont une portée lexicale dans un seul bloc défini par {} ou dans le même fichier s’il n’est pas dans {}s. Ils ne sont pas accessibles à partir de packages/sous-programmes définis en dehors du même périmètre/bloc lexical.

Les variables our sont définies dans un package/fichier et sont accessibles à partir de tout code qui use ou require et les conflits de nom de fichier/fichier sont résolus entre les packages en ajoutant le préfixe au nom approprié.

Pour compléter, les variables local ont une portée "dynamique", se différenciant des variables my en ce sens qu’elles sont également accessibles à partir de sous-routines appelées dans le même bloc.

59
bubaker

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";
48
FMc

Faire face à la portée est un bon aperçu des règles de portée de Perl. Il est assez vieux pour que our ne soit pas discuté dans le corps du texte. Il est traité dans la section Notes à la fin.

L'article parle des variables de package et de la portée dynamique et de la différence entre les variables lexicales et la portée lexicale.

12
daotoad

my est utilisé pour les variables locales, alors que notre est utilisé pour les variables globales. Plus de lecture sur Portée variable en Perl: les bases .

6
ismail

C'est une vieille question, mais j'ai toujours rencontré quelques pièges au sujet des déclarations lexicales en Perl qui me foiraient, 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 pouvions pas dire si local $var = 42; est une définition ou une déclaration. Mais qu'en est-il de ceci:

use strict;
use warnings;

local $var = 42;
print "var: $var\n";

Le deuxième programme va jeter une erreur:

Global symbol "$var" requires explicit package name.

$var _ n'est pas défini, ce qui signifie local $var; n'est qu'une déclaration! Avant d'utiliser local pour déclarer une variable, assurez-vous qu'elle a déjà été définie en tant que variable globale.

Mais pourquoi cela ne va pas échouer?

use strict;
use warnings;

local $a = 42;
print "var: $a\n";

Le résultat est: var: 42.

C'est parce que $a, aussi bien que $b, est une variable globale prédéfinie en Perl. Rappelez-vous la fonction sort ?

2. lexical ou global?

J'étais un programmeur C avant de commencer à utiliser Perl, donc le concept de variables lexicales et globales me semble simple: il ne s'agit que de 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 de 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 définie dans un bloc de fonction! En réalité, 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 obligera le programmeur à déclarer explicitement la variable lexicale, de sorte que nous ne soyons pas dérangés par certaines erreurs prises pour acquis.

5
Xu Ding

Le perldoc a une bonne définition de notre.

Contrairement à my, qui alloue du stockage pour une variable et associe un nom simple à ce stockage pour une utilisation dans l'étendue actuelle, notre association associe un nom simple à une variable de package dans le package actuel, pour une utilisation dans l'étendue actuelle. En d'autres termes, notre a les mêmes règles de portée que my, mais ne crée pas nécessairement de variable.

4
Ólafur Waage

Ceci n’est que quelque peu lié à la question, mais je viens de découvrir un bit (pour moi) obscur de la syntaxe Perl que vous pouvez utiliser avec "nos" (packages) variables que vous ne pouvez pas utiliser avec "mon" (local) variables.

#!/usr/bin/Perl

our $foo = "BAR";

print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";

Sortie:

BAR
BAZ

Cela ne fonctionnera pas si vous changez 'notre' en 'mon'.

2
Misha Gale
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";

Produira 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ù "utiliser strict" obtiendrait cet échec lors de l’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.
0
Lavi Buchnik

Essayez juste 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";
0
Yugdev