En el siguiente articulo se mostrará la guía de estilos que debe seguir un programador de Python, nos servirá para escribir código claro y comprensible para otros programadores, ya que se ha establecido como estándar. Esta guía de estilos fue escrita por el guru Guido van Rossum, el cual es el creador de este lenguaje tan utilizado hoy en día.
PEP: | 8 |
Titulo: | Guía de estilos para el código de Python |
Autor: | Guido van Rossum <guido en python.org> |
Estatus: | Activo |
Tipo: | Proceso |
Creado: | 05-Julio-2001 |
Post-Historico: | 05-Julio-2001, 01-Agosto-2013 |
Introducción
Este documento proporciona convenciones de codificación para el código de Python que comprende la biblioteca estándar en la distribución principal de Python. Consulte el PEP (Python Enhancement Proposals, Propuesta de mejora de Python) informativo complementario que describe las pautas de estilo para el código C en la implementación en C de Python.
Este documento y PEP 257 (Convenciones de Docstring) fueron adaptados del ensayo original de Estilos de Guido, con algunas adiciones de la guía de estilos de Barry.
Esta guía de estilos evoluciona con el tiempo a medida que se identifican convenciones adicionales y las convenciones pasadas se vuelven obsoletas por los cambios en el idioma mismo.
Muchos proyectos tienen sus propias pautas de estilos de codificación. En caso de cualquier conflicto, dichas guías especificas del proyecto tendrán prioridad para ese proyecto.
Una consistencia tonta en el Hobgoblin de Little Minds
Una de las ideas claves de Guido es que el código se lee mucho más a menudo que lo que está escrito. Las directrices que se proporcionan aquí están destinadas a mejorar la legibilidad del código y hacerlo coherente en todo el amplio espectro del código Python. Como dice PEP 20, “La legibilidad cuenta”.
Una guía de estilos es sobre la consistencia. La coherencia con esta guía de estilos es importante. La consistencia dentro de un proyecto es más importante. La consistencia dentro de un módulo o función es lo más importante.
Sin embargo, sepa cuándo ser inconsistente, a veces las recomendaciones de la guía de estilos no son aplicadas. En caso de duda, utiliza tu mejor juicio. Mira otros ejemplos y decide qué se ve mejor. ¡Y no dudes en preguntar!.
En particular: ¡no rompa la compatibilidad hacia atrás solo para cumplir con este PEP!.
Algunas otras buenas razones para ignorar una guía en particular:
- Al aplicar la guía, el código seria menos legible, incluso para alguien que esté acostumbrado a leer el código que sigue a este PEP.
- Para ser coherente con el código circundante que también lo rompe (quizás por razones históricas), aunque esta también es una oportunidad para limpiar el desorden de otra persona (en el verdadero estilo XP).
- Debido a que el código en cuestión es anterior a la introducción de la guía y no hay razón para modificar ese código.
- Cuando el código debe seguir siendo compatible con versiones anteriores de Python que no son compatibles con la función recomendada por la guía de estilos.
Disposición del Código
Indentación
Usar 4 espacios por nivel de indentación.
Las líneas de continuación deben alinear los elementos ajustados ya sea verticalmente utilizando la línea implícita de Python que se une entre paréntesis, corchetes y llaves, o utilizando una indentación. Al usar una indentación se debe considerar lo siguiente; no debe haber argumentos en la primera línea y se debe utilizar una indentación adicional para distinguirse claramente como una línea de continuación.
SI:
# Alineado con delimitador de apertura.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Agregue 4 espacios (un nivel adicional de indentación) para distinguir los argumentos del resto.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# Las indentaciones colgantes deben agregar un nivel.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
NO:
# Argumentos en primera línea están prohibidos cuando no se usa alineación vertical.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Se requiere una indentación adicional ya que la indentación no es distinguible.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
La regla de 4 espacios es opcional para las líneas de continuación.
Opcional:
# Las indentaciones colgantes *pueden* estar sangradas en otros 4 espacios.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
Cuando la parte condicional de una sentencia if es lo suficientemente larga como para requerir que se escriba en varias líneas, vale la pena señalar que la combinación de una palabra clave de dos caracteres (es decir, if), más un espacio sencillo, más un paréntesis de apertura crea un espacio natural. Indentar 4 espacios para las siguientes líneas del condicional multilínea. Esto puede producir un conflicto visual con el conjunto de código indentado anidado dentro de la sentencia if, que también se indentaría naturalmente en 4 espacios. Este PEP no toma una posición explícita sobre cómo (o si) distinguir más visualmente dichas líneas condicionales de la serie anidada dentro de la declaración if. Las opciones aceptables en esta situación incluyen, pero no se limitan a:
# No indentación extra.
if (this_is_one_thing and
that_is_another_thing):
do_something()
# Agrega un comentario, que proporcionará alguna distinción en los editores.
# Soporte de resaltado de sintaxis.
if (this_is_one_thing and
that_is_another_thing):
# Dado que ambas condiciones son ciertas, hacer.
do_something()
# Agregue un poco de indentación adicional en la línea de continuación condicional.
if (this_is_one_thing
and that_is_another_thing):
do_something()
(Consulte también la discusión sobre si se debe romper antes o después de los operadores binarios a continuación).
El corchete/paréntesis/paréntesis de cierre en construcciones de varias líneas puede alinearse bajo el primer carácter que no sea un espacio en blanco de la última línea de la lista, como en:
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
o puede alinearse debajo del primer carácter de la línea que comienza la construcción multilínea, como en:
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
¿Tabulador o Espacios?
Los espacios son el método de indentado preferido.
El tabulador se debe usar únicamente para mantener la coherencia con el código que ya está indentado con tabulación.
Python 3 no permite mezclar el uso de tabulador y espacios para la indentación.
El código de Python 2 indentado con una combinación de tabulaciones y espacios se debe convertir para usar espacios exclusivamente.
Cuando se invoca al intérprete de línea de comandos de Python 2 con la opción -t, emite advertencias sobre el código que mezcla ilegalmente tabulaciones y espacios. Al usar -tt estas advertencias se convierten en errores. Estas opciones son muy recomendables!.
Longitud máxima de líneas
Limitar todas las líneas a un máximo de 79 caracteres.
Para bloques largos de texto que fluyen con menos restricciones estructurales (cadenas de documentación o comentarios), la longitud de la línea debe limitarse a 72 caracteres.
Limitar el ancho de la ventana del editor requerido permite tener varios archivos abiertos lado a lado, y funciona bien cuando se usan herramientas de revisión de código que presentan las dos versiones en columnas adyacentes.
El ajuste predeterminado en la mayoría de las herramientas interrumpe la estructura visual del código, lo que hace que sea más difícil de entender. Los límites se eligen para evitar el ajuste en los editores con el ancho de la ventana establecido en 80, incluso si la herramienta coloca un glifo marcador en la columna final al ajustar las líneas. Es posible que algunas herramientas basadas en la web no ofrezcan el ajuste dinámico de líneas.
La biblioteca estándar de Python es conservadora y requiere limitar las líneas a 79 caracteres (y las cadenas de documentación/comentarios a 72).
La forma preferida de ajustar líneas largas es mediante el uso de la continuación de línea implícita de Python entre paréntesis, corchetes y llaves. Las líneas largas se pueden dividir en varias líneas envolviendo expresiones entre paréntesis. Estos se deben usar en lugar de usar una barra invertida para la continuación de la línea.
Las barras invertidas pueden ser apropiadas a veces. Por ejemplo, las declaraciones largas y múltiples no pueden usar la continuación implícita, por lo que las barras invertidas son aceptables:
with open('/path/to/some/file/you/want/to/read') as file_1, \
open('/path/to/some/file/being/written', 'w') as file_2:
file_2.write(file_1.read())
Asegúrese de indentar la línea continua adecuadamente.
¿Debería un salto de línea antes o después de un operador binario?
Durante décadas, el estilo recomendado fue romper después de los operadores binarios. Pero esto puede afectar la legibilidad de dos maneras: los operadores tienden a dispersarse en diferentes columnas en la pantalla, y cada operador se aleja de su operando y pasa a la línea anterior. Aquí, el ojo tiene que hacer un trabajo extra para indicar qué elementos se agregan y cuáles se restan:
# No: Los operadores se sientan lejos de sus operandos.
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
Para resolver este problema de legibilidad, los matemáticos y sus editores siguen la convención opuesta. Donald Knuth explica la regla tradicional en su serie Computadoras y composición tipográfica: “Aunque las fórmulas dentro de un párrafo siempre se rompen después de las operaciones y relaciones binarias, las fórmulas mostradas siempre se rompen antes de las operaciones binarias”.
Siguiendo la tradición de las matemáticas, generalmente se obtiene un código más legible:
# SI: Operadores fáciles de unir con operandos
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
En el código Python, está permitido romper antes o después de un operador binario, siempre que la convención sea coherente a nivel local. Para el nuevo código se sugiere el estilo de Knuth.
Líneas en blanco
Rodee las definiciones de funciones y clases de nivel superior con dos líneas en blanco.
Las definiciones de métodos dentro de una clase están rodeadas por una sola línea en blanco.
Se pueden usar líneas en blanco adicionales (con moderación) para separar grupos de funciones relacionadas. Las líneas en blanco se pueden omitir entre un grupo de líneas relacionadas (por ejemplo, un conjunto de implementaciones ficticias).
Use líneas en blanco en las funciones, con moderación, para indicar secciones lógicas.
Python acepta el carácter de fuente de información de control-L (es decir, ^ L) como espacios en blanco; Muchas herramientas tratan estos caracteres como separadores de página, por lo que puede usarlos para separar páginas de secciones relacionadas de su archivo. Tenga en cuenta que es posible que algunos editores y visores de código basados en la web no reconozcan control-L como una fuente de formulario y muestren otro glifo en su lugar.
Codificación del archivo fuente
El código en la distribución central de Python siempre debe usar UTF-8 (o ASCII en Python 2).
Los archivos que usan ASCII (en Python 2) o UTF-8 (en Python 3) no deben tener una declaración de codificación.
En la biblioteca estándar, las codificaciones no predeterminadas se deben usar solo para propósitos de prueba o cuando un comentario o cadena de documentos necesite mencionar un nombre de autor que contenga caracteres que no sean ASCII; de lo contrario, el uso de escapes \x, \u, \U o \N es la forma preferida de incluir datos no ASCII en literales de cadena.
Para Python 3.0 y posteriores, la siguiente política se prescribe para la biblioteca estándar (ver PEP 3131): Todos los identificadores en la biblioteca estándar de Python DEBEN usar identificadores solo ASCII, y DEBERÍAN usar palabras en inglés siempre que sea posible (en muchos casos, abreviaturas y se usan términos que no son en inglés). Además, los literales de cadena y los comentarios también deben estar en ASCII. Las únicas excepciones son casos de prueba que prueban las características que no son ASCII y los nombres de los autores. Los autores cuyos nombres no se basan en el alfabeto latino (latin-1, ISO/IEC 8859-1 juego de caracteres) DEBEN proporcionar una transliteración de sus nombres en este juego de caracteres.
Se recomienda a los proyectos de código abierto con una audiencia global que adopten una política similar.
Importaciones
- Las importaciones deben estar generalmente en líneas separadas:
Yes: import os
import sys
No: import sys, os
Está bien decir esto sin embargo:
from subprocess import Popen, PIPE
- Las importaciones siempre se colocan en la parte superior del archivo, justo después de los comentarios y las cadenas de documentación del módulo, y antes de las globales y constantes del módulo.
Las importaciones deben agruparse en el siguiente orden:
- Biblioteca estándar de Python
- Importaciones de terceros
- Importaciones especificas de aplicaciones/bibliotecas locales.
Debe poner una línea en blanco entre cada grupo de importaciones.
Se recomiendan las importaciones absolutas, ya que generalmente son más legibles y tienden a comportarse mejor (o al menos dan mejores mensajes de error) si el sistema de importación está configurado incorrectamente (como cuando un directorio dentro de un paquete termina en sys.path):
import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example
Sin embargo, las importaciones relativas explícitas son una alternativa aceptable a las importaciones absolutas, especialmente cuando se trata de diseños de paquetes complejos donde el uso de importaciones absolutas sería innecesariamente detallado:
from . import sibling
from .sibling import example
El código de la biblioteca estándar debe evitar diseños complejos de paquetes y siempre usar importaciones absolutas.
Las importaciones relativas implícitas nunca deben usarse y se han eliminado en Python 3.
- Cuando se importa una clase desde un módulo que contiene una clase, generalmente está bien deletrear esto:
from myclass import MyClass
from foo.bar.yourclass import YourClass
Si esta ortografía causa conflictos de nombres locales, escríbalos explícitamente:
import myclass
import foo.bar.yourclass
Deben evitarse las importaciones con comodines (from <módulo> import *), ya que no dejan claro qué nombres están presentes en el espacio de nombres, lo que confunde tanto a los lectores como a muchas herramientas automatizadas. Hay un caso de uso defendible para una importación de comodín, que es volver a publicar una interfaz interna como parte de una API pública (por ejemplo, sobrescribir una implementación Python pura de una interfaz con las definiciones de un módulo acelerador opcional y exactamente qué definiciones se aplicarán). sobrescrito no se conoce de antemano).
Cuando se vuelven a publicar los nombres de esta manera, las pautas a continuación con respecto a las interfaces públicas e internas aún se aplican.
Nivel de módulo de nombres “Dunder”
Los “dunders” del nivel del módulo (es decir, nombres con dos guiones bajos iniciales y dos finales) como __all__, __author__, __version__, etc. deben colocarse después de la cadena de documentación del módulo pero antes de cualquier declaración de importación excepto de from __future__ import. Python ordena que las futuras importaciones deben aparecer en el módulo antes de cualquier otro código, excepto las cadenas de documentación:
"""Este es el módulo de ejemplo..
Este modulo hace cosas.
"""
from __future__ import barry_as_FLUFL
__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'
import os
import sys
Citas de cadena
En Python, las cadenas entre comillas simples y las cadenas entre comillas dobles son iguales. Este PEP no hace una recomendación para esto. Elige una regla y apégate a ella. Sin embargo, cuando una cadena contiene caracteres de comillas simples o dobles, use la otra para evitar las barras invertidas en la cadena. Mejora la legibilidad.
Para cadenas de comillas triples, siempre use caracteres de comillas dobles para ser coherente con la convención docstring en PEP 257.
Espacio en blanco en expresiones y declaraciones
Evite los espacios en blanco extraños en las siguientes situaciones:
- Inmediatamente dentro de paréntesis, corchetes o tirantes.
SI: spam(ham[1], {eggs: 2})
No: spam( ham[ 1 ], { eggs: 2 } )
- Entre una coma final y un paréntesis de cierre siguiente.
SI: foo = (0,)
No: bar = (0, )
- Inmediatamente antes de una coma, punto y coma o dos puntos:
SI: if x == 4: print x, y; x, y = y, x
No: if x == 4 : print x , y ; x , y = y , x
- Sin embargo, en una trozo, los dos puntos actúan como un operador binario, y deben tener cantidades iguales en cada lado (tratándolo como el operador con la prioridad más baja). En una trozo extendida, ambos dos puntos deben tener la misma cantidad de espacio aplicado. Excepción: cuando se omite un parámetro de segmento, se omite el espacio.
SI:
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]
No:
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]
- Inmediatamente antes del paréntesis abierto que inicia la lista de argumentos de una llamada de función:
SI: spam(1)
No: spam (1)
- Inmediatamente antes del paréntesis abierto que comienza una indexación o trozo:
SI: dct['key'] = lst[index]
No: dct ['key'] = lst [index]
- Más de un espacio alrededor de un operador de asignación (u otro) para alinearlo con otro.
SI:
x = 1
y = 2
long_variable = 3
No:
x = 1
y = 2
long_variable = 3
Otras Recomendaciones
- Evita los espacios en blanco al final. Debido a que generalmente es invisible, puede ser confuso: por ejemplo, una barra invertida seguida de un espacio y una nueva línea no cuenta como un marcador de continuación de línea. Algunos editores no lo conservan y muchos proyectos (como el propio CPython) tienen enlaces de confirmación previa que lo rechazan.
- Rodear siempre estos operadores binarios con un solo espacio en cada lado: asignación (=), asignación aumentada (+ =, – = etc.), comparaciones (==, <,>,! =, <>, <=,> = , in, not in, is, is not, Booleanos (and, or, not).
- Si se utilizan operadores con diferentes prioridades, considere agregar espacios en blanco alrededor de los operadores con las prioridades más bajas. Usa tu propio juicio; sin embargo, nunca use más de un espacio, y siempre tenga la misma cantidad de espacios en blanco en ambos lados de un operador binario.
SI:
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
No:
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
- Las anotaciones de funciones deben usar las reglas normales para los dos puntos y siempre tienen espacios alrededor de la flecha -> si están presentes.
SI:
def munge(input: AnyStr): ...
def munge() -> AnyStr: ...
No:
def munge(input:AnyStr): ...
def munge()->PosInt: ...
- No use espacios alrededor del signo = cuando se usa para indicar un argumento de palabra clave, o cuando se usa para indicar un valor predeterminado para un parámetro de función no anotado.
SI:
def complex(real, imag=0.0):
return magic(r=real, i=imag)
No:
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
Sin embargo, al combinar una anotación de argumento con un valor predeterminado, use espacios alrededor del signo =:
SI:
def munge(sep: AnyStr = None): ... def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
No:
def munge(input: AnyStr=None): ... def munge(input: AnyStr, limit = 1000): ...
- Las declaraciones compuestas (declaraciones múltiples en la misma línea) generalmente no se recomiendan.
SI:
if foo == 'blah': do_blah_thing() do_one() do_two() do_three()
Más bien no:
if foo == 'blah': do_blah_thing() do_one(); do_two(); do_three()
- Aunque a veces está bien poner un if/for/while con un cuerpo pequeño en la misma línea, nunca haga esto para las declaraciones de varias cláusulas. ¡También evita doblar líneas tan largas!
Más bien no:
if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t < 10: t = delay()
Definitivamente no:
if foo == 'blah': do_blah_thing()
else: do_non_blah_thing()
try: something()
finally: cleanup()
do_one(); do_two(); do_three(long, argument,
list, like, this)
if foo == 'blah': one(); two(); three()
Cuándo usar comas al final
Las comas finales son generalmente opcionales, excepto que son obligatorias al hacer una tupla de un elemento (y en Python 2 tienen semántica para la declaración impresa). Para mayor claridad, se recomienda rodear este último entre paréntesis (técnicamente redundantes).
SI:
FILES = ('setup.cfg',)
OK, pero confuso:
FILES = 'setup.cfg',
Cuando las comas finales son redundantes, a menudo son útiles cuando se usa un sistema de control de versiones, cuando se espera que una lista de valores, argumentos o elementos importados se extienda a lo largo del tiempo. El patrón es colocar cada valor (etc.) en una línea por sí mismo, siempre agregando una coma al final, y agregando el paréntesis/corchete/corchete en la siguiente línea. Sin embargo, no tiene sentido tener una coma al final en la misma línea que el delimitador de cierre (excepto en el caso anterior de tuplas singleton).
SI:
FILES = [
'setup.cfg',
'tox.ini',
]
initialize(FILES,
error=True,
)
No:
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)
Comentarios
Los comentarios que contradicen el código son peores que ningún comentario. ¡Siempre haga una prioridad de mantener los comentarios actualizados cuando cambie el código!
Los comentarios deben ser oraciones completas. La primera palabra debe estar en mayúsculas, a menos que sea un identificador que comience con una letra minúscula (¡nunca altere el caso de los identificadores!).
Los comentarios en bloque generalmente consisten en uno o más párrafos construidos a partir de oraciones completas, y cada oración termina en un punto.
Debe usar dos espacios después de un período de finalización de la oración en los comentarios de varias oraciones, excepto después de la oración final.
Cuando escribas inglés, sigue Strunk y White.
Codificadores de Python de países que no hablan inglés: escriba sus comentarios en inglés, a menos que esté 120% seguro de que las personas que no hablan su idioma nunca leerán el código.
Bloque de comentarios
Los comentarios en bloque generalmente se aplican a algunos (o todos) códigos que los siguen, y están indentados al mismo nivel que ese código. Cada línea de un comentario de bloque comienza con un # y un solo espacio (a menos que sea un texto indentado dentro del comentario).
Los párrafos dentro de un comentario de bloque están separados por una línea que contiene un solo #.
Comentarios en línea
Utilice los comentarios en línea con moderación.
Un comentario en línea es un comentario en la misma línea que una declaración. Los comentarios en línea deben estar separados por al menos dos espacios de la declaración. Deben comenzar con un # y un solo espacio.
Los comentarios en línea son innecesarios y, de hecho, distraen si establecen lo obvio. No hagas esto:
x = x + 1 # Increment x
Pero a veces, esto es útil:
x = x + 1 # Compensate for border
Cadenas de documentación
Las convenciones para escribir buenas cadenas de documentación (a.k.a. “docstrings”) están inmortalizadas en PEP 257.
- Escribe cadenas de documentación para todos los módulos, funciones, clases y métodos públicos. Las cadenas de documentación no son necesarias para los métodos no públicos, pero debe tener un comentario que describa lo que hace el método. Este comentario debería aparecer después de la línea de definición.
- PEP 257 describe buenas convenciones de docstring. Tenga en cuenta que lo más importante es que la “” “que termina una cadena de documentos multilínea debe estar sola en una línea:
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
- Para las cadenas de documentación de un forro, mantenga el “” “de cierre en la misma línea.
Convenciones de nombres
Las convenciones de nomenclatura de la biblioteca de Python son un poco complicadas, por lo que nunca obtendremos esto completamente consistente; sin embargo, aquí están los estándares de denominación recomendados actualmente. Los nuevos módulos y paquetes (incluidos los marcos de terceros) deben escribirse según estos estándares, pero cuando una biblioteca existente tiene un estilo diferente, se prefiere la consistencia interna.
Principio primordial
Los nombres que son visibles para el usuario como partes públicas de la API deben seguir las convenciones que reflejan el uso en lugar de la implementación.
Descriptivo: Estilos de nombres
Hay muchos estilos diferentes de nombres. Es útil poder reconocer qué estilo de denominación se está utilizando, independientemente de para qué se usan.
Los siguientes estilos de denominación se distinguen comúnmente:
- b (letra minúscula)
- B (letra mayúscula única)
- lowercase
- lower_case_with_underscores
- UPPERCASE
- UPPER_CASE_WITH_UNDERSCORES
- CapitalizedWords (o CapWords, o CamelCase), así llamado debido a la apariencia irregular de sus letras). Esto también se conoce a veces como StudlyCaps.
- mixedCase (se diferencia de CapitalizedWords por el carácter inicial en minúscula)
- Capitalized_Words_With_Underscores (feo!)
También existe el estilo de usar un prefijo único corto para agrupar nombres relacionados. Esto no se usa mucho en Python, pero se menciona para completar. Por ejemplo, la función os.stat () devuelve una tupla cuyos elementos tradicionalmente tienen nombres como st_mode, st_size, st_mtime y así sucesivamente. (Esto se hace para enfatizar la correspondencia con los campos de la estructura de llamadas del sistema POSIX, lo que ayuda a los programadores familiarizados con eso).
La biblioteca X11 utiliza una X inicial para todas sus funciones públicas. En Python, este estilo generalmente se considera innecesario porque los nombres de atributos y métodos tienen un prefijo con un objeto, y los nombres de funciones tienen un prefijo con un nombre de módulo.
Además, se reconocen los siguientes formularios especiales que usan guiones bajos iniciales o finales (estos generalmente se pueden combinar con cualquier convención de caso):
- _single_leading_underscore: indicador débil de “uso interno”. P.ej. from M import * no importa objetos cuyo nombre comience por un guión bajo.
- single_trailing_underscore_: utilizado por la convención para evitar conflictos con la palabra clave Python, por ejemplo.
Tkinter.Toplevel(master, class_='ClassName')
- __double_leading_underscore: al nombrar un atributo de clase, invoca la manipulación de nombres (dentro de la clase FooBar, __boo se convierte en _FooBar__boo; ver más abajo).
- __double_leading_and_trailing_underscore__: objetos o atributos “mágicos” que viven en espacios de nombres controlados por el usuario. Por ej: __init__, __import__ o __file__. Nunca inventes tales nombres; Utilícelos únicamente como se documenta.
Prescriptivo: Convenciones de nomenclatura
Nombres a evitar
Nunca use los caracteres ‘l’ (letra minúscula el), ‘O’ (letra mayúscula oh) o ‘I’ (letra mayúscula) como nombres de variable de un solo carácter.
En algunas fuentes, estos caracteres son indistinguibles de los números uno y cero. Cuando tengas la tentación de usar ‘l’, usa ‘L’ en su lugar.
Compatibilidad ASCII
Los identificadores utilizados en la biblioteca estándar deben ser compatibles con ASCII como se describe en la sección de políticas de PEP 3131.
Nombres de paquetes y módulos
Los módulos deben tener nombres cortos, todo en minúsculas. Los guiones bajos se pueden usar en el nombre del módulo si mejora la legibilidad. Los paquetes de Python también deben tener nombres cortos en minúsculas, aunque se desaconseja el uso de guiones bajos.
Cuando un módulo de extensión escrito en C o C++ tiene un módulo Python adjunto que proporciona una interfaz de mayor nivel (por ejemplo, más orientada a objetos), el módulo C/C++ tiene un guión bajo (por ejemplo, _socket).
Nombres de clases
Los nombres de clase normalmente deben usar la convención de CapWords.
La convención de nomenclatura para funciones se puede usar en lugar de eso, en los casos en que la interfaz se documenta y se usa principalmente como un llamador.
Tenga en cuenta que existe una convención separada para los nombres incorporados: la mayoría de los nombres incorporados son palabras simples (o dos palabras juntas), con la convención de CapWords utilizada solo para nombres de excepción y constantes incorporadas.
Tipo de nombres de variables
Los nombres de las variables de tipo introducidas en PEP 484 normalmente deberían usar CapWords, prefiriendo nombres cortos: T, AnyStr, Num. Se recomienda agregar los sufijos _co o _contra a las variables utilizadas para declarar el comportamiento covariante o contravariante de manera correspondiente:
from typing import TypeVar
VT_co = TypeVar('VT_co', covariant=True)
KT_contra = TypeVar('KT_contra', contravariant=True)
Nombres de excepciones
Debido a que las excepciones deben ser clases, la convención de nomenclatura de clase se aplica aquí. Sin embargo, debe usar el sufijo “Error” en sus nombres de excepción (si la excepción es realmente un error).
Nombres de variables globales
(Esperemos que estas variables se utilicen solo dentro de un módulo). Las convenciones son casi las mismas que para las funciones.
Los módulos que están diseñados para su uso a través de M import * deben usar el mecanismo __all__ para evitar exportar globales, o usar la convención más antigua de prefijar dichos globales con un guión bajo (lo que podría querer hacer para indicar que estos globales son “módulos no públicos “).
Nombres de funciones y variables
Los nombres de las funciones deben estar en minúsculas, con palabras separadas por guiones bajos según sea necesario para mejorar la legibilidad.
Los nombres de variables siguen la misma convención que los nombres de funciones.
mixedCase solo se permite en contextos donde ese ya es el estilo prevaleciente (por ejemplo, threading.py), para conservar la compatibilidad con versiones anteriores.
Argumentos de función y métodos
Siempre use self para el primer argumento de los métodos de instancia.
Siempre use cls para el primer argumento de los métodos de clase.
Si el nombre de un argumento de función choca con una palabra clave reservada, generalmente es mejor agregar un subrayado final en lugar de usar una abreviatura o una corrupción ortográfica. Así, class_ es mejor que clss. (Quizás mejor es evitar tales choques usando un sinónimo.)
Nombres de métodos y variables de instancia
Utilice las reglas de nomenclatura de funciones: minúsculas con palabras separadas por guiones bajos según sea necesario para mejorar la legibilidad.
Use un guión bajo solo para métodos no públicos y variables de instancia.
Para evitar conflictos de nombres con las subclases, use dos guiones bajos para invocar las reglas de manipulación de nombres de Python.
Python maneja estos nombres con el nombre de la clase: si la clase Foo tiene un atributo llamado __a, Foo.__a no puede acceder a él. (Un usuario insistente aún podría obtener acceso al llamar a Foo._Foo__a). Generalmente, los guiones bajos dobles se deben usar solo para evitar conflictos de nombre con los atributos en las clases diseñadas para ser subclasificadas.
Nota: existe cierta controversia sobre el uso de __names (ver más abajo).
Constantes
Las constantes generalmente se definen a nivel de módulo y se escriben en mayúsculas con guiones bajos que separan las palabras. Los ejemplos incluyen MAX_OVERFLOW y TOTAL.
Diseñar para la herencia
Siempre decida si los métodos y las variables de instancia de una clase (colectivamente: “atributos”) deben ser públicos o no públicos. En caso de duda, elija no público; es más fácil hacerlo público más tarde que hacer que un atributo público no sea público.
Los atributos públicos son aquellos que espera que usen los clientes no relacionados de su clase, con su compromiso de evitar cambios incompatibles hacia atrás. Los atributos no públicos son aquellos que no están destinados a ser utilizados por terceros; no garantiza que los atributos no públicos no cambien o incluso no se eliminen.
No utilizamos el término “private” aquí, ya que ningún atributo es realmente privado en Python (sin una cantidad de trabajo generalmente innecesaria).
Otra categoría de atributos son aquellos que forman parte de la “subclase API” (a menudo llamada “protected o protegida”). Algunas clases están diseñadas para heredarse, ya sea para ampliar o modificar aspectos del comportamiento de la clase. Al diseñar una clase de este tipo, tenga cuidado de tomar decisiones explícitas sobre qué atributos son públicos, cuáles son parte de la API de subclases y cuáles son realmente solo para ser utilizados por su clase base.
Con esto en mente, aquí están las pautas de Pythonic:
- Los atributos públicos no deben tener guiones bajos.
- Si su nombre de atributo público choca con una palabra clave reservada, agregue un subrayado final al nombre de su atributo. Esto es preferible a una abreviatura o ortografía dañada. (Sin embargo, a pesar de esta regla, ‘cls’ es la ortografía preferida para cualquier variable o argumento que se sepa que es una clase, especialmente el primer argumento de un método de clase).
Nota 1: Consulte la recomendación de nombre de argumento anterior para los métodos de clase.
- Para atributos de datos públicos simples, es mejor exponer solo el nombre del atributo, sin métodos complicados de acceso/mutación. Tenga en cuenta que Python proporciona un camino fácil para futuras mejoras, en caso de que necesite un atributo de datos simple para crecer el comportamiento funcional. En ese caso, use las propiedades para ocultar la implementación funcional detrás de la sintaxis de acceso a atributos de datos simples.
Nota 1: Las propiedades solo funcionan en clases de nuevo estilo.
- Nota 2: intente mantener el comportamiento funcional libre de efectos secundarios, aunque los efectos secundarios como el almacenamiento en caché generalmente están bien.
- Si su clase está diseñada para ser subclasificada y tiene atributos que no desea que usen las subclases, considere nombrarlos con guiones bajos dobles y sin guiones bajos. Esto invoca el algoritmo de manipulación de nombres de Python, donde el nombre de la clase se transforma en el nombre del atributo. Esto ayuda a evitar colisiones de nombres de atributos en caso de que las subclases contengan inadvertidamente atributos con el mismo nombre.
Nota 1: tenga en cuenta que solo el nombre de clase simple se usa en el nombre mutilado, por lo que si una subclase elige el mismo nombre de clase y el mismo nombre de atributo, aún puede obtener colisiones de nombres.
Nota 2: la manipulación de nombres puede hacer ciertos usos, como la depuración y __getattr__(), menos convenientes. Sin embargo, el algoritmo de gestión de nombres está bien documentado y es fácil de realizar manualmente.
Nota 3: No a todo el mundo le gusta la manipulación de nombres Intente equilibrar la necesidad de evitar choques accidentales de nombres con el uso potencial de personas que llaman avanzadas.
Interfaces públicas e internas
Cualquier garantía de compatibilidad con versiones anteriores se aplica solo a las interfaces públicas. Por consiguiente, es importante que los usuarios puedan distinguir claramente entre interfaces públicas e internas.
Las interfaces documentadas se consideran públicas, a menos que la documentación explícitamente las declare como interfaces provisionales o internas exentas de las garantías habituales de compatibilidad con versiones anteriores. Se debe asumir que todas las interfaces no documentadas son internas.
Para soportar mejor la introspección, los módulos deben declarar explícitamente los nombres en su API pública usando el atributo __all__. La configuración de __all__ en una lista vacía indica que el módulo no tiene una API pública.
Incluso con __all__ configurado apropiadamente, las interfaces internas (paquetes, módulos, clases, funciones, atributos u otros nombres) aún deben tener un prefijo con un solo guión bajo.
Una interfaz también se considera interna si cualquier espacio de nombres que contenga (paquete, módulo o clase) se considera interno.
Los nombres importados siempre deben considerarse un detalle de implementación. Otros módulos no deben depender del acceso indirecto a dichos nombres importados a menos que sean una parte explícitamente documentada de la API del módulo que lo contiene, como os.path o el módulo __init__ de un paquete que expone la funcionalidad de los submódulos.
Recomendaciones de programación
- El código debe escribirse de manera que no perjudique a otras implementaciones de Python (PyPy, Jython, IronPython, Cython, Psyco, etc.).
- Las comparaciones con singletons como None deben hacerse siempre con o no, nunca con los operadores de igualdad.
Además, tenga cuidado de escribir si x cuando realmente quiere decir si x no es Ninguno, p. Ej. al probar si una variable o argumento que por defecto es None se estableció en algún otro valor. El otro valor podría tener un tipo (como un contenedor) que podría ser falso en un contexto booleano.
- El uso is not es operador en lugar de not … es. Si bien ambas expresiones son funcionalmente idénticas, la primera es más legible y preferida.
Si:
if foo is not None:
No:
if not foo is None:
Al implementar operaciones de ordenamiento con comparaciones ricas, es mejor implementar las seis operaciones (__eq__, __ne__, __lt__, __le__, __gt__, __ge__) en lugar de confiar en otro código para ejercer solo una comparación particular.
Para minimizar el esfuerzo involucrado, el decorador functools.total_ordering() proporciona una herramienta para generar métodos de comparación que faltan.
- Siempre use una instrucción def en lugar de una instrucción de asignación que vincule una expresión lambda directamente a un identificador.
Si:
def f(x): return 2*x
No:
f = lambda x: 2*x
La primera forma significa que el nombre del objeto de función resultante es específicamente ‘f’ en lugar del genérico ”. Esto es más útil para las trazas y representaciones de cadenas en general. El uso de la declaración de asignación elimina el único beneficio que puede ofrecer una expresión lambda sobre una declaración explícita de definición (es decir, que se puede incrustar dentro de una expresión más grande).
- Derive excepciones de Exception en lugar de BaseException. La herencia directa de BaseException está reservada para las excepciones en las que su captura es casi siempre una tarea incorrecta.
Diseñar jerarquías de excepciones basadas en las distinciones que probablemente necesite el código que captura las excepciones, en lugar de las ubicaciones donde se generan las excepciones. Trate de responder la pregunta “¿Qué salió mal?” programáticamente, en lugar de solo indicar que “ocurrió un problema” (consulte el PEP 3151 para ver un ejemplo de esta lección aprendida para la jerarquía de excepciones incorporada).
las convenciones de nomenclatura de clase se aplican aquí, aunque debe agregar el sufijo “Error” a sus clases de excepción si la excepción es un error. Las excepciones Non-error que se utilizan para el control de flujo no local u otras formas de señalización no necesitan un sufijo especial.
- Utilice el encadenamiento de excepción adecuadamente. En Python 3, se debe usar “raise X from Y” para indicar un reemplazo explícito sin perder el rastreo original.
- Al generar una excepción en Python 2, use raise ValueError(‘message’) en lugar de la forma más antigua raise ValueError, ‘message’.
La última forma no es la sintaxis legal de Python 3.
El formulario de uso de parén también significa que cuando los argumentos de excepción son largos o incluyen el formato de cadena, no es necesario utilizar caracteres de continuación de línea gracias a los paréntesis que lo contienen.
- Cuando detecte excepciones, mencione excepciones específicas siempre que sea posible en lugar de usar una cláusula de except:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
Una simple excepción: la cláusula detectará las excepciones de SystemExit y KeyboardInterrupt, lo que dificultará la interrupción de un programa con Control-C y puede disimular otros problemas. Si desea detectar todas las excepciones que señalan errores de programa, utilice excepto Excepción: (solo excepto es equivalente a excepto BaseException :).
Una buena regla general es limitar el uso de cláusulas ‘except’ en dos casos:
- Si el controlador de excepciones imprimirá o registrará el rastreo; al menos el usuario será consciente de que ha ocurrido un error.
- si el código necesita hacer algún trabajo de limpieza, pero luego permite que la excepción se propague hacia arriba con el aumento. try … finally puede ser una mejor manera de manejar este caso.
- Al vincular excepciones capturadas a un nombre, prefiera la sintaxis de enlace de nombre explícita agregada en Python 2.6:
try:
process_data()
except Exception as exc:
raise DataProcessingFailedError(str(exc))
Esta es la única sintaxis compatible con Python 3, y evita los problemas de ambigüedad asociados con la sintaxis anterior basada en comas.
- Cuando detecte errores en el sistema operativo, prefiera la jerarquía de excepciones explícita introducida en Python 3.3 sobre la introspección de valores errno.
- Además, para todas las cláusulas try/except, limite la cláusula try a la cantidad mínima absoluta de código necesaria. De nuevo, esto evita enmascarar errores.
Si:
try:
value = collection[key]
except KeyError:
return key_not_found(key)
else:
return handle_value(value)
No:
try:
# Too broad!
return handle_value(collection[key])
except KeyError:
# Will also catch KeyError raised by handle_value()
return key_not_found(key)
- Cuando un recurso es local a una sección particular del código, use una declaración with para asegurarse de que se limpie de manera rápida y confiable después de su uso. Una declaración try/finally también es aceptable.
- Los gestores de contexto deben invocarse a través de funciones o métodos separados siempre que hagan algo distinto de adquirir y liberar recursos.
Si:
with conn.begin_transaction():
do_stuff_in_transaction(conn)
No:
with conn:
do_stuff_in_transaction(conn)
El último ejemplo no proporciona ninguna información para indicar que los métodos __enter__ y __exit__ están haciendo algo más que cerrar la conexión después de una transacción. Ser explícito es importante en este caso.
- Sea consistente en las declaraciones de retorno. O todas las declaraciones de retorno en una función deben devolver una expresión, o ninguna de ellas debería. Si cualquier declaración de retorno devuelve una expresión, cualquier declaración de retorno en la que no se devuelva ningún valor debe declarar explícitamente esto como retorno None, y una declaración de retorno explícita debe estar presente al final de la función (si es accesible).
Si:
def foo(x):
if x >= 0:
return math.sqrt(x)
else:
return None
def bar(x):
if x < 0:
return None
return math.sqrt(x)
No:
def foo(x):
if x >= 0:
return math.sqrt(x)
def bar(x):
if x < 0:
return
return math.sqrt(x)
- Utilice métodos de cadena en lugar del módulo de cadena.
- Use ” .startswith() y ” .endswith() en lugar de cortar la cadena para verificar si hay prefijos o sufijos.
startswith() y endswith() son más limpios y menos propensos a errores:
Si: if foo.startswith('bar'):
No: if foo[:3] == 'bar':
- Las comparaciones de tipos de objetos siempre deben usar isinstance() en lugar de comparar tipos directamente.
Si: if isinstance(obj, int):
No: if type(obj) is type(1):
Al verificar si un objeto es una cadena, ¡tenga en cuenta que también podría ser una cadena Unicode! En Python 2, str y unicode tienen una clase base común, basestring, por lo que puedes hacer:
if isinstance(obj, basestring):
Tenga en cuenta que en Python 3, Unicode y Basestring ya no existen (solo hay str) y que un objeto de bytes ya no es un tipo de cadena (es una secuencia de enteros).
- Para las secuencias (cadenas, listas, tuplas), use el hecho de que las secuencias vacías son falsas.
Si: if not seq:
if seq:
No: if len(seq):
if not len(seq):
- No escriba literales de cadena que se basen en espacios en blanco finales significativos. Este espacio en blanco final es indistinguible visualmente y algunos editores (o más recientemente, reindent.py) los recortarán.
- No compare valores booleanos con True o False usando ==.
Si: if greeting:
No: if greeting == True:
Peor: if greeting is True:
Anotaciones de funciones
Con la aceptación de PEP 484, las reglas de estilo para las anotaciones de funciones están cambiando.
- Para que sean compatibles con el reenvío, las anotaciones de funciones en el código de Python 3 deben usar preferiblemente la sintaxis PEP 484. (Hay algunas recomendaciones de formato para las anotaciones en la sección anterior).
- La experimentación con los estilos de anotación que se recomendaron anteriormente en este PEP ya no se recomienda.
- Sin embargo, fuera del estándar, ahora se alientan los experimentos dentro de las reglas de PEP 484. Por ejemplo, marcar una gran biblioteca o aplicación de terceros con anotaciones de tipo PEP 484, revisar lo fácil que fue agregar esas anotaciones y observar si su presencia aumenta la comprensibilidad del código.
- La biblioteca estándar de Python debería ser conservadora al adoptar dichas anotaciones, pero su uso está permitido para nuevos códigos y para grandes refactorizaciones.
- Para el código que desea hacer un uso diferente de las anotaciones de funciones, se recomienda poner un comentario del formulario:
# type: ignore
Cerca de la parte superior del archivo; esto le dice al tipo checker que ignore todas las anotaciones. (En el PEP 484 se pueden encontrar formas más precisas de deshabilitar las quejas de los verificadores de tipos).
- Al igual que los linters, los checkers de tipo son herramientas opcionales, separadas. Los intérpretes de Python por defecto no deberían emitir ningún mensaje debido a la verificación de tipos y no deberían alterar su comportamiento en base a las anotaciones.
- Los usuarios que no quieran utilizar comprobadores de tipos pueden ignorarlos. Sin embargo, se espera que los usuarios de paquetes de bibliotecas de terceros deseen ejecutar comprobadores de tipos sobre esos paquetes. Para este propósito, PEP 484 recomienda el uso de archivos de código auxiliar: archivos .pyi que son leídos por el verificador de tipos en lugar de los archivos .py correspondientes. Los archivos de código auxiliar se pueden distribuir con una biblioteca, o por separado (con el permiso del autor de la biblioteca) a través del repositorio de tipos.
- Para el código que debe ser compatible con versiones anteriores, las anotaciones de tipo se pueden agregar en forma de comentarios. Consulte la sección correspondiente de PEP 484 [6].
Anotaciones variables
PEP 526 introdujo anotaciones variables. Las recomendaciones de estilo para ellos son similares a las de las anotaciones de funciones descritas anteriormente:
- Las anotaciones para variables de nivel de módulo, variables de clase e instancia, y variables locales deben tener un espacio único después de los dos puntos.
- No debe haber espacio antes de los dos puntos.
- Si una asignación tiene un lado derecho, el signo de igualdad debe tener exactamente un espacio en ambos lados.
Si:
code: int
class Point:
coords: Tuple[int, int]
label: str = '<unknown>'
No:
code:int # No hay espacio después de los dos puntos.
code : int # Espacio antes del colon
class Test:
result: int=0 # No hay espacios alrededor del signo de igualdad.
- Aunque se acepta PEP 526 para Python 3.6, la sintaxis de anotación variable es la sintaxis preferida para los archivos de código auxiliar en todas las versiones de Python (consulte PEP 484 para obtener más información).
Referencias
- Style Guide for Python, Guido van Rossum
- PEP 7, Style Guide for C Code, van Rossum
- Barry’s GNU Mailman style guide http://barry.warsaw.us/software/STYLEGUIDE.txt
- Donald Knuth’s The TeXBook, pages 195 and 196.
- http://www.wikipedia.com/wiki/CamelCase
- ypeshed repo https://github.com/python/typeshed
- Suggested syntax for Python 2.7 and straddling codehttps://www.python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code
#HappyCode
0 comentarios