¿Cuáles son algunas características de Python que lo hacen único como su propio lenguaje? [cerrado]

12

¿Cuáles son algunas características de Python que lo hacen único como su propio lenguaje? Estoy buscando cualquier tipo de características que van desde buenas a malas, útiles para obstáculos, sintaxis para uso en el mundo real, pero las observaciones no oscuras serían las más útiles para el desarrollador promedio.

Soy un novato aquí, así que las cosas intuitivas pueden necesitar ser explicadas .....

John
fuente
99
Python no es único, no contiene una única característica única que no se ve en ningún otro idioma.
SK-logic
10
Es el único idioma que sé que es el nombre de Monty Python ...
Yannis
@ SK-logic la pregunta es sobre las características, de las cuales las características son un subconjunto. ¿No hay características exclusivas de Python?
kojiro
@kojiro, nunca he visto una definición formal de una "característica", por lo que preferiría no adivinar.
SK-logic
1
@kojiro, las características PL normalmente se entienden como su sintaxis y semántica. Y ambos están formalmente definidos.
SK-logic

Respuestas:

22

Te resultará difícil encontrar características que sean absolutamente únicas . La mayoría de las características del lenguaje existentes se han adoptado en más de un idioma desde su inicio. Algunos pueden ser más raros, principalmente porque son nuevos y todavía están en la oscuridad, o se extinguieron por una buena razón. Sin embargo, incluso entonces sería mejor mirar combinaciones de características.

Dicho esto, varias características de Python deberían hacer una combinación relativamente única. Al menos no conozco ningún idioma remotamente tan popular (y práctico) con un conjunto de características que se superpongan en su mayoría. Como se señaló en los comentarios, Ruby está bastante cerca, pero existen numerosas diferencias.

  • Metaprograma basado en metaclase . Básicamente, ejecutar código arbitrario en la creación de clases. Hace que la personalización de clases sea muy agradable con muy poco trabajo en el extremo receptor, por ejemplo, para un mapeo relacional de objetos (ORM), las clases de cliente se pueden escribir como de costumbre con unas pocas líneas adicionales attr = SomeDataType()y se genera automáticamente una tonelada de código. Un ejemplo de esto son los "modelos" de Django .
  • Te animamos a usar iteradores para todo . Esto es especialmente evidente en 3.x, donde la mayoría de las alternativas basadas en listas con un equivalente basado en iteradores se han abolido a favor de este último. Los iteradores también sirven como una interfaz casi universal para las colecciones (tanto las que realmente tiene en la memoria como las que solo necesita una vez y, por lo tanto, crea con las siguientes funciones). Agnóstico de colección, eficiente en el O(1)espacio (el espacio para resultados intermedios a menudo sigue naturalmente, muy pocas tareas realmente necesitan todos los elementos en la memoria a la vez), el procesamiento de datos componibles nunca ha sido tan fácil.
  • Expresiones generadoras, relacionadas con lo anterior. Muchos habrán oído hablar de las comprensiones de listas (crear una lista desde otro iterable, filtrar y mapear en el proceso, con una sintaxis muy conveniente). Olvídate de ellos, son el azúcar sintáctico, un caso especial. Las expresiones generadoras están muy próximas sintácticamente y, en última instancia, dan como resultado la misma secuencia de elementos, pero producen resultados perezosamente (y, por lo tanto, ocupan O(1)espacio a menos que se guarden explícitamente los resultados).
  • yield, que principalmente hacen que los iteradores de escritura (llamados aquí generadores) sean mucho más agradables. Son el hermano mayor de lo anterior y admiten todo tipo de flujo de control. C # tiene algo similar, con la misma palabra clave. Pero yieldtambién está sobrecargado para soportar un tipo limitado de corutinas (Lua, por ejemplo, tiene un soporte más elaborado) que, sin embargo, ha sido aprovechado por personas inteligentes que trabajan en problemas difíciles. Dos ejemplos en la parte superior de mi cabeza: análisis de descenso recursivo con retroceso y sin límite de pila y E / S asíncrona (con una sintaxis conveniente).
  • Asignación de objetivos múltiples y desempaquetado iterable. Asignación de esteroides. No solo puede asignar a múltiples valores a la vez (incluso para intercambiar valores y al iterar for key, value in mapping.items()), puede desempaquetar cualquier iterable de longitud conocida (honestamente, principalmente tuplas) en múltiples variables. Desde 3.x es aún práctica para las colecciones de longitud desconocida como se puede especificar algunas variables tomando elementos individuales y una toma de lo que queda: first, *everything_in_between, last = values.
  • Descriptores , probablemente la más poderosa entre las diversas formas de personalizar el acceso a los atributos. Hay propiedades (como en C #, pero sin soporte de lenguaje especial), métodos estáticos, métodos de clase, etc., todos implementados como descriptores. También son objetos de primera clase. Hace solo una semana, me enfrenté a un código repetitivo y complicado en las propiedades, por lo que escribí una pequeña función que genera la parte repetitiva y la envuelve en un properyobjeto.
  • Regla puramente fuera de juego (indentación para delimitar bloques). Puse esto último intencionalmente. Si bien distingue a Python, realmente no se destaca en la programación diaria una vez que está acostumbrado (o al menos esa es mi experiencia).
Comunidad
fuente
Todavía soy un poco nuevo en Ruby, pero ¿creo que también llega a todos menos al último punto? De cualquier manera, estoy de acuerdo en que "Python" probablemente no se encuentre en Python, pero "no es común entre otros idiomas principales".
Plataforma
@Rig: No soy un experto en Ruby, pero no he visto ni metaclases (Ruby ciertamente es tan poderoso con respecto a la metaprogramación, y puede usarlo para fines similares, pero mi impresión fue que se logró de manera diferente), ni generadores ni expresiones generadoras. (aunque parece que hay corutinas), ni desempaquetado iterable (aunque hay una asignación de objetivos múltiples) ni descriptores en Ruby. Sí, Ruby y Python se superponen. Pero hay diferencias .
Bien, +1. Para mí, "asignación de esteroides" es en realidad "coincidencia de patrones de los pobres", pero es increíblemente útil :) Sin embargo, también notaría cuán flexible es el paso de parámetros en funciones: *argsy una **kwargsforma indolora de mapear tuplas y dictados a parámetros, etc. .
9000
Creo que el lisp común con CLOS alcanza todos los puntos, excepto el uso de sintaxis basada en el diseño. Haskell no está orientado a objetos (aunque hay extensiones OO), pero aparte del punto de metaclase, creo que coincide con todas estas características.
Jules
3

Supongo que lo único que hace que Python sea único es la combinación particular de características que expone. Esto sería cierto para la mayoría de los lenguajes de programación.

O podría haber una pequeña cosa: no he visto la forma en que Python pasa explícitamente selfcomo un parámetro formal para las funciones de miembro del objeto realizadas en cualquier otro lenguaje. Es una cosa pequeña, y no veo cómo esto realmente cambia nada.

Pero no soy muy fluido en Python, ¡así que seguramente hay cosas que me faltan!

Torbjørn
fuente
@delnan: Ah, me perdí "explícitamente pasar a mí mismo como un parámetro formal" .. Supongo que eso es lo que obtengo por leer a las 2 am;)
Demian Brecht
44
El yo explícito ocurre también en Oberon, fwiw
grrussel
Un parámetro propio explícito también se utiliza en el sistema de objetos lisp común. CLOS proporciona métodos múltiples, sin embargo, lo que significa que el parámetro self no es de ninguna manera especial, como lo es en python.
Jules
1

El procesamiento automático de cadenas de documentos para convertirse en propiedades de su propietario. En general, todas las brillantes funciones de introspección de Python lo convierten en un lenguaje único, desde la capacidad de usar help () hasta la capacidad de usar __doc__como propiedad de primera clase de un objeto. Por ejemplo:

>>> class DocStringException(Exception):
...     """Error message is the same as docstring"""
...     def __str__(self):
...         return repr(self.__doc__)
... 
>>> class ExampleException(DocStringException):
...     """An example happened"""
... 
>>> raise ExampleException
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.ExampleException: 'An example happened'

Otras características útiles de introspección:

  • help / help () - ayuda con el intérprete / ayuda con un objeto
  • palabras clave - palabras clave de python
  • locals () - obtiene los nombres locales
  • globals () - obtiene los nombres globales
  • dir () - obtiene las propiedades y métodos de un objeto
  • El método .mro. , issubclass - entendiendo la herencia
  • id () - obtiene la dirección de memoria de un objeto
kojiro
fuente
Ruby tiene el mismo poder, al igual que Common Lisp, Clojure y muchos otros lenguajes dinámicos, creo.
Torbjørn
@ Torbjørn qué poder? ¿La documentación automática o las características de introspección?
kojiro
Estaba pensando en ambos. No exactamente lo que digo, sino en espíritu. No creo que Ruby tenga las mismas habilidades de documentación, pero la introspección es segura. CL y Clojure tienen ambas características, y creo que la introspección allí va mucho más allá de lo que encontrarás en Python, ya que es homoicónica .
Torbjørn
1
  1. Generator Expressions
  2. input()Permítanme explicar, no he visto un lenguaje (hasta ahora), donde puede asignar un valor a una declaración que imprime algo, es como el rubí print/gets, pero con un valor asignado a la impresión, en lugar de:print "Foo" bar = gets
  3. yield
  4. Muchos tipos de conjuntos de datos: ordereddict, namedtuple, array, list, tuple, dictionary
Billjk
fuente
Las expresiones generadoras se pueden implementar en Haskell utilizando comprensiones de listas (las listas de Haskell son perezosas, a diferencia de las listas de Python, por lo que no se necesita una sintaxis específica para esto). Por "entrada" supongo que te refieres a la función python 3 de ese nombre (ya que la función python 2 es peligrosa y no debe usarse). Es cierto que esta es una combinación inusual de comportamiento (aunque está presente en javascript - window.prompt - y BASIC, que es donde supongo que Python lo tomó prestado), pero el programador puede implementarlo trivialmente ("input s = putStrLn s >> getStrLn "lo hará para haskell).
Jules
Un lenguaje perezoso como Haskell realmente no necesita rendimiento: solo puede devolver una lista creada utilizando los métodos habituales, y los artículos se generarán a pedido. A pesar de esto, la biblioteca incluye una implementación explícita de corutinas. La biblioteca estándar de Haskell contiene todas las estructuras de datos mencionadas y muchas más.
Jules
-2

La cuestión es que Python se encuentra entre muy pocos lenguajes con una sobrecarga sintáctica extremadamente baja que le otorga enormes poderes expresivos: comprensión de listas / conjuntos / dictados, rendimiento, decoradores, evaluación, programación de metaclases, introspección, estructuras de datos integradas optimizadas (listas, dicts, sets), todas esas cosas conspiran de una manera muy agradable para darle (al desarrollador) el poder de expresar sus pensamientos en un código conciso y elegante casi tan rápido como pueda pensar. Realmente no puedo pensar en ningún otro idioma con este conjunto de características asesinas combinadas.

Rabih
fuente
1
Si cree que Python tiene una sobrecarga sintáctica baja (a pesar de tener una gramática obscenamente complicada y una cantidad relativamente grande de azúcar de sintaxis), ¿qué piensa de Scheme?
Tikhon Jelvis
Eval realmente no debería usarse para ningún programa de producción (aunque lo reconozco puede ser útil para hacks rápidos). Como se muestra en los comentarios para otras preguntas, Python no es en absoluto único en tener estas características. Creo, por ejemplo, que clojure tiene todas las características que enumeras, y la mayoría se puede hacer con lisp común.
Jules
-4

Yo diría que es uso de sangría para encerrar sentencias y bucles. No he visto eso en ningún otro idioma.

¡Creo que es muy útil porque hace que sea mucho más difícil ofuscar el código de Python!

También parece ejecutarse de manera ordenada línea por línea con la excepción de las funciones, y también puede interpretarse como tal, lo cual es bueno.

Liang
fuente
2
Wikipedia conoce una pantalla llena de idiomas que también lo hacen. Se llama la regla de fuera de juego .
3
No entiendo. También parece ejecutarse de manera ordenada línea por línea con la excepción de las funciones, y también puede interpretarse como tal, lo cual es bueno. Qué significa eso?
kojiro