Qual'è la differenza tra 'my' e 'our' in Perl?


188

So cosa myc'è in Perl. Definisce una variabile che esiste solo nell'ambito del blocco in cui è definita. Cosa fa our?

In cosa ourdifferisce da my?

Risposte:


215

Grande domanda: in che cosa ourdifferisce mye cosa fa our?

In sintesi:

Disponibile da Perl 5, myè un modo per dichiarare variabili non-pacchetto, che sono:

  • privato
  • nuovo
  • non globale
  • separato da qualsiasi pacchetto, in modo che la variabile non sia accessibile sotto forma di $package_name::variable.


D'altra parte, le ourvariabili sono variabili di pacchetto e quindi automaticamente:

  • variabili globali
  • sicuramente non privato
  • non necessariamente nuovo
  • è possibile accedere al di fuori del pacchetto (o ambito lessicale) con lo spazio dei nomi qualificato, come $package_name::variable.


La dichiarazione di una variabile con ourconsente di prevedere le variabili in modo da utilizzarle use strictsenza ottenere avvisi di battitura o errori di compilazione. Da Perl 5.6, ha sostituito il obsoleto use vars, che era solo nell'ambito dei file e non come ambito lessicale our.

Ad esempio, il nome formale e qualificato per la variabile $xinside package mainè $main::x. La dichiarazione our $xconsente di utilizzare la $xvariabile bare senza penalità (ovvero, senza un errore risultante), nell'ambito della dichiarazione, quando lo script utilizza use stricto use strict "vars". L'ambito potrebbe essere uno o due o più pacchetti o un piccolo blocco.


2
In che modo il nostro differisce dal locale?
Nathan Fellman,

17
@Nathan Fellman, localnon crea variabili. Essa non riguarda mye oura tutti. localesegue temporaneamente il backup del valore della variabile e cancella il valore corrente.
ikegami,

1
ourle variabili non sono variabili del pacchetto. Non sono di portata globale, ma variabili di portata lessicale proprio come le myvariabili. Si può vedere che nel seguente programma: package Foo; our $x = 123; package Bar; say $x;. Se si desidera "dichiarare" una variabile di pacchetto, è necessario utilizzare use vars qw( $x );. our $x;dichiara una variabile con ambito lessicale che è aliasata della variabile con lo stesso nome nel pacchetto in cui è ourstata compilata.
ikegami,

60

I collegamenti PerlMonks e PerlDoc di Cartman e Olafur sono un ottimo riferimento - di seguito è la mia crepa in un riassunto:

myle variabili hanno un ambito lessicale all'interno di un singolo blocco definito dallo {}stesso file o all'interno di esso se non in {}s. Non sono accessibili da pacchetti / subroutine definiti al di fuori dello stesso ambito / blocco lessicale.

ourle variabili sono incluse in un pacchetto / file e sono accessibili da qualsiasi codice che useo requirequel pacchetto / file - i conflitti di nomi vengono risolti tra i pacchetti anteponendo lo spazio dei nomi appropriato.

Giusto per concludere, le localvariabili hanno un ambito "dinamico", differendo dalle myvariabili in quanto sono accessibili anche dalle subroutine chiamate all'interno dello stesso blocco.


+1 per "Le myvariabili hanno un ambito lessicale [...] all'interno dello stesso file se non in {}s". Mi è stato utile, grazie.
Georg,

48

Un esempio:

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

11

Far fronte a Scoping è una buona panoramica delle regole di scoping Perl. È abbastanza vecchio che ournon è discusso nel corpo del testo. È affrontato nella sezione Note alla fine.

L'articolo parla delle variabili del pacchetto e dell'ambito dinamico e di come ciò differisca dalle variabili lessicali e dall'ambito lessicale.


5

myè usato per le variabili locali, mentre ourè usato per le variabili globali.

Maggiori informazioni su Scoping variabile in Perl: le basi .


16
Fai attenzione a lanciare parole locali e globali. I termini propri sono lessicali e pacchetto. Non puoi creare vere variabili globali in Perl, ma alcune esistono già come $ _, e local si riferisce a variabili di pacchetto con valori localizzati (creati da local), non a variabili lessicali (create con my).
Chas. Owens,

${^Potato}è globale. Si riferisce alla stessa variabile indipendentemente da dove la si utilizza.
MJD

5

Ho mai incontrato alcune insidie ​​sulle dichiarazioni lessicali in Perl che mi hanno incasinato, che sono anche legate a questa domanda, quindi aggiungo solo il mio sommario qui:

1. Definizione o dichiarazione?

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

L'output è var: 42. Tuttavia non abbiamo potuto dire se si local $var = 42;tratta di una definizione o dichiarazione. Ma che dire di questo:

use strict;
use warnings;

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

Il secondo programma genererà un errore:

Global symbol "$var" requires explicit package name.

$varnon è definito, il che significa che local $var;è solo una dichiarazione! Prima di utilizzare localper dichiarare una variabile, assicurarsi che sia stata precedentemente definita come variabile globale.

Ma perché questo non fallirà?

use strict;
use warnings;

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

L'uscita è: var: 42.

Questo perché $a, oltre che $b, è una variabile globale predefinita in Perl. Ricorda la funzione di ordinamento ?

2. Lessico o globale?

Ero un programmatore C prima di iniziare a usare Perl, quindi il concetto di variabili lessicali e globali mi sembra semplice: corrisponde solo alle variabili auto ed esterne in C. Ma ci sono piccole differenze:

In C, una variabile esterna è una variabile definita all'esterno di qualsiasi blocco funzione. D'altra parte, una variabile automatica è una variabile definita all'interno di un blocco funzione. Come questo:

int global;

int main(void) {
    int local;
}

Mentre in Perl, le cose sono sottili:

sub main {
    $var = 42;
}

&main;

print "var: $var\n";

L'output è var: 42. $varè una variabile globale anche se definita in un blocco funzione! In realtà in Perl, ogni variabile è dichiarata come globale per impostazione predefinita.

La lezione è quella di aggiungere sempre use strict; use warnings;all'inizio di un programma Perl, che costringerà il programmatore a dichiarare esplicitamente la variabile lessicale, in modo da non incasinarci per alcuni errori dati per scontati.


Maggiori informazioni su ["ricordare [$ ae $ b in] ordinamento" qui] ( stackoverflow.com/a/26128328/1028230 ). Perl non smette mai di stupirmi.
ruffin,

4

Il perldoc ha una buona definizione della nostra.

A differenza di my, che alloca sia l'archiviazione per una variabile che associa un nome semplice a tale archiviazione da utilizzare nell'ambito corrente, i nostri associati associano un nome semplice a una variabile pacchetto nel pacchetto corrente, da utilizzare nell'ambito corrente. In altre parole, il nostro ha le stesse regole di scoping del mio, ma non crea necessariamente una variabile.


2

Questo è solo in qualche modo correlato alla domanda, ma ho appena scoperto un (per me) oscuro bit di sintassi perl che puoi usare con le "nostre" variabili (pacchetto) che non puoi usare con "mio" (locale) variabili.

#!/usr/bin/perl

our $foo = "BAR";

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

Produzione:

BAR
BAZ

Questo non funzionerà se cambi "da" a "mio".


1
Non così. $ foo $ {foo} $ {'foo'} $ {"foo"} funzionano tutti allo stesso modo per assegnazione variabile o dereferenziazione. Scambiare il nostro nell'esempio sopra per il mio funziona. Quello che probabilmente hai provato è stato provare a dereferenziare $ foo come variabile di pacchetto, come $ main :: foo o $ :: foo, che funzionerà solo per i pacchetti globali, come quelli definiti con il nostro .
Cosmicnet,

Ho appena eseguito nuovamente il test utilizzando v5.20 e sicuramente non fornisce lo stesso output con il mio (stampa BAR due volte.)
Misha Gale,

1
Il mio test (su Windows): 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 Nel mio test ero caduto nella stessa trappola. $ {foo} è uguale a $ foo, le parentesi sono utili durante l'interpolazione. $ {"foo"} è in realtà uno sguardo a $ main :: {} che è la tabella dei simboli principale, in quanto tale contiene solo variabili con ambito pacchetto.
Cosmicnet,

1
$ {"main :: foo"}, $ {":: foo"} e $ main :: foo sono gli stessi di $ {"foo"}. La scorciatoia è perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"opera sensibile al pacchetto , poiché in questo contesto $ {"foo"} è ora uguale a $ {"test :: foo"}. Of Symbol Tables and Globs contiene alcune informazioni, così come il libro di programmazione Advanced Perl. Ci scusiamo per il mio precedente errore.
Cosmicnet,

0
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";

Emetterà questo:

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 

Nel caso in cui l'utilizzo di "Usa rigoroso" ottenga questo errore durante il tentativo di eseguire lo script:

Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.

Si prega di fornire una sorta di spiegazione. Il dumping di codice come questo è raramente considerato appropriato.
Scott Solmer,

in parole semplici: La nostra (come dice il nome) è una declinazione variabile per usare quella variabile da qualsiasi posto nello script (funzione, blocco ecc ...), ogni variabile di default (nel caso non dichiarato) appartiene a "main" pacchetto, la nostra variabile può ancora essere utilizzata anche dopo la declinazione di un altro pacchetto nello script. la "mia" variabile nel caso dichiarata in un blocco o in una funzione, può essere utilizzata solo in quel blocco / funzione. nel caso in cui la "mia" variabile sia stata dichiarata non chiusa in un blocco, può essere utilizzata in qualsiasi punto dello scriot, anche in un blocco chiuso o in una funzione come la "nostra" variabile, ma non può essere utilizzata in caso di modifica del pacchetto
Lavi Buchnik,

Il mio script sopra mostra che per impostazione predefinita ci troviamo nel pacchetto "principale", quindi lo script stampa una "nostra" variabile dal pacchetto "principale" (non chiuso in un blocco), quindi dichiariamo due "mie" variabili in una funzione e stampali da quella funzione. quindi stampiamo una "nostra" variabile da un'altra funzione per mostrare che può essere utilizzata in una funzione. quindi cambiamo il pacchetto in "cambiato" (non "principale" non più) e stampiamo nuovamente la "nostra" variabile con successo. quindi tentando di stampare una "mia" variabile al di fuori della funzione e fallito. lo script mostra solo la differenza tra "nostro" e "mio" utilizzo.
Lavi Buchnik,

0

Prova a utilizzare il seguente programma:

#!/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";

Questo spiega la differenza tra il mio e il nostro. La mia variabile esce dal campo di applicazione al di fuori delle parentesi graffe ed è raccolta dei rifiuti ma la nostra variabile è ancora viva.
Yugdev,

-1
#!/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;

Puoi spiegare cosa intende dimostrare questo codice? Perché oure mydiverso? Come mostra questo esempio?
Nathan Fellman,

-1

Pensiamo a cosa sia realmente un interprete: è un pezzo di codice che memorizza i valori in memoria e consente alle istruzioni in un programma che interpreta di accedere a quei valori con i loro nomi, che sono specificati in queste istruzioni. Quindi, il grande compito di un interprete è quello di modellare le regole di come dovremmo usare i nomi in quelle istruzioni per accedere ai valori che l'interprete memorizza.

Incontrando "mio", l'interprete crea una variabile lessicale: un valore denominato a cui l'interprete può accedere solo mentre esegue un blocco e solo dall'interno di quel blocco sintattico. Incontrando "nostro", l'interprete crea un alias lessicale di una variabile di pacchetto: lega un nome, che l'interprete suppone da allora in poi elaborare come nome di una variabile lessicale, fino al termine del blocco, al valore del pacchetto variabile con lo stesso nome.

L'effetto è che puoi quindi far finta di utilizzare una variabile lessicale e bypassare le regole di "uso rigoroso" sulla qualificazione completa delle variabili del pacchetto. Poiché l'interprete crea automaticamente le variabili del pacchetto quando vengono utilizzate per la prima volta, l'effetto collaterale dell'utilizzo di "our" potrebbe anche essere che l'interprete crea anche una variabile del pacchetto. In questo caso, vengono create due cose: una variabile di pacchetto, a cui l'interprete può accedere da qualsiasi luogo, a condizione che sia correttamente designata come richiesto da "use strict" (anteposto con il nome del suo pacchetto e due due punti) e il suo alias lessicale.

fonti:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.