¿Python tiene un "uso estricto" y "usa advertencias" como en perl?
warnings (5)
Como otros usuarios han publicado, Python no tiene un pragma estricto. Y esto, 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, sigo usando Perl.
Sin duda habrá devotos de Python que se ofendan con esta afirmación. He oído a algunos decir que no necesitan estricta. Encuentro que aquellos que dicen esto típicamente no saben qué estricto te compra. 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 a las ventas. De acuerdo hay formas más eficientes de hacer esto, pero es solo una ilustración.
Entonces, ¿ves algo mal con el código? ¿No? Intenta ejecutarlo. Cuando lo haces obtienes:
100
106.0
100
105.0
Todavía no veo un problema? Entonces tienes un problema mayor de lo que crees. Aquí está el código equivalente presentado 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 el pragma estricto de Perl habilitado, incluso se obtiene el resultado idéntico:
100
106.0
100
105.0
Pero con el encendido estricto, aparece el siguiente mensaje de error cuando 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 el impuesto de ventas de computación en línea para el estado de Michigan. Perl encuentra y aplasta este error de forma explícita. Mientras tanto, Python gira la cabeza y mira para otro lado.
Este es un gran problema. Imagine que su negocio en línea utiliza este software para calcular cuánto carga la tarjeta de crédito de un cliente. ¿Cuánto tiempo pasará antes de que se dé cuenta de que los clientes de Michigan están obteniendo un impuesto sobre las ventas? Cuando lo haga, ¿vuelve al cliente y le dice "lo siento, necesitamos más dinero de usted" o se come la pérdida usted mismo?
Por supuesto, cualquier empresa que use este tipo de algoritmo de codificación para calcular el impuesto a las ventas probablemente tenga mayores problemas. Pero con este ejemplo puede ver claramente lo que hace el estricto pragma en Perl 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 sobre Python. Este es uno.
Estoy aprendiendo perl y python ... al mismo tiempo, no por mi diseño, pero tiene que hacerse.
Pregunta:
En una secuencia de comandos perl que uso (ver más abajo) en la parte superior de mi txt.
#!/usr/bin/env perl
use strict;
use warnings;
¿Hay algo que debería hacer en la rutina para mis scripts de Python?
LeoNerd''s proporciona una gran explicación de por qué no hay ''uso estricto'' o ''uso de advertencias'' en Python.
En respuesta a:
¿Hay algo que debería hacer en la rutina para mis scripts de Python?
Puede que esté 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 ayudarlo a encontrar problemas potenciales y a advertir advertencias. También tienen mucho que decir sobre el formato de su código, que puede o no puede interesarle.
Aquí hay una razón decente para su uso. Y preguntas relacionadas con here y here .
No hay realmente ningún equivalente. El diseño de Python ha evolucionado con el tiempo y se han realizado muchos cambios (especialmente en 3.x) para garantizar que los valores predeterminados en el idioma sean los que el desarrollador quiera de manera predeterminada. Es muy raro que una característica exista pero sea una bandera opcional.
Esto probablemente se debe a " El Zen de Python ". Debería haber una, y preferiblemente solo una, forma obvia de hacerlo. El diseño de Python se centra en la legibilidad, y tener muchas maneras de hacer las cosas o cambiar la forma en que funciona el lenguaje dificulta la lectura del código.
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 nuevas en versiones anteriores (como la división que va de la división entera a la flotante de manera predeterminada). Esto es similar en el sentido de que está mejorando el comportamiento predeterminado para ser más sensato en el caso estándar.
Editar: Parece que he atraído la ira de los usuarios de Perl que ven esta publicación como un ataque a Perl: nunca fue concebido como tal. Perl es un lenguaje excelente, mi publicación original solo usaba términos pobres y no estaba claro en su explicación. He intentado aclarar
Para ejecutar Python con advertencias activadas:
python -W all file.py
En respuesta a:
¿Hay algo que debería hacer en la rutina para mis scripts de Python?
Creo que generalmente es una buena idea asegurarse de que su código cumpla con PEP 8 . Como se alude en otra respuesta, puede hacer esto programáticamente:
pip install pep8 && pep8 file.py
Para proporcionar una respuesta que quizás evite un poco del ruido de comentarios aquí, intentaré con otro.
Los dos pragmas en su pregunta original realmente se expanden a:
use strict "vars";
use strict "refs";
use strict "subs";
use warnings;
Para responder cada uno a su vez:
- El efecto de
use strict "vars"
es causar un error en tiempo de compilación para referirse a una variable sin declarar primero que existe (como es el predeterminado en más lenguajes estáticos como C, C ++ y Java). Como Python no tiene una sintaxis específica para declarar que existe una variable, no tiene equivalente. Asignar un nombre en Python siempre lo crea si no existía primero. Esta característica destrict
no tiene equivalente de Python y la seguridad que proporciona no se puede recrear.
P.ej:
$ 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 del
use strict "refs"
es no permitir el uso de strings simples que contengan el nombre de una variable (existente o nueva) como referencia a la variable misma. Python no hace esto, así que no necesita deshabilitarlo.
P.ej:
$ 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 causar un tiempo de compilación en cualquier intento de invocar una función que se sabe que no existe. Python no realiza ninguna comprobación de este tipo, y no tiene forma de habilitar dicha función.
P.ej:
$ 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 las
use warnings
deuse warnings
es habilitar más advertencias tanto en compilación como en tiempo de ejecución de varias categorías de comportamiento que eran predeterminadas en versiones anteriores, pueden desearse a veces o que nunca han sido una buena idea, pero no son estrictamente un error. Por ejemplo, el uso de valores no inicializados como números debería dar una advertencia, pero originalmente no lo hizo.
P.ej:
$ 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 alcance léxico, y pueden habilitarse o deshabilitarse en ámbitos pequeños según se requiera; dónde está el __future__
de Python solo habilitado para un archivo fuente completo.
P.ej.
use strict;
use warnings;
my $total;
$total += count_things($_) for @list;
{
no warnings ''uninitialized'';
printf "The total is %d/n", $total;
}
Un ejemplo algo artificial, pero este demuestra el uso de no warnings ''uninitialized''
para desactivar la advertencia sobre el uso de un valor no inicializado simplemente dentro de la instrucción printf
, manteniendo las otras advertencias habilitadas en cualquier otro lugar.
En resumen, entonces: 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 tienen use warnings
. Esas funciones que proporciona se habilitan solo en el nivel de archivo y no se pueden habilitar o deshabilitar selectivamente por alcance.
Editar: En realidad, ahora me han informado que Python tiene algunos indicadores de advertencia controlables, que pueden habilitarse y deshabilitarse según sea necesario.