¿Cuáles son los inconvenientes de Python? [cerrado]

147

Python parece estar de moda en estos días, y no sin mérito, ya que es realmente un lenguaje con el que casi disfruta que se le dé un nuevo problema para resolver. Pero, como dijo un sabio una vez (llamándolo sabio solo porque no tengo idea de quién lo dijo realmente; no estoy seguro de si era tan sabio), saber realmente un idioma no solo sabe ventajas de sintaxis, diseño, etc., pero también sus inconvenientes. Ningún idioma es perfecto, algunos son mejores que otros.

Entonces, ¿cuáles serían, en su opinión, inconvenientes objetivos de Python?

Nota: No estoy pidiendo una comparación de idioma aquí (es decir, C # es mejor que Python porque ... yadda yadda yadda), más que una opinión objetiva (hasta cierto nivel) qué características del lenguaje están mal diseñadas, si, cuáles son algunos te faltan, etc. Debe usar otro idioma como comparación, pero solo para ilustrar un punto que sería difícil de explicar de otra manera (es decir, para facilitar la comprensión)

Torre
fuente
50
Creo que esta es una pregunta subjetiva útil, y sería una pena cerrarla.
Eric Wilson
25
Parece que hay un fanático de Python aquí que simplemente rechaza todas las respuestas contra Python.
zvrba
2
@ TMN: Eso todavía trata el espacio en blanco como tokens, simplemente no los devuelve, y eso es exactamente lo que hace la gramática de Python.
99
@Roger: la convención sobre SO es hacer comentarios negativos. Dado que este es un sitio para opiniones subjetivas , no veo razón para votos negativos, especialmente. sin comentarios. Por lo tanto, mantengo mi "insultos".
zvrba
8
@zvrba: Los votos negativos todavía significan "no útil", como siempre.

Respuestas:

109

Utilizo Python de forma regular y, en general, considero que es un lenguaje muy bueno. Sin embargo, ningún idioma es perfecto. Aquí están los inconvenientes en orden de importancia para mí personalmente:

  1. Es lento. Quiero decir muy, muy lento. Muchas veces esto no importa, pero definitivamente significa que necesitará otro idioma para esos bits críticos de rendimiento.

  2. Las funciones anidadas son un asco porque no se pueden modificar las variables en el ámbito externo. Editar: todavía uso Python 2 debido al soporte de la biblioteca, y este error de diseño me irrita muchísimo, pero aparentemente se solucionó en Python 3 debido a la declaración no local . No puedo esperar a que las bibliotecas que utilizo sean portadas para que esta falla pueda enviarse al montón de la historia para siempre.

  3. Faltan algunas características que pueden ser útiles para la biblioteca / código genérico y, en mi humilde opinión, la simplicidad se lleva a extremos insalubres. Los más importantes en los que puedo pensar son los tipos de valores definidos por el usuario (supongo que se pueden crear con magia de metaclase, pero nunca lo he intentado) y el parámetro de función ref.

  4. Está lejos del metal. ¿Necesita escribir primitivas de subprocesamiento o código de kernel o algo así? Buena suerte.

  5. Si bien no me importa la falta de capacidad para detectar errores semánticos por adelantado como una compensación por el dinamismo que ofrece Python, desearía que hubiera una forma de detectar errores sintácticos y cosas tontas como escribir nombres de variables sin tener que ejecutar el código.

  6. La documentación no es tan buena como los lenguajes como PHP y Java que tienen fuertes respaldos corporativos.

revs dsimcha
fuente
6060
@Casey, tengo que estar en desacuerdo. El índice es horrible: intente buscar la withdeclaración o los métodos en a list. Todo lo cubierto en el tutorial es básicamente inescrutable. Tengo mucha mejor suerte con la documentación de Microsoft para C ++.
Mark Ransom
17
Alrededor de 5: solo use pyflakes. Está escrito para detectar exactamente esos errores.
Alexander Solovyov
44
Respecto a la velocidad: con el auge de PyPy, muchos usuarios de Python ahora podrán manejar el problema de la velocidad simplemente usando un intérprete con un compilador JIT incorporado (por ahora, los usuarios de Python 3 y los usuarios de módulos de extensión C no manejados por cpyext No tengo esta opción).
ncoghlan
29
Desprecio los documentos de Python. Son más bonitas que la mayoría para estar seguros, pero muchas veces mucha información útil se agrupa en una página, como los métodos en cadenas y listas, y todos los tipos de secuencia también se agrupan. Cuando busco esta información, aterrizo en un tomo enorme y tengo que buscar en la página para encontrar lo que quiero. También encuentro que el índice en estas páginas es difícil de leer, y a veces es difícil decir qué sección quiero.
Carson Myers
55
¿Cómo puede la distancia del metal ser un argumento? ¿Python alguna vez pretendió ser un lenguaje de sistemas?
Mark Canlas
66

Odio que Python no pueda distinguir entre declaración y uso de una variable. No necesita escribir estática para que eso suceda. Sería bueno tener una manera de decir "esta es una variable que declaro deliberadamente, y tengo la intención de introducir un nuevo nombre, esto no es un error tipográfico".

Además, generalmente uso las variables de Python en un estilo de escritura única, es decir, trato las variables como inmutables y no las modifico después de su primera asignación. Gracias a características como la comprensión de la lista, esto es realmente increíblemente fácil y hace que el código fluya más fácilmente.

Sin embargo, no puedo documentar ese hecho. Nada en Python me impide sobrescribir o reutilizar variables.

En resumen, me gustaría tener dos palabras clave en el idioma: vary let. Si escribo en una variable no declarada por ninguno de esos, Python debería generar un error. Además, letdeclara las variables como de solo lectura, mientras que las varvariables son "normales".

Considere este ejemplo:

x = 42    # Error: Variable `x` undeclared

var x = 1 # OK: Declares `x` and assigns a value.
x = 42    # OK: `x` is declared and mutable.

var x = 2 # Error: Redeclaration of existing variable `x`

let y     # Error: Declaration of read-only variable `y` without value
let y = 5 # OK: Declares `y` as read-only and assigns a value.

y = 23    # Error: Variable `y` is read-only

Tenga en cuenta que los tipos siguen siendo implícitos (pero las letvariables son para todos los propósitos y tipos estánticamente tipados, ya que no pueden volver a un nuevo valor, mientras que las varvariables aún pueden tipearse dinámicamente).

Finalmente, todos los argumentos del método deberían ser automáticamente let, es decir, deberían ser de solo lectura. En general, no hay una buena razón para modificar un parámetro, excepto por el siguiente modismo:

def foo(bar = None):
    if bar == None: bar = [1, 2, 3]

Esto podría ser reemplazado por un idioma ligeramente diferente:

def foo(bar = None):
    let mybar = bar or [1, 2, 3]
Konrad Rudolph
fuente
66
Ojalá Python tuviera una declaración "var". Además de la (muy buena) razón por la que declaras, también sería mucho más fácil leer el código porque entonces puedes simplemente escanear la página para detectar todas las declaraciones de variables.
jhocking
25
Es como si los desarrolladores de Python ignoraran las lecciones del pasado. No declarar variables, no declarar funciones, es un error cometido por primera vez en la década de 1950. Esos errores difíciles de encontrar que resultaron de un error tipográfico difícil de detectar fueron sorprendentemente hechos por primera vez en la década de 1950. Este error de idioma se ha cometido (y luego corregido) una y otra vez. Declarar variables no es una carga enorme. Me ha salvado el trasero varias veces. Inevitablemente use strict;y use warnings;en perl en un guión de cualquier tamaño. Python ha despojado al desarrollador de demasiadas ayudas de depuración.
David Hammen
19
@David, para ser justos con Python, generará una excepción si intenta acceder a una variable que no ha sido asignada. Muchos de los idiomas que carecen de declaraciones devolverían algún tipo de valor predeterminado. Como resultado, la versión de Python es mucho menos problemática que esas.
Winston Ewert
1
@yi_H La propuesta no debía ser compatible con versiones anteriores, ni siquiera una propuesta real. La pregunta era, "cuáles son los inconvenientes de Python" ... bueno, no tener vary let(o un mecanismo similar) es un inconveniente. Dicho de otra manera: si hubiera sido el diseñador de Python, habría hecho algo como esto. Dicho esto , las versiones futuras podrían incluir esto cuando cargue un paquete especial (similar a __future__). Decir import strict. Sin embargo, esto no sucederá, ya que requiere hacks sintácticos ...
Konrad Rudolph
3
+1 Para agregar mejores habilidades de programación 'funcionales'.
Evan Plaice
44

Mi queja principal es el enhebrado, que no es tan eficaz en muchas circunstancias (en comparación con Java, C y otros) debido al bloqueo global del intérprete (consulte la charla "Inside the Python GIL" (enlace PDF) )

Sin embargo, hay una interfaz multiproceso que es muy fácil de usar, sin embargo, será más pesado en el uso de memoria para el mismo número de procesos frente a subprocesos, o difícil si tiene muchos datos compartidos. Sin embargo, el beneficio es que una vez que tiene un programa trabajando con múltiples procesos, puede escalar en múltiples máquinas, algo que un programa de subprocesos no puede hacer.

Realmente no estoy de acuerdo con la crítica de la documentación, creo que es excelente y mejor que la mayoría, si no todos los idiomas principales.

También puede detectar muchos de los errores de tiempo de ejecución que ejecutan pylint .

Casey
fuente
2
+1 para pylint. No lo sabía. La próxima vez que haga un proyecto en Python, lo probaré. Además, el subprocesamiento múltiple parece funcionar bien si usa Jython en lugar de la implementación de CPython de referencia. OTOH Jython es algo más lento que CPython, por lo que esto puede vencer parcialmente el propósito.
dsimcha
3
¿El subproceso no está bien soportado? Las bibliotecas de subprocesos han estado allí desde antes de 2.1.
rox0r
2
Sé que hay soporte para subprocesos, pero en comparación con Java o C, el GIL realmente reducirá su rendimiento. Es por eso que se prefiere el módulo de multiprocesamiento en lugar de subprocesos.
cmcginty
2
La documentación es buena si puedes encontrarla. Buscar en Google clases de Java es mucho más fácil que Python.
Brendan Long
@Casey He aclarado la redacción en la respuesta, ya que los subprocesos son compatibles, solo exhibe un rendimiento extraño (también se agregó una referencia y algunos enlaces a documentos)
dbr
28

Podría decirse que la falta de tipeo estático, que puede introducir ciertas clases de errores de tiempo de ejecución , no vale la flexibilidad adicional que brinda el tipeo de pato.

Jacob
fuente
55
Esto es correcto, aunque hay herramientas como PyChecker que pueden verificar si hay errores en un compilador en lenguajes como C / Java.
Oliver Weiler
24
La escritura dinámica es una decisión de diseño consciente, no un inconveniente.
missingfaktor
14
Es lo mismo que decir que la debilidad de Java es la falta de tipeo dinámico.
MAK
12
@missingfaktor, @MAK, obviamente escribir pato era una característica prevista. Pero la mayoría de las decisiones de diseño introducen beneficios e inconvenientes objetivos. La flexibilidad adicional del código es un beneficio del tipeo dinámico, y las clases adicionales de posibles errores de tiempo de ejecución son un inconveniente. La parte subjetiva es si la característica vale la pena.
Jacob
66
La falta de escritura estática hace que sea más fácil para los programadores escribir código que tenga errores de tiempo de ejecución. En C #, int foo = 4; Console.Write(foo.Length);no se compila, por lo que el error "Int32 no tiene una propiedad Longitud" no puede aparecer accidentalmente en el software publicado. En python, a menos que ejecute herramientas secundarias opcionales para buscar errores como ese, el código que accede a miembros de objetos no existentes puede pasar desapercibido hasta que termine causando errores de tiempo de ejecución.
Jacob
27

Creo que las partes orientadas a objetos de Python se sienten "atornilladas". Toda la necesidad de pasar explícitamente "self" a cada método es un síntoma de que su componente OOP no se planificó expresamente , se podría decir; también muestra las reglas de alcance a veces vergonzosas de Python que fueron criticadas en otra respuesta.

Editar:

Cuando digo que las partes orientadas a objetos de Python se sienten "atornilladas", quiero decir que a veces, el lado de la POO se siente bastante inconsistente. Tomemos Ruby, por ejemplo: en Ruby, todo es un objeto, y se llama a un método usando la obj.methodsintaxis familiar (con la excepción de los operadores sobrecargados, por supuesto); en Python, todo es también un objeto, pero algunos métodos se llaman como una función; es decir, se sobrecarga __len__para devolver una longitud, pero se llama utilizando en len(obj)lugar del más obj.lengthcomún (y consistente) común en otros idiomas. Sé que hay razones detrás de esta decisión de diseño, pero no me gustan.

Además, el modelo OOP de Python no tiene ningún tipo de protección de datos, es decir, no hay miembros privados, protegidos y públicos; puedes imitarlos usando _y __frente a métodos, pero es un poco feo. Del mismo modo, Python tampoco entiende bien el aspecto de paso de mensajes de OOP.

revs mipadi
fuente
17
El parámetro self simplemente hace explícito lo que otros idiomas dejan implícito. Esos idiomas tienen claramente un parámetro "propio".
13
@Roger Pate: Sí, pero esa necesidad explícita de "uno mismo" es un poco molesto (y, diría, una abstracción permeable). Tampoco surgió como una decisión de diseño deliberada, sino debido a las reglas de alcance "extrañas" de Python. No puedo encontrar el artículo rápidamente, pero hay una publicación por correo electrónico de Guido van Rossum que explica muy bien por qué se requiere el parámetro "self".
mipadi
2
@Roger Pate: en lenguajes orientados a objetos, pasar el objetivo como primer parámetro aún podría considerarse un detalle de implementación. Sin embargo, mi punto no es si es una buena idea o no; El punto es que en Python, no se debe a una decisión de diseño consciente, sino a evitar las verrugas en el sistema de alcance.
mipadi
3
@mipadi: La actualización tiene un mejor razonamiento (por lo que eliminaré el voto negativo), pero si ve a len como un operador que sobrecarga, es más OO en Python. Me encantaría ver un ejemplo o razonamiento sobre cómo Python se equivoca al pasar mensajes.
8
El self explícito es una consecuencia del hecho de que los métodos son solo funciones (y, como señaló Winston, declaraciones de variables locales implícitas). Es libre de que no le guste esa decisión de diseño, pero llamar a OOP "atornillado" en un lenguaje donde todo es accesible como un objeto en tiempo de ejecución es una tontería.
ncoghlan
19

Cosas que no me gustan de Python:

  1. Enhebrado (sé que ya se ha mencionado, pero vale la pena mencionarlo en cada publicación).
  2. No se admiten funciones anónimas de varias líneas ( lambdasolo puede contener una expresión).
  3. Falta de una función / clase de lectura de entrada simple pero potente (como cino scanfen C ++ y C o Scanneren Java).
  4. Todas las cadenas no son unicode por defecto (pero se arreglan en Python 3).
MAK
fuente
55
Con respecto a (2), creo que esto se compensa con la posibilidad de tener funciones anidadas.
Konrad Rudolph
3
@KonradRudolph Mi reparo principal con funciones anidadas en lugar de lambdas de varias líneas es que el orden de lectura se intercambia.
CookieOfFortune
2
@wkschwartz: raw_inputy 'sys.stdin' son bastante simples. No admiten la entrada formateada (por ejemplo, algo como "% d:% d:% d"% (hora, minuto, segundo) para leer a tiempo). Hasta ahora, Python no tiene nada parecido a la funcionalidad de scanf (en C) o Scanner (Java).
MAK
2
@limscoder: todas las cadenas son unicode de forma predeterminada en Java. No veo una buena razón para tener clases str y unicode separadas. En mi humilde opinión, las cadenas y matrices de bytes no deben representarse por la misma abstracción. Una clase de cadena debe ser para almacenar y manipular texto, cuya representación interna realmente no nos importa. No deberíamos querer hacer cosas como truncar / reemplazar / eliminar / insertar en un byte específico dentro de una cadena; queremos hacer esto en un carácter específico . Es fácil olvidar la distinción y hacer que su código explote cuando se ingresa una entrada que no está en inglés.
MAK
1
@limscoder: si quieres ver unicode fácil, prueba Tcl. Tuve que cambiar de Tcl a Python hace unos años, y me sorprendió lo primitivo que es el soporte unicode de Python en comparación. Es realmente invisible en Tcl, y un gran dolor en Python.
Bryan Oakley
18

Argumentos predeterminados con tipos de datos mutables.

def foo(a, L = []):
    L.append(a)
    print L

>>> foo(1)
[1]
>>> foo(2)
[1, 2]

Suele ser el resultado de algunos errores sutiles. Creo que sería mejor si creara un nuevo objeto de lista siempre que se requiriera un argumento predeterminado (en lugar de crear un solo objeto para usar en cada llamada a la función).

Editar: no es un gran problema, pero cuando algo necesita ser referido en los documentos, generalmente significa que es un problema. Esto no debería ser obligatorio.

def foo(a, L = None):
    if L is None:
        L = []
    ...

Especialmente cuando eso debería haber sido el valor predeterminado. Es solo un comportamiento extraño que no coincide con lo que cabría esperar y no es útil para una gran cantidad de circunstancias.

revs jsternberg
fuente
Veo muchas quejas sobre esto, pero ¿por qué la gente insiste en tener una lista vacía (que la función modifica) como argumento predeterminado? ¿Es esto realmente un gran problema? Es decir, ¿es esto un problema real ?
Martin Vilcans
8
Viola el principio de la menor sorpresa. Uno no esperaría que los parámetros de una función sobrevivan a través de llamadas.
aib
Es una consecuencia de ser un lenguaje de script. Este error solo te dejará perplejo UNA VEZ, y nunca más. Descubrir este error por sí mismo realmente te da una patada en el trasero para recordarte que sí, este sigue siendo un lenguaje de secuencias de comandos. Y eso es solo porque el lenguaje es tan bueno para ocultar el aspecto del script (suponiendo que lo use correctamente).
Zoran Pavlovic
@ZoranPavlovic por curiosidad, ¿por qué es esto una consecuencia de ser un lenguaje de script? Parece ser un problema con cuándo se enlazan los datos y porque las listas son mutables (que son dos cosas que normalmente son buenas, pero terminan siendo malas cuando se combinan). El mismo problema podría ocurrir en un lenguaje sin secuencias de comandos si vincula los datos en el momento de la creación de la función en lugar de crear una nueva lista cada vez que se llama a la función.
jsternberg
@aib: No lo creo, el parámetro aquí, como cualquier otro objeto de Python, es un puntero a un objeto. En este caso, el objeto es mutable y la variable está vinculada cuando se declara la función. El parámetro "sobrevive a través de llamadas", pero lo que sobrevive es la referencia a un objeto mutable.
Patrick Collins
14

Algunas de las características de Python que lo hacen tan flexible como un lenguaje de desarrollo también son vistas como inconvenientes importantes por aquellos utilizados para el análisis estático de "todo el programa" realizado por el proceso de compilación y enlace en lenguajes como C ++ y Java.

  • Declaración implícita de variables locales.

Las variables locales se declaran utilizando la instrucción de asignación ordinaria. Esto significa que los enlaces de variables en cualquier otro ámbito requieren una anotación explícita para ser recogida por el compilador (declaraciones globales y no locales para ámbitos externos, notación de acceso a atributos, por ejemplo, ámbitos). Esto reduce enormemente la cantidad de repeticiones necesarias cuando se programa, pero significa que se necesitan herramientas de análisis estático de terceros (como pyflakes) para realizar comprobaciones manejadas por el compilador en lenguajes que requieren declaraciones de variables explícitas.

  • "Parche de mono" es compatible

El contenido de los módulos, los objetos de clase e incluso el espacio de nombres incorporado se puede modificar en tiempo de ejecución. Esto es enormemente poderoso, permitiendo muchas técnicas extremadamente útiles. Sin embargo, esta flexibilidad significa que Python no ofrece algunas características comunes a los lenguajes OO de tipo estático. En particular, el parámetro "self" para los métodos de instancia es explícito en lugar de implícito (dado que los "métodos" no tienen que definirse dentro de una clase, se pueden agregar más tarde modificando la clase, lo que significa que no es particularmente práctico para pasar la referencia de instancia implícitamente) y los controles de acceso a los atributos no se pueden aplicar fácilmente en función de si el código está "dentro" o "fuera" de la clase (ya que esa distinción solo existe mientras se ejecuta la definición de clase).

  • Lejos del metal

Esto también es cierto para muchos otros lenguajes de alto nivel, pero Python tiende a abstraer la mayoría de los detalles del hardware. Los lenguajes de programación de sistemas como C y C ++ siguen siendo mucho más adecuados para manejar el acceso directo al hardware (sin embargo, Python hablará con ellos con gusto a través de los módulos de extensión CPython o, de manera más portátil, a través de la ctypesbiblioteca).

revs ncoghlan
fuente
12
  1. Usar sangría para bloques de código en lugar de {} / begin-end, lo que sea.
  2. Cada lenguaje moderno más nuevo tiene un alcance léxico adecuado, pero no Python (ver más abajo).
  3. Documentos caóticos (compárelos con la documentación de Perl5, que es excelente).
  4. Camisa de fuerza (solo hay una forma de hacerlo).

Ejemplo de alcance roto; transcripción de la sesión de intérprete:

>>> x=0
>>> def f():
...     x+=3
...     print x
... 
>>> f()
Traceback (most recent call last):
  File "", line 1, in ?
  File "", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment

globaly nonlocalse han introducido palabras clave para corregir esta estupidez de diseño.

zvrba
fuente
2
con respecto al alcance, podría valer la pena que los curiosos miren python.org/dev/peps/pep-3104 para comprender el razonamiento del método actual.
Winston Ewert
De acuerdo con +1. Entonces, +1.
Jas
34
Tener una forma de hacerlo es una ventaja. Cuando lees el código de otra persona, no tienes que descifrar una sola declaración. Una vez que las expresiones idiomáticas están programadas en su cerebro, debe tener un reconocimiento instantáneo.
rox0r
99
Completamente de acuerdo con @ rox0r. La "camisa de fuerza" evita todo tipo de guerras de sintaxis.
keithjgrant
8
Para ser honesto, rara vez necesito las palabras clave globalo nonlocalen Python. Tan raramente que olvido que este problema existe y tengo que volver a buscarlo en Google las pocas veces que aparece, a pesar de que escribo código Python todos los días en el trabajo. Para mí, el código que necesita modificar las variables globales (o peor, las variables externas no globales) es un olor a código. Por lo general, (no siempre) hay una mejor manera.
Ben
11

Me parece muy inquietante la combinación de sintaxis orientada a objetos this.method()y procesal / funcional de Python method(this):

x = [0, 1, 2, 3, 4]
x.count(1)
len(x)
any(x)
x.reverse()
reversed(x)
x.sort()
sorted(x)

Esto es particularmente malo porque una gran cantidad de funciones (en lugar de métodos) simplemente se vuelcan en el espacio de nombres global : métodos relacionados con listas, cadenas, números, constructores, metaprogramación, todo mezclado en una gran lista ordenada alfabéticamente.

Como mínimo, los lenguajes funcionales como F # tienen todas las funciones correctamente espaciadas en los módulos:

List.map(x)
List.reversed(x)
List.any(x)

Entonces no están todos juntos. Además, este es un estándar seguido en toda la biblioteca, por lo que al menos es consistente.

Entiendo las razones para hacer la función vs método , pero todavía creo que es una mala idea mezclarlos de esta manera. Sería mucho más feliz si se siguiera la sintaxis del método, al menos para las operaciones comunes:

x.count(1)
x.len()
x.any()
x.reverse()
x.reversed()
x.sort()
x.sorted()

Si los métodos están mutando o no, tenerlos como métodos en el objeto tiene varias ventajas:

  • Lugar único para buscar las operaciones "comunes" en un tipo de datos: otras bibliotecas / etc. pueden tener otras cosas elegantes que pueden hacer a los tipos de datos, pero las operaciones "predeterminadas" están en los métodos del objeto.
  • No es necesario seguir repitiendo Moduleal llamar Module.method(x). Tomando el ejemplo de la lista funcional anterior, ¿por qué tengo que seguir diciendo Listuna y otra vez? ¡Debe saber que es un Listy no quiero llamar a la Navigation.map()función en él! El uso de la x.map()sintaxis lo mantiene SECO y sin ambigüedades.

Y, por supuesto, tiene ventajas sobre la forma de hacerlo de poner todo en el espacio de nombres global . No es que la forma actual sea incapaz de hacer las cosas. Incluso es bastante conciso ( len(lst)), ¡ya que nada tiene espacio de nombres! Entiendo las ventajas de usar funciones (comportamiento predeterminado, etc.) sobre los métodos, pero todavía no me gusta.

Es solo desordenado. Y en grandes proyectos, el desorden es tu peor enemigo.

revs Haoyi
fuente
1
sí ... realmente extraño el estilo LINQ (estoy seguro de que LINQ no es el primero en implementarlo, pero estoy más familiarizado con él) manejo de listas.
CookieOfFortune
1
No pienses en len (x) como un método. "len" es una función. Python tiene funciones y métodos y no veo nada de malo en ese enfoque. La falta de funciones adecuadas es, por lo general, la fuente de muchos tipos de escritura innecesarios.
rbanffy
Sé que len()es una función, y cuáles son las ventajas. También dije por qué creo que es una mala idea, por qué creo que las funciones globales son una idea particularmente mala, y por qué creo que los métodos proporcionan un método conveniente para organizar y determinar su funcionalidad =)
Haoyi
No creo que 42 (¿o son 43?) Palabras clave sea un número 'grande'. Eso también incluye cosas como def, classy otras llamadas sin función. Compare eso con más de 100 en la mayoría de los otros idiomas populares. Además, considere la línea de import this: Namespaces are one honking great idea -- let's do more of those!. Creo que podría malinterpretar los espacios de nombres de Python;)
Wayne Werner
8

Falta de homoiconicidad .

Python tuvo que esperar 3.x para agregar una palabra clave "con". En cualquier lenguaje homoicónico podría haberse agregado trivialmente en una biblioteca.

La mayoría de los otros problemas que he visto en las respuestas son de uno de 3 tipos:

1) Cosas que se pueden arreglar con herramientas (p. Ej., Pyflakes) 2) Detalles de implementación (GIL, rendimiento) 3) Cosas que se pueden arreglar con estándares de codificación (es decir, características que la gente desearía que no estuvieran allí)

# 2 no es un problema con el idioma, IMO # 1 y # 3 no son problemas serios.

Aidenn
fuente
1
withestaba disponible desde Python 2.5 con from __future__ import with_statement, pero estoy de acuerdo, ocasionalmente encuentro desafortunado que declaraciones como if/ for/ print/ etc sean "especiales" en lugar de funciones regulares
dbr
7

Python es mi lenguaje favorito, ya que es muy expresivo, pero aún así evita que cometas demasiados errores. Todavía tengo algunas cosas que me molestan:

  • No hay funciones anónimas reales. Lambda puede usarse para funciones de una sola declaración, y la withdeclaración puede usarse para muchas cosas en las que usaría un bloque de código en Ruby. Pero en algunas situaciones hace que las cosas sean un poco más torpes de lo que deberían ser. (Lejos de ser tan torpe como sería en Java, pero aún así ...)

  • Alguna confusión en la relación entre módulos y archivos. Ejecutar "python foo.py" desde la línea de comandos es diferente de "import foo". Las importaciones relativas en Python 2.x también pueden causar problemas. Aún así, los módulos de Python son mucho mejores que las características correspondientes de C, C ++ y Ruby.

  • Explícito self. Aunque entiendo algunas de las razones, y aunque uso Python a diario, tiendo a cometer el error de olvidarlo. Otro problema con esto es que se vuelve un poco tedioso convertir una clase en un módulo. El yo explícito está relacionado con el alcance limitado del que otros se han quejado. El alcance más pequeño en Python es el alcance de la función. Si mantiene sus funciones pequeñas, como debería, eso no es un problema en sí mismo y la OMI a menudo proporciona un código más limpio.

  • Algunas funciones globales, como len, que esperarías que fuera un método (que en realidad está detrás de escena).

  • Sangrado significativo. No es la idea en sí, lo que creo que es genial, pero dado que esto es lo único que impide que tanta gente pruebe Python, quizás Python estaría mejor con algunos símbolos de inicio / fin (opcionales). Ignorando a esas personas, también podría vivir totalmente con un tamaño forzado para la sangría.

  • Que no es el lenguaje incorporado de los navegadores web, en lugar de JavaScript.

De estas quejas, es solo la primera que me importa lo suficiente y creo que debería agregarse al idioma. Los otros son bastante menores, excepto el último, ¡lo que sería genial si sucediera!

Martin Vilcans
fuente
+1 Me hace preguntarme si escribir datetime.datetime.now()cuando un proyecto podría escribir datetime.nowy luego mezclar dos proyectos de una manera de escribirlo descarta el otro y seguramente esto no habría sucedido en Java, que no nombraría un módulo igual que un archivo (?) si ve cómo la forma común parece hacer que el módulo nos confunda con el archivo cuando ambos usos se practican y son explícitos self, todavía trato de entenderlo ya que las llamadas no tienen el mismo número de argumentos que las funciones. ¿Y podría pensar que la máquina virtual Python tiene es lenta?
Niklas Rosencrantz
En cuanto a su problema con la palabra clave self explícita ¿Puedo sugerir usar un buen IDE de Python para eso? Sé que PyDev en Eclipse completa automáticamente la parte propia de una firma de función si detecta que estás escribiendo dentro de una clase.
Zoran Pavlovic
5

Python no está completamente maduro: el lenguaje python 3.2 en este momento tiene problemas de compatibilidad con la mayoría de los paquetes actualmente distribuidos (generalmente son compatibles con python 2.5). Este es un gran inconveniente que actualmente requiere más esfuerzo de desarrollo (encuentre el paquete necesario; verifique la compatibilidad; evalúe elegir un paquete que no sea tan bueno que pueda ser más compatible; tome la mejor versión, actualícela a 3.2, lo que podría llevar días; luego comenzar a hacer algo útil).

Probablemente a mediados de 2012 esto será un inconveniente menor.

Tenga en cuenta que supongo que un fan-boy me votó negativamente. Sin embargo, durante una discusión de desarrolladores, nuestro equipo de desarrolladores de alto nivel llegó a la misma conclusión.

La madurez en un sentido principal significa que un equipo puede usar la tecnología y ponerse en marcha muy rápidamente sin riesgos ocultos (incluidos los problemas de compatibilidad). Los paquetes de Python de terceros y muchas aplicaciones no funcionan en 3.2 para la mayoría de los paquetes de hoy. Esto crea más trabajo de integración, prueba, reimplementación de la tecnología en sí misma en lugar de resolver el problema en cuestión == tecnología menos madura.

Actualización para junio de 2013: Python 3 todavía tiene problemas de madurez. De vez en cuando, un miembro del equipo mencionará un paquete necesario y luego dirá "excepto que es solo para 2.6" (en algunos de estos casos he implementado una solución alternativa a través del socket localhost para usar el paquete solo 2.6 con 2.6, y el resto de nuestras herramientas se quedan con 3.2). Ni siquiera MoinMoin, el wiki de Python puro, está escrito en Python 3.

Jonathan Cline IEEE
fuente
2
Estoy de acuerdo con usted solo si su definición de madurez no es compatible con una versión que es incompatible por diseño .
tshepang
3
Estoy de acuerdo en que las dos transmisiones incompatibles de Python son un problema (aunque es comprensible por qué se hizo), pero no lo veo como un problema de "madurez".
Winston Ewert
La madurez en un sentido significa que un equipo puede usar la tecnología y ponerse en marcha muy rápidamente sin riesgos ocultos (incluidos problemas de compatibilidad). Los paquetes de Python de terceros y muchas aplicaciones no funcionan en 3.2 para la mayoría de los paquetes de hoy. Esto crea más trabajo de integración, prueba, reimplementando la tecnología en sí misma en lugar de resolver el problema en cuestión == tecnología menos madura.
Jonathan Cline IEEE
2
Luego solo usa Python 2.x. Ya sabes ... la versión que todos usan. O lea la documentación de los paquetes durante 2 segundos para averiguar con qué versiones es compatible.
jsternberg
2
"El hecho de que Python 3.0 se haya lanzado durante algún tiempo no significa que sea la versión que debería usar. Python 3.0 y 2.x se están desarrollando al mismo tiempo. Espero que en el futuro todos podamos usar python 3.0, pero por ahora usar 2.x es una buena solución "-> Esa es una forma de decir 500 caracteres: aún no está maduro.
Jonathan Cline IEEE
4

El alcance de Python está muy roto, lo que hace que la programación orientada a objetos en Python sea muy incómoda.

Mason Wheeler
fuente
8
¿Puede dar un ejemplo? (Estoy seguro de que tienes razón, pero me gustaría un ejemplo)
Winston Ewert
24
Me gusta Python pero detesto absolutamente tener que poner self.delante de cada referencia a una propiedad y método de instancia. Hace que sea imposible usar Python para crear un DSL como es tan fácil de hacer en Ruby.
Adam Crossland
35
No me encuentro incómodo, me gusta lo explícito.
Winston Ewert
99
No veo cuál es el problema con el yo explícito. En C ++, Java y D, las personas a menudo hacen explícitas las variables miembro por convención, por ejemplo, al prefijarlas con un guión bajo.
dsimcha
77
Usas self en métodos diferentes de su declaración: def foo (self) pero self.foo (). Encuentro esta mezcla de definición explícita pero material implícito detrás de escena no demasiado bonita.
LennyProgrammers
4

Mis quejas sobre Python:

  • OOP atornillado (ver la respuesta de @ mipadi para más detalles sobre esto)
  • Implementación rota de lambdas
  • Problemas de alcance
  • No hay colecciones persistentes en la biblioteca estándar.
  • Poca susceptibilidad a las DSL integradas
missingfaktor
fuente
¿Por qué el voto negativo?
missingfaktor
No soy el votante negativo, pero ¿puedes explicar por qué crees que el OO está atornillado? Python siempre ha tenido OO, es una parte central del lenguaje.
Daenyth
Ver la respuesta de @ mipadi.
missingfaktor
4

Los modificadores de acceso en Python no son exigibles, lo que dificulta la escritura de código bien estructurado y modularizado.

Supongo que eso es parte del alcance roto de @ Mason, un gran problema en general con este lenguaje. Para el código que se supone que es legible, parece bastante difícil imaginar qué puede y debe estar dentro del alcance y qué valor tendrá en un momento dado: actualmente estoy pensando en pasar del lenguaje Python debido a estos inconvenientes. .

Solo porque "todos somos adultos con consentimiento" no significa que no cometamos errores y que no trabajemos mejor dentro de una estructura sólida, especialmente cuando trabajamos en proyectos complejos: la sangría y los subrayados sin sentido no parecen ser suficientes .

Mikey
fuente
Entonces, la falta de controles de acceso es mala ... ¿pero el alcance explícito de las escrituras variables en cualquier espacio de nombres no local también es malo?
ncoghlan
@ncoghlan: 1 - esa característica es estándar en muchos idiomas modernos, dependiendo de cómo configure su proyecto. 2-Está bajo el control del programador. 3 - no estoy seguro de lo que es tan bueno de eso - puede controlar fácilmente su alcance con algunas configuraciones de proyecto en la mayoría de los idiomas compilados / IDE. Si 'todos somos adultos con consentimiento', deberíamos poder tomar nuestras propias decisiones y ajustar el alcance de acuerdo con nuestro nivel de comodidad particular.
Vector
2
La cuestión es que las personas que solicitan "controles de acceso forzoso" nos piden que eliminemos una de las cosas que hacen de Python un lenguaje de pegamento tan bueno: es deliberadamente difícil para los desarrolladores controlar cómo se usa su código más tarde. ¿Qué parte de la plantilla en los patrones de C ++ y Java existe únicamente para evitar los controles de acceso forzados? Definitivamente puedo entender a las personas que eligen no usar Python por esas razones, pero la aplicación estática nunca será un sustituto de las pruebas rigurosas.
ncoghlan
1
@ncoghlan: para mí, lo mejor de Python es la elegancia de la sintaxis y la concisión: expresividad. Y como dije, el alcance tiene menos que ver con los programadores que se meten con cosas que no deberían que con la estructura y organización del código, por lo que el concepto de 'adultos que consienten' es discutible. Trabajo en proyectos complejos, no en simples utilidades y scripts (el código debe estar cuidadosamente modularizado y estructurado), los modificadores de acceso son una de las formas más importantes de garantizarlo.
Vector
1
Y la revisión de código, el entrenamiento y el análisis de acoplamiento son otros. Para mí, los controles de acceso forzoso caen en la misma categoría que la escritura estática: ayudan a proporcionar cierta confianza adicional en la corrección (pero no lo suficiente como para evitar la necesidad de realizar pruebas exhaustivas), pero a un alto costo en la productividad del desarrollo. (En un nivel práctico, los controles de acceso a los atributos de clase tampoco se ajustan al modelo de objetos de Python donde los métodos son funciones ordinarias recuperadas de las clases. El límite "interior / exterior" para las clases realmente no existe, por lo que no puede ser forzado)
ncoghlan
3
  1. El rendimiento no es bueno, pero está mejorando con pypy,
  2. El GIL evita el uso de subprocesos para acelerar el código (aunque esto suele ser una optimización prematura),
  3. Solo es útil para la programación de aplicaciones,

Pero tiene algunas excelentes características de rescate:

  1. Es perfecto para RAD,
  2. Es fácil interactuar con C (y para que C incorpore un intérprete de Python),
  3. Es muy legible
  4. Es fácil de aprender
  5. Está bien documentado
  6. Las baterías realmente están incluidas, su biblioteca estándar es enorme y pypi contiene módulos para prácticamente todo,
  7. Tiene una comunidad saludable.
dan_waterworth
fuente
¿Qué inspiró a mencionar las ventajas? La pregunta por los problemas. De todos modos, ¿qué quiere decir que es útil solo para la programación de aplicaciones? ¿Qué otra programación hay? ¿Para qué específicamente no es bueno?
tshepang
55
Enumeré las ventajas porque creo que superan las desventajas. ¿Alguna vez ha intentado implementar un módulo de kernel de Linux en Python?
dan_waterworth
3

Estoy a favor de Python y la primera desventaja que me viene a la mente es que cuando comento una declaración como if myTest():esta, debe cambiar la sangría de todo el bloque ejecutado que no tendría que ver con C o Java. De hecho, en Python, en lugar de comentar una cláusula if, comencé a comentarlo de esta manera: `if True: #myTest (), por lo que no tendré que cambiar el siguiente bloque de código. Como Java y C no dependen de la sangría, hace que comentar las declaraciones sea más fácil con C y Java.

Niklas Rosencrantz
fuente
1
¿Editaría seriamente el código C o Java para cambiar el nivel de bloque de algún código sin cambiar su sangría?
Ben
44
@Ben Temporalmente, sí ...
alternativa
1
@ben lo mismo aquí.
Christopher Mahan
2
Yo uso el truco de cambiar if something()a if False and something(). Otro truco es "comentar" con una cadena de varias líneas.
Martin Vilcans
1
@ Martin por supuesto! if False ...
Christopher Mahan
3

El despacho múltiple no se integra bien con el sistema de tipo de despacho único establecido y no es muy eficiente.

La carga dinámica es un problema enorme en sistemas de archivos paralelos donde la semántica similar a POSIX conduce a ralentizaciones catastróficas para operaciones intensivas en metadatos. Tengo colegas que han quemado un cuarto de millón de horas centrales con solo cargar Python (con numpy, mpi4py, petsc4py y otros módulos de extensión) en 65k núcleos. (La simulación arrojó nuevos resultados científicos significativos, por lo que valió la pena, pero es un problema cuando se quema más de un barril de petróleo para cargar Python una vez). La incapacidad de vincular estáticamente nos ha obligado a ir a grandes contorsiones para tiempos de carga razonables a escala, incluyendo parchear libc-rtld para dlopenrealizar el acceso al sistema de archivos colectivo.

Jed
fuente
Wow, parece altamente técnico, ¿tiene algún material de referencia, ejemplos, publicaciones de blog o artículos sobre el tema? Me pregunto si podría estar expuesto a tales casos en un futuro cercano.
vincent
Aron dio una charla en SciPy 2012 . El dlopenmaterial está en nuestra biblioteca collfs . Ese repositorio también contiene trucos zipimport adicionales inspirados en el almacenamiento en caché de ruta de Asher Langton. Estamos trabajando en una mejor distribución y un papel.
Jed
3
  • un buen número de bibliotecas y software de terceros muy convencionales que son ampliamente utilizados, no son pitónicos. Algunos ejemplos: soaplib, openerp, reportlab. La crítica está fuera de alcance, está allí, se usa ampliamente, pero hace que la cultura de las pitones sea confusa (daña el lema que dice "Debería haber una, y preferiblemente solo una, forma obvia de hacerlo"). Los éxitos pitónicos conocidos (como django o trac) parecen ser la excepción.
  • La profundidad de abstracción potencialmente ilimitada de instancia, clase, metaclase es conceptualmente hermosa y única. Pero para dominarlo, debe conocer profundamente al intérprete (en qué orden se interpreta el código de Python, etc.). No es ampliamente conocido y utilizado (o utilizado correctamente), mientras que la magia negra similar, como los genéricos de C #, que es conceptualmente más complicada (en mi humilde opinión) parece más conocida y utilizada, proporcionalmente.
  • Para obtener una buena comprensión de la memoria y el modelo de subprocesos, debe tener bastante experiencia con Python, porque no hay especificaciones completas. Simplemente sabe lo que funciona, tal vez porque leyó las fuentes del intérprete o experimentó caprichos y descubrió cómo solucionarlos. Por ejemplo, solo hay referencias fuertes o débiles, no las referencias suaves y fantasmas de Java. Java tiene un hilo para la recolección de basura, mientras que no hay una respuesta formal sobre cuándo ocurre la recolección de basura en python; puede observar que la recolección de basura no ocurre si no se ejecuta ningún código de Python, y concluir que probablemente suceda a veces al intentar asignar memoria. Puede ser complicado cuando no sabes por qué no se lanzó un recurso bloqueado (mi experiencia al respecto fue mod_python en freeswitch).

De todos modos, Python es mi idioma principal desde hace 4 años. Ser fanboys, elitistas o monomaníacos no es parte de la cultura python.

vincent
fuente
+1. La especificación para el modelo de memoria y subprocesamiento está en marcha Pero FWIW, el recolector de basura de Java que se encuentra en un hilo (y casi todo lo demás sobre el GC) no es un aspecto del lenguaje Java o las especificaciones de VM en sí, sino que es una cuestión de la implementación de una JVM particular. Sin embargo, la JVM principal de Sun / Oracle está ampliamente documentada con respecto al comportamiento y la configuración de GC, en la medida en que hay libros completos publicados sobre el ajuste de JVM. En teoría, uno podría documentar CPython de la misma manera, independientemente de las especificaciones del idioma.
Andrew Janke
2
  • Extraña POO:
    • len(s)a través __len__(self)y otros "métodos especiales"
    • métodos extra especiales que podrían derivarse de otros métodos especiales ( __add__y __iadd__para +y +=)
    • self como primer parámetro del método
    • puedes olvidarte de llamar al constructor de la clase base
    • sin modificadores de acceso (privado, protegido ...)
  • sin definiciones constantes
  • sin inmutabilidad para tipos personalizados
  • GIL
  • bajo rendimiento que conduce a una mezcla de Python y C y problemas con las compilaciones (en busca de bibliotecas C, dependencias de la plataforma ...)
  • mala documentación, especialmente en librerías de terceros
  • incompatibilidad entre Python 2.xy 3.x
  • herramientas de análisis de código deficientes (en comparación con lo que se ofrece para lenguajes tipados estáticamente como Java o C #)
deamon
fuente
55
Personalmente, creo que la incompatibilidad entre 2.xy 3.x es una de las mayores ventajas de Python. Claro, también es una desventaja. Pero la audacia de los desarrolladores para romper la compatibilidad con versiones anteriores también significa que no tuvieron que cargar sin parar. Más idiomas necesitan tal revisión.
Konrad Rudolph
0

"Inmutabilidad" no es exactamente su punto fuerte. Los números AFAIK, las tuplas y las cadenas son inmutables, todo lo demás (es decir, los objetos) es mutable. Compare eso con lenguajes funcionales como Erlang o Haskell, donde todo es inmutable (al menos por defecto).

Sin embargo, la inmutabilidad realmente brilla con la concurrencia *, que tampoco es el punto fuerte de Python, por lo que al menos es consecuente.

(* = Para los nitpickers: me refiero a la concurrencia que es al menos parcialmente paralela. Creo que Python está bien con la concurrencia de "subproceso único", en la que la inmutabilidad no es tan importante. (Sí, amantes de FP, sé que la inmutabilidad es genial incluso sin concurrencia.))

Kosta
fuente
0

Me encantaría tener construcciones explícitamente paralelas. Más a menudo que no, cuando escribo una lista de comprensión como

[ f(x) for x in lots_of_sx ]

No me importa el orden en que se procesarán los elementos. A veces, ni siquiera me importa en qué orden se devuelven.

Incluso si CPython no puede hacerlo bien cuando mi f es Python puro, un comportamiento como este podría definirse para que otras implementaciones lo usen.

rbanffy
fuente
// genera grupos de subprocesos // pasa Queue queue a todos los subprocesos que.extend ([x para x en lots_of_sx]) que.wait () # Espera a que los subprocesos procesen todos los lots_of_sx.
Zoran Pavlovic
0

Python no tiene optimización de llamadas de cola, principalmente por razones filosóficas . Esto significa que el recursivo de cola en estructuras grandes puede costar memoria O (n) (debido a la pila innecesaria que se mantiene) y requerirá que reescriba la recursión como un bucle para obtener memoria O (1).

a3nm
fuente