2010-09-13 6 views

Respuesta

2

Yo diría que el número uno está tratando de escribir código estáticamente tipado en un lenguaje dinámico.

no dude en utilizar un identificador para apuntar a una cadena y luego una lista de secciones independientes de código

keys = 'foo bar foobar' # Imagine this coming in as an argument 
keys = keys.split() # Now the semantically chose name for the argument can be 
        # reused As the semantically chosen name for a local variable 

no dude en tratar funciones como valores normales: son. Toma el siguiente analizador Supongamos que queremos tratar todas las etiquetas de encabezado por igual y las etiquetas ul como las etiquetas ol.

class Parser(HTMLParser): 
    def __init__(self, html): 
     self.feed(html) 

    def handle_starttag(self, tag, attrs): 
     parse_method = 'parse_' + tag  
     if hasattr(self, parse_method): 
      getattr(self, parse_method)(attrs) 


    def parse_list(self, attrs): 
     # generic code 

    def parse_header(self, attrs): 
     # more generic code 

    parse_h1 = parse_h2 = parse_h3 = parse_h4 = parse_h5 = parse_h6 = parse_header 
    parse_ol = parse_ul = parse_list 

Esto podría hacerse mediante el uso de código de menos genérico en el método handle_starttag en un lenguaje como Java llevando un registro de qué etiquetas mapa para el mismo método pero si luego decide que desea manejar etiquetas div, se tiene que agregar eso en la lógica de despacho. Aquí solo agrega el método parse_div y listo.

No tipear! ¡Tipo de pato!

def funtion(arg): 
    if hasattr(arg, 'attr1') and hasattr(arg, 'attr2'): 
     foo(arg): 
    else: 
     raise TypeError("arg must have 'attr1' and 'attr2'") 

a diferencia del isinstance(arg, Foo). Esto le permite pasar cualquier objeto con attr1 y attr2. Esto le permite, por ejemplo, pasar una clase de seguimiento envuelta alrededor de un objeto para fines de depuración. Tendría que modificar la clase para hacer eso en Java AFAIK.

Como lo señala THC4k, otra forma (más pitonica) de hacer esto es la expresión EAPF. No me gusta esto porque me gusta detectar errores tan pronto como sea posible. Sin embargo, es más eficiente si esperas que el código rara vez falle. No le digas a nadie que no me gusta, aunque nuestros dejarán de pensar que sé cómo escribir Python. Aquí hay un ejemplo cortesía de THC4k.

try: 
    foo(arg): 
except (AttributeError, TypeError): 
    raise InvalidArgumentError(foo, arg) 

Es un volado que si debemos coger el AttributeError y TypeError o simplemente dejar que se propagan a alguna parte que sabe cómo manejar ellos, pero esto es sólo un ejemplo así que vamos a dejarlo volar.

+0

@ THC4k. ¿Cómo se dice que es extraño? A menos que 'type (Foo)' sea una subclase de 'type' que sobrepase el atributo' __instancecheck__', 'isinstance' depende de la ubicación en las jerarquías de clase. La forma en que presenté no comparte esta deficiencia. LBYL vs EAFP es otro problema. Olvidé incluir el otro estilo. – aaronasterling

+0

'if hasattr (arg, 'attr1') y hasattr (arg, 'attr2')' es una verificación de tipo. Comprueba si arg pertenece a la clase de tipos (implícita) de "cosas que tienen un atributo attr1 y attr2". Ese * es * más general que el uso de 'isinstance', que solo busca un tipo único, no una clase de tipo completa. Pero esos controles a menudo son innecesarios: simplemente haga foo (arg) de inmediato, vea qué sucede y capture Excepciones donde tenga sentido. Deje que Python le haga todas las comprobaciones de tipos - si foo (arg) no tiene sentido, arrojará una excepción eventualmente. –

+0

@aaronasterling lo siento, sí mala redacción, estaba reescribiendo el comentario. –

3

"Is the only solution to write tests for each method?"

¿Está usted diciendo no pruebas de escritura para cada método en Java?

Si escribió pruebas para cada método en Java, entonces, bueno, nada cambia, ¿verdad?

renaming a method, seems so risky!

Correcto. No lo hagas

adding/removing parameters seems so risky!

¿Qué? ¿Estás hablando de parámetros opcionales? Si es así, tener varios nombres sobrecargados en Java parece arriesgado y confuso. Tener parámetros opcionales parece más simple.


Si busca en SO las preguntas más comunes de Python, encontrará que algunas cosas son crónicas.

  • Cómo actualizar el PYTHONPATH.

  • Por qué un cálculo aleatorio de coma flotante no es lo mismo que una abstracción matemática puede indicar.

  • Usando Python 3 y escribiendo el código de un tutorial de Python 2.

  • Por qué Python no tiene declaraciones supercomplejas protected, private y public.

  • Por qué Python no tiene un tipo de enumeración.

El problema crónico # 1 parece estar utilizando objetos mutables como valores predeterminados para una función. Simplemente evita esto.

+2

Por mi parte, rara vez era necesario meterse con PYTHONPATH. Y el n. ° 3 es un problema independiente del lenguaje con flotantes, cada uno (no importa si Java o C# o ... o incluso Scheme) el programador digno de su sal lo sabrá. De lo contrario, de acuerdo. – delnan

+3

@delnan: No debe meterse con eso, pero hay una sorprendente cantidad de preguntas sobre ese tema. Además, el problema del flotador debe ser conocido. Sin embargo ... Sorprendentemente ... SO está lleno de preguntas "2.1 + 3.2! = 5.3". –

+3

De acuerdo, algunas personas no obtienen rutas de búsqueda de importación y números en coma flotante, pero ¿esto es porque provienen de un lenguaje estático? Lo más probable es que los puntos flotantes no funcionen igual en todos los idiomas, y al menos Java parece tener algo similar a 'PYTHONPATH',' CLASSPATH' (corrígeme si estoy equivocado, no soy Java). – delnan

2

Algunas cosas que me llamaron la atención cuando se trata de la primera salida de Python (que viene de un fondo principalmente de Java):

  1. Escribir Pythonic código. Utilice las expresiones idiomáticas recomendadas para Python, en lugar de hacerlo de la manera anterior de Java/C. Esto es más que solo un problema cosmético o dogmático. El código pitónico es realmente mucho más rápido en la práctica que el código tipo C prácticamente todo el tiempo. De hecho, en mi humilde opinión, gran parte de la noción de "Python es lento" se debe al hecho de que codificadores inexpertos intentaron codificar Java/C en Python y terminaron teniendo un gran impacto de rendimiento y se les ocurrió la idea de que Python es terriblemente lento Utilice las listas de comprensión y mapa/filtro/reducir siempre que sea posible.

  2. Póngase cómodo con la idea de que las funciones son realmente objetos. Páselos como devoluciones de llamada, haga que las funciones devuelvan funciones, conozca los cierres, etc.

  3. Hay muchas cosas geniales y casi mágicas que puedes hacer en Python como renombrar métodos como mencionas. Estas cosas son geniales para mostrar las características de Python, pero realmente no son necesarias si no las necesitas. De hecho, como señaló S. Lott, es mejor evitar cosas que parecen riesgosas.

+1

Python ** es ** más lento. Órdenes de magnitud más lenta. Pero no importa. En parte porque el código idiomático no es * que * lento, en parte porque no hacemos Raytracers en Python.Además, las cosas interesantes que hacen que el lenguaje sea tan lento también compensan por completo la pérdida de rendimiento. – delnan

+0

@delnan. He visto itertools batir el código C puro en 20 segundos más o menos en una tarea de ochenta minutos;) – aaronasterling

+1

@aaronasterling: ¿No es itertools una biblioteca C? (Podría estar equivocado) – Daenyth

Cuestiones relacionadas