¿Python tiene un "use strict;" y "use warnings;" como en perl?


Estoy aprendiendo perl y python... al mismo tiempo, no es mi diseño, pero tiene que hacerse.

Pregunta:

En un script de perl que uso(ver más abajo) en la cabeza de mi txt.

#!/usr/bin/env perl

use strict;
use warnings;

¿Hay algo que deba hacer en rutina para mis scripts python?

Author: jon_shep, 2012-11-17

5 answers

Para dar una respuesta que quizás evite un poco del ruido del comentario aquí, probaré otra.

Los dos pragmatas en tu pregunta original realmente se expanden a: {[18]]}

use strict "vars";
use strict "refs";
use strict "subs";
use warnings;

Para responder a cada uno a su vez:

  • El efecto de use strict "vars" es hacer que un error en tiempo de compilación se refiera a una variable sin declarar primero que existe (como es el predeterminado en lenguajes más estáticos como C, C++ y Java). Porque Python no tiene una sintaxis específica para declarar que una variable existe, no tiene equivalente. Asignar un nombre en Python siempre lo crea si no existía primero. Esta característica de strict no tiene equivalente en Python y la seguridad que proporciona no puede ser recreada.

Eg:

$ perl -c -e 'use strict "vars"; $foo = 1'
Global symbol "$foo" requires explicit package name at -e line 1.
-e had compilation errors.

$ perl -c -e 'no strict "vars"; $foo = 1'
-e syntax OK
  • El efecto de use strict "refs" es no permitir el uso de cadenas simples que contengan el nombre de una variable (existente o nueva) como referencia a la variable en sí. Python no hace esto, por lo que no tiene necesidad de desactivarlo se.

Eg:

$ perl -e 'use strict "refs"; ${"message"} = "hello"; print $message'
Can't use string ("message") as a SCALAR ref while "strict refs" in use at -e line 1.

$ perl -e 'no strict "refs"; ${"message"} = "hello"; print $message'
hello
  • El efecto de use strict "subs" es provocar en tiempo de compilación cualquier intento de llamar a una función que se sabe que no existe. Python no realiza ninguna de estas comprobaciones, y no tiene forma de habilitar tal característica.

Eg:

$ perl -c -e 'use strict "subs"; foo'
Bareword "foo" not allowed while "strict subs" in use at -e line 1.
-e had compilation errors.

$ perl -c -e 'no strict "subs"; foo'
-e syntax OK
  • El efecto de use warnings es habilitar más advertencias tanto en compilación como en tiempo de ejecución de varias categorías de comportamiento que era predeterminado en versiones anteriores, a veces puede ser deseado, o que nunca ha sido un buena idea, pero no es estrictamente un error. Por ejemplo, el uso de valores no iniciados como números debería generalmente dar una advertencia, pero originalmente no lo hizo.

Eg:

$ perl -e 'use warnings; my $u; print 2 + $u'
Use of uninitialized value $u in addition (+) at -e line 1.
2

$ perl -e 'no warnings; my $u; print 2 + $u'
2

Finalmente, se han hecho algunos comentarios de que Python tiene una funcionalidad similar en __future__. Sin embargo, esto no debe considerarse similar al pragmata de Perl, ya que la mayoría de estos últimos tienen un ámbito léxico, y se pueden habilitar o deshabilitar dentro de pequeños ámbitos según sea necesario; where's Python __future__ es solo habilitado para un archivo de origen completo.

Eg.

use strict;
use warnings;

my $total;

$total += count_things($_) for @list;

{
   no warnings 'uninitialized';
   printf "The total is %d\n", $total;
}

Un ejemplo algo ingenioso, pero este demuestra el uso de no warnings 'uninitialized' para desactivar la advertencia sobre el uso de un valor no iniciado simplemente dentro de la instrucción printf, mientras mantiene las otras advertencias habilitadas en cualquier otro lugar.


En resumen: Python no tiene un use strict o casi equivalente, ya que cualquiera de las características de seguridad que proporciona son obligatorias o no están disponibles en el lenguaje Python, y no tiene un use warnings. Las características que proporciona solo se habilitan a nivel de archivo y no se pueden habilitar o deshabilitar selectivamente por ámbito.


Edit: En realidad, ahora se me ha informado que Python tiene algunas banderas de advertencia controlables, que se pueden habilitar y deshabilitar según sea necesario.

 49
Author: LeoNerd,
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
2017-01-28 01:40:06

Como otros usuarios han publicado, Python no tiene pragma estricto. Y esta, en mi opinión, es una de sus mayores deficiencias. Además, es una de las razones por las que, para proyectos de programación serios, todavía uso Perl.

No hay duda de que habrá devotos de Python que se ofendan con esta declaración. He oído a algunos decir que no necesitan estricta. Me parece que los que dicen esto normalmente no saben lo que te compra estricta. Considere el siguiente bloque de código en Python:

def Main():
    print(GetPrice(100,"Alaska"))
    print(GetPrice(100,"Florida"))
    print(GetPrice(100,"Michigan"))
    print(GetPrice(100,"Wisconsin"))

def GetPrice(UnitPrice,State):
    StateSalesTaxRate = 0
    if State == "Alabama": StateSalesTaxRate = 0.04
    if State == "Alaska": StateSalesTaxRate = 0
    if State == "Arizona": StateSalesTaxRate = 0.056
    if State == "Arkansas": StateSalesTaxRate = 0.065
    if State == "California": StateSalesTaxRate = 0.075
    if State == "Colorado": StateSalesTaxRate = 0.029
    if State == "Connecticut": StateSalesTaxRate = 0.0635
    if State == "Delaware": StateSalesTaxRate = 0
    if State == "Florida": StateSalesTaxRate = 0.06
    if State == "Georgia": StateSalesTaxRate = 0.04
    if State == "Guam": StateSalesTaxRate = 0.04
    if State == "Hawaii": StateSalesTaxRate = 0.04
    if State == "Idaho": StateSalesTaxRate = 0.06
    if State == "Illinois": StateSalesTaxRate = 0.0625
    if State == "Indiana": StateSalesTaxRate = 0.07
    if State == "Iowa": StateSalesTaxRate = 0.06
    if State == "Kansas": StateSalesTaxRate = 0.0615
    if State == "Kentucky": StateSalesTaxRate = 0.06
    if State == "Louisiana": StateSalesTaxRate = 0.04
    if State == "Maine": StateSalesTaxRate = 0.055
    if State == "Maryland": StateSalesTaxRate = 0.06
    if State == "Massachusetts": StateSalesTaxRate = 0.0625
    if State == "Michigan": StateSalesTexRate = 0.06
    if State == "Minnesota": StateSalesTaxRate = 0.06875
    if State == "Mississippi": StateSalesTaxRate = 0.07
    if State == "Missouri": StateSalesTaxRate = 0.04225
    if State == "Montana": StateSalesTaxRate = 0
    if State == "Nebraska": StateSalesTaxRate = 0.055
    if State == "Nevada": StateSalesTaxRate = 0.0685
    if State == "New Hampshire": StateSalesTaxRate = 0
    if State == "New Jersey": StateSalesTaxRate = 0.07
    if State == "New Mexico": StateSalesTaxRate = 0.05125
    if State == "New York": StateSalesTaxRate = 0.04
    if State == "North Carolina": StateSalesTaxRate = 0.0475
    if State == "North Dakota": StateSalesTaxRate = 0.05
    if State == "Ohio": StateSalesTaxRate = 0.0575
    if State == "Oklahoma": StateSalesTaxRate = 0.045
    if State == "Oregon": StateSalesTaxRate = 0
    if State == "Pennsylvania": StateSalesTaxRate = 0.06
    if State == "Puerto Rico": StateSalesTaxRate = 0.105
    if State == "Rhode Island": StateSalesTaxRate = 0.07
    if State == "South Carolina": StateSalesTaxRate = 0.06
    if State == "South Dakota": StateSalesTaxRate = 0.04
    if State == "Tennessee": StateSalesTaxRate = 0.07
    if State == "Texas": StateSalesTaxRate = 0.0625
    if State == "Utah": StateSalesTaxRate = 0.0595
    if State == "Vermont": StateSalesTaxRate = 0.06
    if State == "Virginia": StateSalesTaxRate = 0.053
    if State == "Washington": StateSalesTaxRate = 0.065
    if State == "West Virginia": StateSalesTaxRate = 0.06
    if State == "Wisconsin": StateSalesTaxRate = 0.05
    if State == "Wyoming": StateSalesTaxRate = 0.04
    return(UnitPrice*(1+StateSalesTaxRate))

if __name__ == '__main__': Main()

Este código calcula el costo de las compras, incluido el impuesto sobre las ventas. Por supuesto que hay formas más eficientes de hacer esto, pero es solo una ilustración.

Entonces, ¿ves algo malo con el código? ¿No? Intenta ejecutarlo. Cuando lo hace usted consigue:

100
106.0
100
105.0

¿Todavía no ves un problema? Entonces tienes un problema más grande de lo que crees. Aquí está el código equivalente renderizado en Perl:

use strict;

sub Main
{
    print GetPrice(100,"Alaska"), "\n";
    print GetPrice(100,"Florida"), "\n";
    print GetPrice(100,"Michigan"), "\n";
    print GetPrice(100,"Wisconsin"), "\n";    
}

sub GetPrice
{
    my($UnitPrice,$State) = @_;
    my $StateSalesTaxRate = 0;
    $StateSalesTaxRate = 0.04 if $State eq "Alabama";
    $StateSalesTaxRate = 0 if $State eq "Alaska";
    $StateSalesTaxRate = 0.056 if $State eq "Arizona";
    $StateSalesTaxRate = 0.065 if $State eq "Arkansas";
    $StateSalesTaxRate = 0.075 if $State eq "California";
    $StateSalesTaxRate = 0.029 if $State eq "Colorado";
    $StateSalesTaxRate = 0.0635 if $State eq "Connecticut";
    $StateSalesTaxRate = 0 if $State eq "Delaware";
    $StateSalesTaxRate = 0.06 if $State eq "Florida";
    $StateSalesTaxRate = 0.04 if $State eq "Georgia";
    $StateSalesTaxRate = 0.04 if $State eq "Guam";
    $StateSalesTaxRate = 0.04 if $State eq "Hawaii";
    $StateSalesTaxRate = 0.06 if $State eq "Idaho";
    $StateSalesTaxRate = 0.0625 if $State eq "Illinois";
    $StateSalesTaxRate = 0.07 if $State eq "Indiana";
    $StateSalesTaxRate = 0.06 if $State eq "Iowa";
    $StateSalesTaxRate = 0.0615 if $State eq "Kansas";
    $StateSalesTaxRate = 0.06 if $State eq "Kentucky";
    $StateSalesTaxRate = 0.04 if $State eq "Louisiana";
    $StateSalesTaxRate = 0.055 if $State eq "Maine";
    $StateSalesTaxRate = 0.06 if $State eq "Maryland";
    $StateSalesTaxRate = 0.0625 if $State eq "Massachusetts";
    $StateSalesTexRate = 0.06 if $State eq "Michigan";
    $StateSalesTaxRate = 0.06875 if $State eq "Minnesota";
    $StateSalesTaxRate = 0.07 if $State eq "Mississippi";
    $StateSalesTaxRate = 0.04225 if $State eq "Missouri";
    $StateSalesTaxRate = 0 if $State eq "Montana";
    $StateSalesTaxRate = 0.055 if $State eq "Nebraska";
    $StateSalesTaxRate = 0.0685 if $State eq "Nevada";
    $StateSalesTaxRate = 0 if $State eq "New Hampshire";
    $StateSalesTaxRate = 0.07 if $State eq "New Jersey";
    $StateSalesTaxRate = 0.05125 if $State eq "New Mexico";
    $StateSalesTaxRate = 0.04 if $State eq "New York";
    $StateSalesTaxRate = 0.0475 if $State eq "North Carolina";
    $StateSalesTaxRate = 0.05 if $State eq "North Dakota";
    $StateSalesTaxRate = 0.0575 if $State eq "Ohio";
    $StateSalesTaxRate = 0.045 if $State eq "Oklahoma";
    $StateSalesTaxRate = 0 if $State eq "Oregon";
    $StateSalesTaxRate = 0.06 if $State eq "Pennsylvania";
    $StateSalesTaxRate = 0.105 if $State eq "Puerto Rico";
    $StateSalesTaxRate = 0.07 if $State eq "Rhode Island";
    $StateSalesTaxRate = 0.06 if $State eq "South Carolina";
    $StateSalesTaxRate = 0.04 if $State eq "South Dakota";
    $StateSalesTaxRate = 0.07 if $State eq "Tennessee";
    $StateSalesTaxRate = 0.0625 if $State eq "Texas";
    $StateSalesTaxRate = 0.0595 if $State eq "Utah";
    $StateSalesTaxRate = 0.06 if $State eq "Vermont";
    $StateSalesTaxRate = 0.053 if $State eq "Virginia";
    $StateSalesTaxRate = 0.065 if $State eq "Washington";
    $StateSalesTaxRate = 0.06 if $State eq "West Virginia";
    $StateSalesTaxRate = 0.05 if $State eq "Wisconsin";
    $StateSalesTaxRate = 0.04 if $State eq "Wyoming";
    return($UnitPrice*(1+$StateSalesTaxRate));
}

Main();

Sin pragma estricto de Perl habilitado, incluso se obtiene la idéntica salida:

100
106.0
100
105.0

Pero con strict activado, se obtiene el siguiente mensaje de error cuando se ejecuta este script de Perl:

Global symbol "$StateSalesTexRate" requires explicit package name at line 37.
Execution aborted due to compilation errors. 

El problema en ambos ejemplos es que hay un error tipográfico en una de las líneas de cálculo. Tengo " StateSalesTexRate "en lugar de" StateSalesTaxRate " para la línea que calcula el impuesto sobre las ventas para el estado de Michigan. Perl encuentra y elimina este error explícitamente. Mientras tanto, Python gira la cabeza y mira hacia otro lado.

Esto es algo importante. Imagina esto el software está siendo utilizado por su negocio en línea para calcular cuánto carga la tarjeta de crédito de un cliente. ¿Cuánto tiempo tomará antes de darse cuenta de que los clientes de Michigan están recibiendo un pase en el impuesto sobre las ventas? Cuando lo hace, ¿vuelve al cliente y dice "Lo siento, necesitamos más dinero de usted" o se come la pérdida usted mismo?

Por supuesto, cualquier empresa que utilice este tipo de algoritmo de codificación para calcular el impuesto sobre las ventas probablemente tenga problemas más grandes. Pero usted puede ver claramente por este ejemplo lo que el strict pragma in Perl lo hace y por qué yo y otros creemos que debería ser una característica esencial de cualquier lenguaje de scripting.

Hay muchas cosas que realmente me gustan de Python. Entiendo por qué algunas personas prefieren Python a Perl. Pero hay algunas cosas que realmente detesto de Python. Esta es una.

 18
Author: Rodney Kadura,
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-12-03 16:40:56

Para ejecutar Python con advertencias activadas:

python -W all file.py

En respuesta a:

¿Hay algo que deba hacer en rutina para mis scripts python?

Creo que generalmente es una buena idea asegurarse de que su código cumple con PEP 8. Como se menciona en otra respuesta, puedes hacer esto programáticamente:

pip install pep8 && pep8 file.py
 7
Author: Jian,
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-09-25 04:03:40

Leonerd's proporciona una gran explicación de por qué no hay 'use strict' o 'use warnings' en Python.

En respuesta a:

¿Hay algo que debería estar haciendo en la rutina para mis scripts python?

Puede estar interesado en ejecutar su código a través de un analizador de código estático como pylint, y/o una comprobación de formato de código como pep8.

Pueden ayudar a encontrar problemas potenciales y marcar advertencias. También tienen mucho que decir sobre el formateo de su código, en el que puede o no estar interesado.

Aquí hay una razón decente para su uso. Y preguntas relacionadas con Stackoverflow aquí y aquí.

 5
Author: Sean,
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
2017-05-23 11:46:57

No hay realmente ningún equivalente. El diseño de Python ha evolucionado con el tiempo, y se han realizado muchos cambios (particularmente en 3.x) para asegurarse de que los valores predeterminados en el idioma son lo que un desarrollador quiere por defecto. Es muy raro que una característica exista pero sea una bandera opcional.

Esto probablemente se reduce a El Zen de Python 'Debería haber una obvious y preferiblemente sólo una obvious forma obvia de hacerlo.' El diseño de Python se centra en la legibilidad, y tiene muchas formas de hacer las cosas o cambiar la forma en que funciona el lenguaje hacen que el código sea más difícil de leer.

Lo más cercano, yo diría, son las importaciones de __future__ en versiones anteriores de Python para introducir algunas correcciones / nuevas características de las versiones más recientes en versiones anteriores (como la división que pasa de entero a división flotante por defecto). Esto es similar en el sentido de que está mejorando el comportamiento por defecto para ser más sensible en el caso estándar.

Editar: Parece que he atraído la ira de los usuarios de perl que ven este post como un ataque a Perl - nunca fue pensado como tal. Perl es un buen lenguaje, mi post original solo usaba palabras pobres y no estaba claro en su explicación. He intentado aclararlo.

 0
Author: Gareth Latty,
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-01-16 21:41:10