¿Python tiene un “uso estricto” y “uso de advertencias” como en perl?

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

Pregunta:

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

#!/usr/bin/env perl use strict; use warnings; 

¿Hay algo que debería hacer en la rutina de mis scripts de python?

Para proporcionar una respuesta que quizás evite un poco del ruido de los comentarios aquí, intentaré con otra.

Los dos pragmáticos en su pregunta original realmente se expanden a:

 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 comstackción se refiera a una variable sin declarar primero que existe (como es el valor predeterminado en más lenguajes estáticos como C, C ++ y Java). Como Python no tiene una syntax específica para declarar que existe una variable, no tiene equivalente. Asignar un nombre en Python siempre lo crea si no existió primero. Esta función de strict no tiene un equivalente de Python y la seguridad que proporciona no puede ser recreada

P.ej:

 $ perl -c -e 'use strict "vars"; $foo = 1' Global symbol "$foo" requires explicit package name at -e line 1. -e had comstacktion 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 propia variable. Python no hace esto, por lo que no necesita desactivarlo.

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 provocar un tiempo de comstackción en cualquier bash de llamar a una función que se sabe que no existe. Python no realiza ninguna comprobación de este tipo, y no tiene manera de habilitar tal característica.

P.ej:

 $ perl -c -e 'use strict "subs"; foo' Bareword "foo" not allowed while "strict subs" in use at -e line 1. -e had comstacktion errors. $ perl -c -e 'no strict "subs"; foo' -e syntax OK 
  • El efecto de las use warnings de use warnings es permitir más advertencias tanto en la comstackción como en el tiempo de ejecución de varias categorías de comportamiento que fueron predeterminadas en versiones anteriores, que a veces pueden desearse, 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 generalmente 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 a la pragmata de Perl, ya que la mayoría de los últimos tienen un scope léxico, y pueden habilitarse o inhabilitarse en pequeños ámbitos según sea necesario; dónde está __future__ de Python solo se habilita 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 un tanto artificial, pero este demuestra el uso de no warnings 'uninitialized' para deshabilitar la advertencia sobre el uso de un valor no inicializado simplemente dentro de la statement printf , mientras se mantienen las demás 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 es obligatoria o no está disponible en el idioma de Python, y no tiene use warnings . Las funciones que proporciona están habilitadas solo a nivel de archivo y no pueden habilitarse o deshabilitarse selectivamente por scope.


Edición: En realidad ahora me informaron que Python tiene algunos indicadores de advertencia controlables, que pueden habilitarse y deshabilitarse según sea necesario.

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 progtwigción serios, todavía utilizo Perl.

Sin duda, habrá devotos de Python que se ofenden con esta afirmación. He oído a algunos decir que no necesitan estricto. Encuentro que aquellos que dicen esto normalmente no saben qué es lo que te compra estrictamente. 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. Por supuesto, 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 ves un problema? Entonces tienes un problema más grande del que sabes. Aquí está el código equivalente representado 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 obtienes el mismo resultado:

 100 106.0 100 105.0 

Pero con el estricto activado, aparece el siguiente mensaje de error al ejecutar este script Perl:

 Global symbol "$StateSalesTexRate" requires explicit package name at line 37. Execution aborted due to comstacktion 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 a las ventas para el estado de Michigan. Perl encuentra y aplasta este error explícitamente. Mientras tanto, Python gira la cabeza y mira hacia otro lado.

Este es un gran problema. Imagine que su negocio en línea está utilizando este software para calcular cuánto cobra a la tarjeta de crédito de un cliente. ¿Cuánto tiempo pasará antes de que se dé cuenta de que los clientes de Michigan obtienen un impuesto sobre el impuesto a las ventas? Cuando lo hace, ¿vuelve al cliente y dice “Lo sentimos, 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 encoding para calcular el impuesto sobre las ventas probablemente tenga mayores problemas. Pero puede ver claramente en este ejemplo lo que hace el pragma estricto en Perl y por qué yo y otros creemos que debe 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.

Para ejecutar Python con las advertencias activadas:

 python -W all file.py 

En respuesta a:

¿Hay algo que debería hacer en la rutina de 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 

LeoNerd 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 de mis scripts de 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 verificació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 formato de su código, que le puede interesar o no.

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

Realmente no hay 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 lo que un desarrollador desea de forma predeterminada. Es muy raro que exista una característica, pero puede ser una marca opcional.

Esto probablemente se reduce a El Zen de Python ‘Debe haber uno, y preferiblemente solo una – manera 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 hace que el código sea más difícil de leer.

El más cercano, diría yo, es la importación de __future__ en versiones anteriores de Python para introducir algunas correcciones / nuevas características de versiones más nuevas en versiones anteriores (como la división que va de la división de enteros a flotantes de forma predeterminada). Esto es similar en el sentido de que está mejorando el comportamiento predeterminado para ser más sensible en el caso estándar.

Edit: 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 publicación original solo usaba una mala redacción y no estaba clara en su explicación. He intentado aclarar.