¿Cuál es la diferencia entre mi y nuestro en Perl?


Sé lo que my está en Perl. Define una variable que solo existe en el ámbito del bloque en el que está definida. ¿Qué hace our? ¿En qué se diferencia our de my?

 171

12 answers

Gran pregunta: ¿Cómo our se diferencian de my y lo hace our hacer?

En resumen:

Disponible desde Perl 5, my es una forma de declarar:

  • variables no empaquetadas, que son
  • privado,
  • nuevo ,
  • variables no globales ,
  • separado de cualquier paquete. De modo que la variable no puede ser accessed in the form of $package_name::variable.


Por otra parte, our las variables son:

  • empaquetar variables, y por lo tanto automáticamente
  • variables globales ,
  • definitivamente no privado,
  • ni son necesariamente nuevos; y {[40]]}
  • se puede acceder a fuera del paquete (o ámbito léxico) con el espacio de nombres calificado, como $package_name::variable.


Declarar una variable con our le permite predeclare variables con el fin de utilizarlas bajo use strict sin obtener advertencias de errores tipográficos o errores en tiempo de compilación. Desde Perl 5.6, ha reemplazado a los obsoletos use vars, que solo tenía un ámbito de archivo, y no un ámbito léxico como es our.

Por ejemplo, el nombre formal y calificado para la variable $x dentro de package main es $main::x. Declarar our $x le permite utilizar la variable bare $x sin penalización (es decir, sin un error resultante), en el ámbito de la declaración, cuando el script utiliza use strict o use strict "vars". El ámbito puede ser uno, o dos, o más paquetes, o un bloque pequeño.

 198
Author: Fran Corpier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-18 23:37:13

Los enlaces de PerlMonks y PerlDoc de cartman y Olafur son una gran referencia - a continuación se muestra mi crack en un resumen:

my las variables tienen un ámbito léxico dentro de un solo bloque definido por {} o dentro del mismo archivo si no están en {} s. No son accesibles desde paquetes/subrutinas definidos fuera del mismo ámbito / bloque léxico.

our las variables están dentro del ámbito de un paquete / archivo y son accesibles desde cualquier código que use o require que los conflictos de nombre de paquete / archivo son se resuelve entre paquetes anteponiendo el espacio de nombres apropiado.

Sólo para completar, local variables son "dinámicamente" ámbito, a diferencia de my variables que también son accesibles desde las subrutinas llamadas dentro de la misma cuadra.

 59
Author: bubaker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-06 08:02:30

Un ejemplo:

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";
 45
Author: FMc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-28 03:24:36

Hacer frente al Scoping es una buena visión general de las reglas de scoping de Perl. Es bastante viejo que our no se discute en el cuerpo del texto. Se aborda en la sección Notas al final.

El artículo habla sobre las variables de paquete y el alcance dinámico y cómo esto difiere de las variables léxicas y el alcance léxico.

 12
Author: daotoad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-10 16:37:42

My se usa para variables locales, mientras que as our se usa para variables globales. Más lectura sobre Alcance de variables en Perl: los fundamentos.

 6
Author: ismail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-10 10:27:50

Es una vieja pregunta, pero alguna vez me encontré con algunas trampas sobre las declaraciones léxicas en Perl que me arruinaron, que también están relacionadas con esta pregunta, así que solo añado mi resumen aquí: {[18]]}

1. definición o declaración?

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

La salida es var: 42. Sin embargo, no podríamos decir si local $var = 42; es una definición o declaración. Pero ¿qué tal esto:

use strict;
use warnings;

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

El segundo programa lanzará un error:

Global symbol "$var" requires explicit package name.

$var no está definido, lo que significa que local $var; es solo un declaración! Antes de usar local para declarar una variable, asegúrese de que está definida previamente como una variable global.

Pero ¿por qué esto no fallará?

use strict;
use warnings;

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

La salida es: var: 42.

Eso es porque $a, así como $b, es una variable global predefinida en Perl. ¿Recuerdas la función sort?

2. léxico o global?

Yo era programador de C antes de comenzar a usar Perl, por lo que el concepto de variables léxicas y globales parece directo para mí: solo corresponde a las variables auto y externas en C. Pero hay pequeñas diferencias:

En C, una variable externa es una variable definida fuera de cualquier bloque de función. Por otro lado, una variable automática es una variable definida dentro de un bloque de función. Así:

int global;

int main(void) {
    int local;
}

Mientras que en Perl, las cosas son sutiles: {[18]]}

sub main {
    $var = 42;
}

&main;

print "var: $var\n";

La salida es var: 42, $var es una variable global incluso se define en un bloque de función! En realidad en Perl, cualquier variable es declarado como global por defecto.

La lección es siempre agregar use strict; use warnings; al principio de un programa Perl, lo que obligará al programador a declarar la variable léxica explícitamente, para que no nos confundamos con algunos errores que se dan por sentados.

 4
Author: Xu Ding,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-07 15:31:02

El perldoc tiene una buena definición de nuestro.

A diferencia de my, que asigna almacenamiento para una variable y asocia un nombre simple con ese almacenamiento para su uso dentro del ámbito actual, our asocia un nombre simple con una variable de paquete en el paquete actual, para su uso dentro del ámbito actual. En otras palabras, nuestro tiene las mismas reglas de alcance que mi, pero no necesariamente crea una variable.

 3
Author: Ólafur Waage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-11 00:23:17

Esto solo está un poco relacionado con la pregunta, pero acabo de descubrir una (para mí) oscura sintaxis de perl que puede usar con "nuestras" variables (paquete) que no puede usar con "mis" variables (locales).

#!/usr/bin/perl

our $foo = "BAR";

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

Salida:

BAR
BAZ

Esto no funcionará si cambias 'nuestro' por 'mi'.

 2
Author: Misha Gale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-02 15:03:03
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";

Producirá esto:

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 

En caso de usar "use strict"obtendrá este error al intentar ejecutar el 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
Author: Lavi Buchnik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-05 20:32:42

Solo intenta usar el siguiente programa:

#!/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
Author: Yugdev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-05 11:08:47
#!/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;
 -1
Author: xoid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-16 08:02:24

Pensemos en lo que es realmente un intérprete: es una pieza de código que almacena valores en la memoria y permite que las instrucciones de un programa que interpreta accedan a esos valores por sus nombres, que se especifican dentro de estas instrucciones. Por lo tanto, el gran trabajo de un intérprete es dar forma a las reglas de cómo debemos usar los nombres en esas instrucciones para acceder a los valores que almacena el intérprete.

Al encontrar "my", el intérprete crea una variable léxica: un valor con nombre que el intérprete solo puede acceder mientras ejecuta un bloque, y solo desde dentro de ese bloque sintáctico. Al encontrar "nuestro", el intérprete crea un alias léxico de una variable de paquete: enlaza un nombre, que el intérprete se supone que procesará a partir de entonces como el nombre de una variable léxica, hasta que el bloque esté terminado, con el valor de la variable de paquete con el mismo nombre.

El efecto es que luego puede pretender que está utilizando una variable léxica y omitir las reglas de ' uso strict ' on full qualification of package variables. Dado que el intérprete crea automáticamente variables de paquete cuando se usan por primera vez, el efecto secundario de usar "nuestro" también puede ser que el intérprete cree una variable de paquete también. En este caso, se crean dos cosas: una variable de paquete, a la que el intérprete puede acceder desde cualquier lugar, siempre que se designe correctamente como se solicita por 'use strict' (precedido con el nombre de su paquete y dos puntos), y su léxico apodo.

Fuentes:

 -1
Author: Evgeniy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-27 04:57:43