2010-02-06 23 views
10

Generalmente, declarar variables en la asignación se considera una práctica recomendada en VBScript o JavaScript, por ejemplo, aunque está permitido.¿Cuál es la forma pitónica de declarar variables?

¿Por qué Python te obliga a crear la variable solo cuando la usas? Dado que Python es sensible a mayúsculas y minúsculas, ¿no puede causar errores porque ha escrito mal el nombre de una variable?

¿Cómo evitarías tal situación?

+3

"Por qué Python te fuerza" ... "no puede causar errores" Esta es la definición misma de "subjetivo y argumentativo". Yo voté por cerrar. – balpha

+6

@balpha considere aprender qué significan las palabras "subjetivo" y "argumentativo", ya que los ejemplos que cita son el * exactamente opuesto * de ambos. – hobbs

+0

@hobbs Estoy hablando de la definición del * motivo cercano * "subjetivo y argumentativo" (tenga en cuenta el * solo * par de comillas alrededor de ambas palabras). Es imposible responder objetivamente a esta pregunta [ejemplo 2], y la pregunta fue hecha de una manera polémica y de confrontación [ejemplo 1]. – balpha

Respuesta

9

En python, es útil pensar en declarar variables como valores vinculantes para los nombres.

Intente no escribirlos mal, o tendrá algunos nuevos (suponiendo que esté hablando de instrucciones de asignación, al hacer referencia a ellas se producirá una excepción).

Si habla de variables de instancia, no podrá usarlas después.

Por ejemplo, si usted tenía una clase myclass y en su método __init__ escribió self.myvar = 0, a continuación, tratando de hacer referencia self.myvare causará un error, en lugar de darle un valor predeterminado.

+4

+1 lo que dijiste sobre la falta de ortografía me hizo reír – lamas

+0

¿Podrías explicar por qué al hacer referencia a self.myvar causarás un error? –

+1

Hacer referencia a 'self.myvar' NO provocará un error, ya que se asigna en' init'. Hacer referencia a 'self.myvare' FUERA DE' init' (debería haber sido más explícito sobre eso) causará un error, porque no fue asignado en 'init'. – danben

5

Python nunca te fuerza a crear una variable solo cuando la usas. Siempre puede vincular None a un nombre y luego usar el nombre en otro lugar más adelante.

+3

-1 de mí, ya que no creo que realmente estés respondiendo la pregunta. Si edita para mostrar cómo esto podría evitar los problemas que preocupan a los PO, obtendré +2. –

3

Si realiza algún desarrollo serio, utilizará un entorno de desarrollo (integrado). Pylint será parte de esto y le dirá todos sus errores ortográficos. No es necesario que dicha función forme parte del idioma.

+3

Pylint ayuda. Sin embargo, el uso de Pylint o un IDE para un desarrollo serio no es un hecho. – batbrat

+0

+1 para Pylint, +0 para "No es necesario que esa característica forme parte del idioma". –

+0

Muchos buenos programadores de Python no usan un IDE, sino que optan por vim o Emacs. –

4

Para evitar una situación con los nombres de variables falta de ortografía, uso un editor de texto con una función de autocompletado y binded

python -c "import py_compile; py_compile.compile('{filename}')" 

a una función que se llamará cuando guardo un archivo.

3

Prueba.

ejemplo, con el archivo de variable.py:

#! /usr/bin/python 

somevar = 5 

Entonces, hacer archivo variable.txt (para mantener las pruebas):

>>> import variables 
>>> variables.somevar == 4 
True 

Luego hacer:

python -m doctest variable.txt 

Y conseguir:

********************************************************************** 
File "variables.txt", line 2, in variables.test 
Failed example: 
    variables.somevar == 4 
Expected: 
    True 
Got: 
    False 
********************************************************************** 
1 items had failures: 
    1 of 2 in variables.test 
***Test Failed*** 1 failures. 

Esto muestra una variable declarada incorrectamente.

Probar:

>>> import variables 
>>> variables.someothervar == 5 
True 

Tenga en cuenta que la variable no tiene el mismo nombre.

********************************************************************** 
File "variables.test", line 2, in variables.test 
Failed example: 
    variables.someothervar == 5 
Exception raised: 
    Traceback (most recent call last): 
     File "/usr/local/lib/python2.6/doctest.py", line 1241, in __run 
     compileflags, 1) in test.globs 
     File "<doctest variables.test[1]>", line 1, in <module> 
     variables.someothervar == 5 
    AttributeError: 'module' object has no attribute 'someothervar' 
********************************************************************** 
1 items had failures: 
    1 of 2 in variables.test 
***Test Failed*** 1 failures. 

Esto muestra una variable mal escrita.

>>> import variables 
>>> variables.somevar == 5 
True 

Y esto vuelve sin ningún error.

He hecho suficiente desarrollo de VBScript para saber que los errores tipográficos son un problema en el nombre de la variable, y suficiente desarrollo de VBScript para saber que Option Explicit es una muleta en el mejor de los casos. (< - 12 años de experiencia en ASP VBScript me lo enseñaron de la manera difícil)

15

Es un artefacto tonto de la inspiración de Python por "enseñanza de idiomas", y sirve para hacer que el lenguaje sea más accesible al eliminar el escollo de " declaración "enteramente". Por la razón que sea (probablemente representada como "simplicidad"), Python nunca obtuvo una restricción opcional como la "Opción explícita" de VB para introducir declaraciones obligatorias. Sí, puede ser una fuente de errores, pero como demuestran las otras respuestas aquí, los buenos codificadores pueden desarrollar hábitos que les permitan compensar casi cualquier deficiencia en el lenguaje, y según las deficiencias, esta es una muy pequeña.

+3

Espero que esta respuesta gane. Claramente, la respuesta es "No se puede hacer eso en Python, pero es menos importante de lo que crees". –

12

Si desea una clase con atributos de "abajo bloqueado" ejemplo, no es difícil de hacer uno, por ejemplo:

class LockedDown(object): 
    __locked = False 
    def __setattr__(self, name, value): 
    if self.__locked: 
     if name[:2] != '__' and name not in self.__dict__: 
     raise ValueError("Can't set attribute %r" % name) 
    object.__setattr__(self, name, value) 
    def _dolock(self): 
    self.__locked = True 

class Example(LockedDown): 
    def __init__(self): 
    self.mistakes = 0 
    self._dolock() 
    def onemore(self): 
    self.mistakes += 1 
    print self.mistakes 
    def reset(self): 
    self.mitsakes = 0 

x = Example() 
for i in range(3): x.onemore() 
x.reset() 

Como se verá, las llamadas a x.onemore funcionan bien, pero reset genera una excepción debido a la ortografía incorrecta del atributo como mitsakes. Las reglas de participación aquí son que __init__ debe establecer todos los atributos a los valores iniciales, luego llame al self._dolock() para prohibir cualquier adición adicional de atributos. Expongo los atributos "súper privados" (que comienzan con __), que estilísticamente deberían usarse muy raramente, para roles totalmente específicos, y con un alcance extremadamente limitado (por lo que es trivial detectar errores tipográficos en la inspección súper cuidadosa que se necesita) de todos modos para confirmar la necesidad de super-privacidad), pero esa es una elección estilística, fácil de revertir; de manera similar para la opción de hacer que el estado bloqueado sea "irreversible" (por medios "normales", es decir, que requieren una solución muy explícita para eludir).

Esto no se aplica a otros tipos de nombres, como los locales de función; de nuevo, no es gran cosa, porque cada función debe ser muy pequeña, y es un alcance totalmente autónomo, trivialmente fácil de inspeccionar (si escribes funciones de 100 líneas, tienes otros problemas serios ;-).

¿Vale la pena la molestia? No, porque las pruebas de unidades semi-decentes obviamente deberían detectar todos los errores tipográficos con la mayor facilidad, como un efecto colateral natural del ejercicio total de la funcionalidad de la clase. En otras palabras, no es necesario tener más pruebas de unidad solo para captar los errores tipográficos: la unidad necesita pruebas de todos modos para detectar errores semánticos triviales (uno por uno, +1 donde significa -1, etc. ., etc.) también detectará todos los errores tipográficos.

Robert Martin y Bruce Eckel tanto articulado este punto hace 7 años en artículos separados e independientes - Blog de Eckel está temporalmente fuera de este momento, pero Martín del derecho here, y cuando el sitio de Eckel revive el artículo debe ser here. La tesis es polémica (Jeff Attwood y sus comentaristas lo debaten here, por ejemplo), pero es interesante observar que Martin y Eckel son expertos bien conocidos de lenguajes estáticos como C++ y Java (aunque con relaciones amorosas, respectivamente, con Ruby y Python), y están lejos de ser los únicos que han descubierto la importancia de las pruebas unitarias ... y de cómo un buen conjunto de pruebas unitarias, como efecto colateral, hace que la rigidez de un lenguaje estático sea redundante.

Por cierto, una forma de comprobar sus suites de prueba es la "inyección de error": revise sistemáticamente la base de código introduciendo una ortografía incorrecta: ejecute las pruebas para asegurarse de que fallen, si no agregan una que falla, corrige el error de ortografía, repite. Se puede automatizar bastante bien (no la parte de "agregar una prueba", sino la búsqueda de errores potenciales que no están cubiertos por el paquete), al igual que otras formas de inyecciones de error (cambia cada entero constante, uno por uno, para uno más, y uno menos; cambie cada < a <= etc; cambie cada condición if y while a su inversa; ...), mientras que otras formas de inyección de errores requieren mucha más sabiduría humana. Desafortunadamente, no conozco las suites disponibles públicamente de marcos de inyección de errores (para cualquier idioma), podría ser un proyecto de código abierto genial ;-).

+0

otra joya de respuesta. – telliott99

+0

@telliott, gracias! -) –

+0

Error de inyección es una gran idea. Pero no estoy de acuerdo con que la utilidad obvia de las pruebas unitarias haga que la tipificación fuerte sea inútil. ¿Por qué no le pides al compilador que haga algunos controles básicos por ti, para que puedas encontrar una clase de errores (seguro, no * todos * errores) más temprano y con menos esfuerzo? Los populares lenguajes fuertemente tipados son detallados porque no son geniales para inferir tipos automáticamente, pero idiomas como OCaml y Haskell muestran que no tiene por qué ser así. –

-1

La declaración de la variable no previene errores. Más que la falta de declaración de variables causa errores.

Las declaraciones de variables previenen un tipo específico de error, pero crea otros tipos de errores.

Prevenir. Escribir código donde hay un intento de establecer (o cambiar) una variable con el tipo de datos incorrecto.

Causas. Soluciones estúpidas para forzar una serie de tipos no relacionados para que las tareas "simplemente funcionen". Ejemplo: el lenguaje C union. Además, las declaraciones variables nos obligan a usar moldes. Lo cual también nos obliga a suprimir las advertencias en los moldes en tiempo de compilación porque "sabemos" que "simplemente funcionará". Y no es así.

La falta de declaraciones de variables no causa errores. El "escenario de amenaza" más común es algún tipo de "asignación errónea" a una variable.

  1. fue la variable que se "reutilizado"? Esto es tonto pero legal y funciona.

  2. ¿Alguna parte del programa asignó incorrectamente el tipo incorrecto?

    Esto lleva a una sutil pregunta de "¿qué significa incorrecto?" En un lenguaje de pato, lo incorrecto significa "No ofrece los métodos o atributos correctos". Lo cual todavía es nebuloso. Específicamente, significa que "se le pedirá al tipo que proporcione un método o atributo que no tiene". Lo cual generará una excepción y el programa se detendrá.

La generación de una excepción no detectada en el uso de producción es molesta y muestra una falta de calidad. Es estúpido, pero también es un modo de falla detectado y conocido con un rastreo hacia la causa raíz exacta.

"no puede causar errores porque se escribió mal el nombre de una variable"

Sí. Puede.

Pero tenga en cuenta este código de Java.

public static void maine(String[] argv) { 
    int main; 
    int mian; 
} 

Un error de ortografía aquí es igualmente fatal. Java estáticamente tipeado ha hecho nada para evitar que un nombre de variable mal escrito cause un error.

+2

(1) Nadie dice que las declaraciones impiden * todos * los errores debidos a errores ortográficos. (2) El sistema de tipo half-assed de C/C++ es un truco (motivado por la eficiencia), claro, pero no pinta todos los lenguajes fuertemente tipados con ese pincel. P.ej. Java rompe su argumento "Causas". (3) ¿No cree que es mejor descubrir un error de tipo antes (en tiempo de compilación) en lugar de más tarde (en tiempo de ejecución)? (4) También me gustan los lenguajes de pato, pero eso no significa que la mecanografía fuerte no tenga ningún valor. –

+0

"no puede causar errores porque escribió mal el nombre de una variable" es defectuoso. No digo que las alternativas sean perfectas. Estoy diciendo que la suposición en la parte superior de esta pregunta es incorrecta. –

Cuestiones relacionadas