23 votos

Cómo diseñar el código en Python?

Vengo de Java y el aprendizaje de Python. Hasta ahora lo que he encontrado muy bien, pero a la vez muy difícil de adaptar, es que no hay necesidad de declarar los tipos. Entiendo que cada variable es un puntero a un objeto, pero de momento no soy capaz de entender cómo diseño mi código a continuación.

Por ejemplo, estoy escribiendo una función que acepta un 2D NumPy matriz. A continuación, en el cuerpo de la función que yo estoy llamando a los diferentes métodos de esta matriz (que es un objeto de array en Numpy). Pero en el futuro, supongamos que se desea utilizar esta función, por el tiempo que se me habrán olvidado totalmente lo que debería de pasar a la función como un tipo. ¿Qué hace la gente normalmente? Hacer que acaba de escribir la documentación para esto? Porque si ese es el caso, entonces, esto implica más a escribir y plantea la pregunta acerca de la idea de no declarar el tipo.

Supongamos también quiero pasar un objeto similar a una matriz en el futuro. Normalmente en Java uno de implementar una interfaz y, a continuación, deje que ambas clases para implementar los métodos. A continuación, en función de los parámetros que definen la variable del tipo de la interfaz. ¿Cómo puede se puede solucionar este problema en Python o qué enfoques pueden ser utilizados para hacer la misma idea?

32voto

uʍop ǝpısdn Puntos 16540

Esta es muy buena pregunta.

Duck typing

La primera cosa a entender acerca de python es el concepto de pato escritura:

Si camina como un pato, y grazna como un pato, entonces yo lo llamo un pato

A diferencia de Java, Python tipos nunca se declaró explícitamente. No hay ninguna restricción, ni en tiempo de compilación ni en tiempo de ejecución, en el tipo de un objeto puede asumir.

Lo que tienes que hacer es, simplemente, tratar a los objetos como si fueran de el tipo perfecto para sus necesidades. No preguntar o preguntarse acerca de su tipo. Si implementa los métodos y atributos que se desea, entonces que es eso. Se va a hacer.

def foo(duck):
    duck.walk()
    duck.quack()

El único contrato de esta función es que duck expone walk() y quack(). Un más refinado ejemplo:

def foo(sequence):
    for item in sequence:
        print item

¿Qué es sequence? Un list? Un numpy array? Un dict? Un generator? No importa. Si es iterable (es decir, puede ser utilizado en un for ... in), que sirve a su propósito.

Tipo de sugerencias

Por supuesto, nadie puede vivir en constante temor de ser objetos de un tipo incorrecto. Esto es abordado con el estilo de codificación, convenciones y una buena documentación. Por ejemplo:

  • Un nombre de variable count debe contener un número entero
  • Una variable Foo comenzar con una letra mayúscula en la celebración de una type (class)
  • Un argumento bar cuyo valor por defecto es False, debe contener una bool demasiado cuando se reemplaza

Tenga en cuenta que el duck typing concepto puede ser aplicado a estos 3 ejemplos:

  • count puede ser cualquier objeto que implementa +, -y <
  • Foo puede ser cualquier exigible que devuelve una instancia de un objeto
  • bar puede ser cualquier objeto que implementa __nonzero__

En otras palabras, el tipo nunca se define de forma explícita, pero siempre fuertemente insinuado. O más bien, las capacidades del objeto son siempre insinuada, y su tipo exacto no es relevante.

Es muy común el uso de objetos de tipo desconocido. La mayoría de los marcos exponer a los tipos que se parecen a las listas y los diccionarios, pero no lo son.

Por último, si usted realmente necesita saber, allí está la documentación. Encontrará la documentación de python inmensamente superior a la de Java. Siempre vale la pena leer.

4voto

Aaron Hall Puntos 7381

He revisado un montón de código en Python escrito en Java y .Neto de los desarrolladores, y la he visto varias veces un par de problemas que me pueden avisar/informar acerca de:

Python no es Java

No envolver todo en una clase:

Parece que incluso el más simple de la función de los vientos de estar envuelto en una clase cuando los desarrolladores de Java de empezar a escribir en Python. Python no es Java. No escribir getters y setters, que es lo que la propiedad decorador.

Tengo dos predicados antes de que yo considere clases de escritura:

  1. Estoy casando estado con la funcionalidad
  2. Espero tener varias instancias (de lo contrario un nivel de módulo dict y funciones está bien!)

No tipo de verificación todo

Python usa el pato a escribir. Consulte el modelo de datos. Su builtin tipo de coacción es tu amigo.

No lo ponemos todo en un try-excepto bloque

Sólo la captura de excepciones que usted sabe que va a obtener, mediante el uso de excepciones en todas partes para el control de flujo es computacionalmente costoso y puede ocultar los errores. Trate de usar la mayoría de excepción específica espera que usted puede conseguir. Esto conduce a un código más robusto en el largo plazo.

Aprender los tipos integrados y métodos, en particular:

A partir de los datos del modelo

str

  • join
  • just do dir(str) y aprender de todos ellos.

list

  • append (agregar un elemento al final de la lista)
  • extend (ampliar la lista con la adición de cada elemento en un iterable)

dict

  • get (proporcionar un defecto que le impide tener que coger keyerrors!)
  • setdefault (establecer el valor predeterminado o el valor ya está ahí!)
  • fromkeys (construir un diccionario con los valores predeterminados de un iterable de llaves!)

set

Los conjuntos contienen únicos (no repitition) hashable objetos (como cadenas de caracteres y números). Pensando en los diagramas de Venn? Quiero saber si un conjunto de cadenas es en un conjunto de otras cadenas, o lo que los solapamientos son (o no?)

  • union
  • intersection
  • difference
  • symmetric_difference
  • issubset
  • isdisjoint

Y acaba de hacer dir() de cada tipo que encuentras para ver los métodos y atributos en su espacio de nombres y, a continuación, hacer ayuda() en el atributo a ver qué hace!

Aprender las funciones incorporadas y de la biblioteca estándar:

Yo he cogido a los desarrolladores escribir sus propias funciones max y conjunto de objetos. Es un poco embarazoso. No deje que esto le suceda a usted!

Los módulos importantes a tener en cuenta en la Biblioteca Estándar son:

  • os
  • sys
  • collections
  • itertools
  • pprint (Yo lo uso todo el tiempo)
  • logging
  • unittest
  • re (expresiones regulares son increíblemente eficiente en el análisis de las cadenas de un montón de casos de uso)

Y leer la documentación para una breve visita de la biblioteca estándar, aquí la Parte 1 y he aquí la Parte II. Y en general, hacer rozando todos los docs un gol temprano.

Leer las Guías de Estilo:

Usted va a aprender mucho acerca de las mejores prácticas sólo mediante la lectura de sus guías de estilo! Recomiendo:

Además, usted puede aprender gran estilo por Google para el tema que usted está buscando con la frase "mejor práctica" y, a continuación, la selección de la correspondiente Stackoverflow respuestas con el mayor número de upvotes!

Le deseo suerte en su viaje de aprendizaje de Python!

2voto

Chinmay Kanchi Puntos 16353

Por ejemplo, estoy escribiendo una función que acepta un 2D Numpy matriz. A continuación, en el cuerpo de la función que yo estoy llamando a los diferentes métodos de esta matriz (que es un objeto de matriz en Numpy). Pero en el futuro, supongamos que se desea utilizar esta función, por el tiempo que yo podría olvidó por completo lo que debería pasar a la función como un tipo. ¿Qué hace la gente normalmente? Hacer que acaba de escribir una documentación para esto?

Escribir la documentación y el nombre de la función y las variables de forma adecuada.

def func(two_d_array): 
    do stuff

También supongamos que queremos en el futuro para pasar un objeto similar a una matriz, normalmente en Java uno de implementar una interfaz y, a continuación, deje que ambas clases para implementar los métodos.

Usted podría hacer esto. Crear una clase base y heredar de ella, por lo que varios tipos tienen la misma interfaz. Sin embargo, muy a menudo, esto es una exageración y que simplemente había utilizar pato escribiendo en su lugar. Con el pato de escribir, todo lo que importa es que el objeto que está siendo evaluado define el derecho propiedades y métodos que se requieren para utilizarlo dentro de su código.

Tenga en cuenta que usted puede comprobar los tipos en Python, pero esto generalmente se considera una mala práctica, porque le impide el uso de pato escritura y otros modelos de codificación habilitado por Python dinámica del tipo de sistema.

1voto

Wyzard Puntos 16284

Sí, usted debe documentar de qué tipo(s) de los argumentos de sus métodos de esperar, y es el autor de la llamada a pasar el tipo correcto de objeto. Dentro de un método, usted puede escribir el código para comprobar el tipo de cada argumento, o puede simplemente asumir que es el tipo correcto, y se basan en Python para que automáticamente se lanzará una excepción si el pasado-en el objeto no admite los métodos que el código necesita recurrir a ella.

La desventaja de tipado dinámico es que el equipo no puede hacer mucho frente comprobación de corrección, como usted señala, hay una mayor carga en el programador para asegurarse de que todos los argumentos son del tipo correcto. Pero la ventaja es que tienen mucha más flexibilidad en qué tipos se pueden pasar a sus métodos:

  • Usted puede escribir un método que admite varios tipos de objetos diferentes para un determinado argumento, sin necesidad de sobrecargas y de código duplicado.
  • A veces, un método realmente no se preocupan por el tipo exacto de un objeto, siempre que admita un método particular o de la operación - es decir, de la indización con corchetes, que trabaja en cadenas, matrices, y una variedad de otras cosas. En Java, tendrías que crear una interfaz, y escribir clases contenedoras para adaptar varios pre-existente de tipos de interfaz. En Python no es necesario hacer nada de eso.

0voto

zhangxaochen Puntos 7821

Usted puede utilizar assert a verificar si las condiciones partido:

In [218]: def foo(arg):
     ...:     assert type(arg) is np.ndarray and np.rank(arg)==2, \
     ...:         'the argument must be a 2D numpy array'
     ...:     print 'good arg'

In [219]: foo(np.arange(4).reshape((2,2)))
good arg

In [220]: foo(np.arange(4))
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-220-c0ee6e33c83d> in <module>()
----> 1 foo(np.arange(4))

<ipython-input-218-63565789690d> in foo(arg)
      1 def foo(arg):
      2     assert type(arg) is np.ndarray and np.rank(arg)==2, \
----> 3         'the argument must be a 2D numpy array'
      4     print 'good arg'

AssertionError: the argument must be a 2D numpy array

Siempre es mejor para documentar lo que has escrito completamente como @ChinmayKanchi mencionado.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X