[PARTE 1] ¡Aprende Python Avanzado!

Iniciado por Mortal_Poison, Noviembre 04, 2017, 09:35:00 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Noviembre 04, 2017, 09:35:00 PM Ultima modificación: Noviembre 04, 2017, 09:42:54 PM por Mortal_Poison

Hola a tod@s,

Hoy les traigo un aporte de Python Avanzado,donde asumo que ya conocen y tienen buenas bases de Python. Estos tutoriales también los llevaré a mi canal donde los explicaré con voz, por si a alguien le interesa. Además de eso, también mostraré las vulnerabilidades que se cometen cuando se programan en éstos lenguajes de Scripting, ya sea PHP, Python(con sus frameworks) y entre otros(será en otro hilo).

Comencemos...


Ilustración 1. Guido van Rossum

No sé ustedes, pero yo vi esa imagen y se me vino a la mente Kevin Mitnick(por su parecido físico xd).

Por la década de los 80's, cuando se creo éste lenguaje de scripting que muchos amamos, comenzó a evolucionar con su misma filosofía: proporcionar un lenguaje de programación que fuera multiparadigma con legibilidad y productividad. La cuestión es, la gente solía ver a Python como un lenguaje de Scripting y no como lo anterior. Sin embargo, las empresas pioneras en ese entonces, notaron que con Python podían construir cualquier tipo de sistema. Y así fue como se convirtió en lo que hoy conocemos: en un lenguaje de Scripting.

Cabe aclarar que abarcaré todo desde la última versión de Python, la 3.x.x.

Python 3, a pesar de sus nuevas y emocionantes características, todavía no es adoptado en la comunidad. Notemos en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta donde observamos la compatibilidad de los paquetes más populares en Python 3, fue llamada Python 3 Wall Of Shame. Es un poco triste, pero esto pasa con cualquier versión de cualquier lenguaje de programación: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Esta situación está cambiando poco a poco, de hecho, si notan, en la página los paquetes enumerados se están poniendo de color verde, precisamente porque se está avanzando en este aspecto.

La gente suele comentar: "los paquetes de Python 2 a la versión de Python 3 no se encuentran". Pues cuando la página esté totalmente verde como un trébol, ésta gente no tendrá excusa para aprovechar el máximo potencial de la versión de Python 3. A pesar de todo, tienen razón. He desarrollado herramientas(que son privadas pero que he presentado en conferencias) que están en Python 2.x por su compatibilidad. El problema radica en que, permutar una aplicación existente en Python 2.x a Python 3.x resulta un completo problema. Pero como existen páginas para convertir migraciones de Oracle a Mysql, también las hay en Python. Claro está, esto no garantiza un 100% de que todo funcionará correctamente(porque lo he comprobado) sino más bien de migrarlo y verificar todo de nuevo. La herramienta para transformar el código de Python 2.x a Python 3.x se llama No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Ilustración 2. Mongomering Berns aludiendo a las empresas.

Ahora imaginen, si a mi me cuesta un poco, a las organizaciones un proceso como esos les va a costar el doble o incluso el triple, y eso ellas no lo pueden permitir.


Ilustración 3. Arquitecto de Software.

Sin embargo, realizar un cambio de estos lo podemos hacer mediante metodologías de diseños de arquitectura de software, como por ejemplo la orientada a No tienes permitido ver los links. Registrarse o Entrar a mi cuenta o No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, donde se puede conseguir un objetivo bastante grande y con muy buenos resultados. No me centraré en cuáles diseños de Arquitectura de Software existen, de esto, existen estudios hasta posdoctorados.

Sin embargo, yo recomendaría a las empresas hacerlo, los beneficios que trae Python 3 es verdaderamente fabuloso. Basémonos en el No tienes permitido ver los links. Registrarse o Entrar a mi cuenta éste es el que nos indica qué va a ocurrir con Python 2 y por qué migrar a Python 3. Se comenta en el artículo que ya no habrá versión 2.8 en la versión de Python y que además, en un momento determinado a posteriori, proyectos principales como Django, Numpy y Flask eliminarán la compatibilidad con la versión 2.x y solo estarán disponibles en la versión 3. Es un aspecto muy importante que quería tocar, por el hecho que muchos de los desarrolladores se abstienen a migrar a una versión de Python 3.

Principales diferencias entre Python 2 y Python 3

Mostraré las principales diferencias que existen con ejemplos, recordando a un amigo que una vez me dijo: "ese código no sirve, da error por todo". Lo que no se dió cuenta, era que estaba en Python 3 y no en Python 2.

Para los que no estén familiarizados, por favor remitirse al siguiente No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


  • Cambios de Sintaxis.
  • Cambios de librerías.
  • Cambios de tipos de datos y también de colecciones.

Comencemos por los cambios de sintaxis, en Python 2 imprimir un mensaje sería lo siguiente:
Código: python
print "El mundo caerá en caos"


Mientras que en Python 3:
Código: python
print("El mundo caerá en caos")


Obviamente, si intentamos ejecutar con Python 2 el código de Python 3, nos generará error y viceversa.


Ilustración 4. Ejecutando con Python 3 un mensaje con la sintaxis de Python 2.

Esa es una de las diferencias, además de:
print ya no es una declaración sino una función, esa es la razón por lo que el paréntesis ahora es obligatorio.
➡ Las excepciones cambiaron: from except exc, var a except, exc como var.
➡ El operador de comparación <> ha sido removido y cambiado a !=.
➡ La función sort() y las listas con método sorted() ya no aceptan el argumento No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
➡ Las expresiones de divisiones entre enteros como por ejemplo 3/2, retornará flotantes. Para ello debemos usar el operador //. Esto es muy bueno, porque podemos hacer una división como: 10//7 y el resultado será 1.

Compatibilidades entre versiones

Realmente se torna complicado cuando queremos hacer esto. Sin embargo, vale la pena. La mejor manera hasta ahora para definir cómo puede cambiar la compatibilidad en el futuro es mediante No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

SemVer describe un estándar que es ampliamente aceptado a nivel mundial para marcar el alcance del cambio en el código mediante el especificador de la versión que consiste en solo tres números. También ofrece algunos consejos de cómo manejar las políticas para desaprobar esto. Podemos obtener más detalles en su página oficial, donde nos indica el formato MAYOR, MENOR o PATCH dependiendo el número de versión.

La compatibilidad muchas veces la podemos agregar en un fichero llamado No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, de hecho, hay mucha información acerca de esto:
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Si vemos el código de No tienes permitido ver los links. Registrarse o Entrar a mi cuenta en el proyecto de GitHub, nos damos cuenta que es de la siguiente forma:

Código: python
# -*- coding: utf-8 -*-
import sys
## Condición para verificar la versión de Python.
if sys.version_info < (3, 0, 0):
    import urlparse  # Si es menor a la 3.0

    def is_string(s):
        return isinstance(s, basestring)  # noqa
## Sino, usamos la librería de Python 3.
else:
    from urllib import parse as urlparse  # noqa

    def is_string(s):
        return isinstance(s, str)


Esa es una forma muy conveniente para las dependencias de librerías y asumir la compatiblidad en nuestros proyectos de Python.

Hablemos de Jython


Ilustración 5. Logo de Jython.

Nos permite usar sin problemas las clases de Java dentro de nuestros módulos de Python. No tienes permitido ver los links. Registrarse o Entrar a mi cuenta  utilizar sin problemas las clases de Java dentro de sus módulos de Python. Tenemos que Jython es multiplataforma, posee velocidad y memoria y además, también tiene sincronismo multihilo. No tienes permitido ver los links. Registrarse o Entrar a mi cuenta uno de los frameworks también está intentando promover e incentivar para que Jython se encuentre en el mundo de Java.

Hablemos de IronPython


Ilustración 6. Logo de IronPython.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta nos permite integrar Python al Framework de .NET. El proyecto es apoyado por Microsoft, donde trabajan los desarrolladores líderes de IronPython. Es una implementación bastante importante para la promoción de un idioma. Además de Java que posee una de las comunidades desarrolladoras más grandes que existen, .NET no es la excepción. También creo que vale la pena resaltar que Microsoft proporciona un conjunto de herramientas de desarrollo gratuitas que convierten a Visual Studio en un IDE de Python completo. Esto se logra con plugins desarrollados como PVTS(Python Tools for Visual Studio) de Visual Studio y está disponible como código fuente abierto. Lo puedes descargar del siguiente No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Hablemos de PyPy


Ilustración 7. Logo de PyPy.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta es probablemente una de las implementación más emocionantes, ya que su objetivo es volver a escribir código Python en Python. En PyPy, el intérprete de Python está escrito en Python. Tenemos una capa de código C que lleva a cabo el trabajo de nuts and bolts para la implementación CPython de Python. Sin embargo, en la implementación de PyPy, esta capa de código C se reescribe totalmente en Python puro. ¿Qué significa esto? significa que puede cambiar el comportamiento del intérprete durante el tiempo de ejecución e implementar patrones de código que no podrían hacerse fácilmente en CPython. En la actualidad, PyPy apunta a ser totalmente compatible con la versión de Python 2.7, mientras que PyPy3 es compatible con la versión de Python 3.2.5.

Command Shells para Python

Existen varios, sabemos que python al instalarlo trae un command line, sin embargo, aquí van otros.

bpython

bpython posee una interfaz elegante para el intérprete de Python. Éstos son algunos de las cosas que podemos obtener con bpython:
• Resaltado de sintaxis en línea
• Autocompletar similar a Readline con sugerencias que se muestran a medida que escribe
• Autoindentación(para las personas que dicen que odian python por su indentación  ::) )
• Soporte de Python 3
• Listas de parámetros esperados para cualquier función de Python

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


iPython

IPyhton (No tienes permitido ver los links. Registrarse o Entrar a mi cuenta) proporciona un shell de comandos de Python extendido. Entre sus características, enumeraré las que son más interesantes:
• Introspección dinámica de objetos
• Acceso al shell del sistema desde el prompt
• Soporte directo de creación de perfiles
• Instalaciones de depuración

Ahora, IPython es una parte del proyecto más grande conocido como No tienes permitido ver los links. Registrarse o Entrar a mi cuenta que proporciona notebooks interactivos con código en vivo que puede ser escrito en muchos idiomas distintos.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

ptpython

ptpython es un proyecto open source, la implementación de las utilidades básicas del núcleo está disponible como un paquete separado llamado prompt_toolkit. Esto permite crear varias interfaces interactivas de línea de comandos que estéticamente son agradables. A menudo se suele comparar con bpython en el aspecto de funcionaldiades, pero la principal diferencia es que habilita un modo de compatibilidad con IPython y su sintaxis habilita características adicionales como %pdb,%cpaste o %perfil.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Para finalizar les comentaré de varios debuggers que uso cuando me estoy dando cabezasos contra la pared al no encontrar por qué me sale error :-\.

Debugging In Python

La depuración de código es un elemento esencial en el proceso de desarrollo de software. Muchos programadores/desarrolladores pueden pasar la mayor parte de su vida utilizando únicamente registros extensos como sus principales herramientas de depuración, pero la mayoría de los desarrolladores profesionales prefieren confiar en algún tipo de depurador para sus tareas diarias. Python, ya viene con un depurador interactivo incorporado llamado pdb, para los que no lo conocían, pueden consultar en el siguiente No tienes permitido ver los links. Registrarse o Entrar a mi cuentamás información. Se puede invocar desde la línea de comandos en el script existente, por lo que Python ingresará a la depuración post-mortem si el programa sale anormalmente(muy común xd):

Código: python
python -m pdb Mortal_Poison.py


Éste tipo de depuración post-mortem si bien es útil, no abarca todos los escenarios. Pragmáticamente solo es útil cuando la aplicación existente posee alguna excepción si se produce el error. En muchos casos, el código defectuoso se comporta de forma anormal pero no se cierra inesperadamente(no sé si se acuerden de lo de los temas de errores en tiempo de ejecución / compilación). En esos casos, podemos indicarle a el debugger que se establezca en una línea de código específica, para ello usamos:

Código: python
import pdb; pdb.set_trace()


Esto hará que el intérprete de Python inicie la sesión del depurador en esa línea de cñidugi, Es muy útil cuando tenemos problemas de localizar y a primera vista, también nos es muy familair con el depurador de GNU(GDB). Como sabemos, Python es un lenguaje dinámico y la sesión de pdb es muy similar a una sesión de intérprete ordinaria. Es decir, el desarrollador no solo se limita a localizar el código debuggeado sino que también puede realizar importaciones a módulos o también, invocar cualquier código.

Lamentablemente, la primera experiencia con pdb puede ser un poco abrumadora y frustante, debido a la existencia de comandos crípticos de depuración de letras cortas como h, b, s, n, j y r. En caso de duda, el comando help pdb escrito durante la sesión del depurador proporcionará un uso extenso e información adicional que nos proporcionará ayuda. La sesión del depurador en pdb también es muy simple y no proporciona funciones adicionales, como la finalización de pestañas o el resaltado del código. Afortunadamente, hay pocos paquetes disponibles en PyPI que proporcionen tales características disponibles a partir de shells de Python alternativos mencionados anteriormente.

Los ejemplos más notables son:
• No tienes permitido ver los links. Registrarse o Entrar a mi cuenta: Paquete separado basado en iPython.
• No tienes permitido ver los links. Registrarse o Entrar a mi cuenta: Paquete separado basado en ptpython.
• No tienes permitido ver los links. Registrarse o Entrar a mi cuenta: Incluido con bpython.

Si desean mucha más información acerca de esto, podemos recurrir a la No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Además de eso, también existen otros debuggers que he tenido la oportunidad de usar y son los siguientes:


Ahora si vamos a lo que nos compete.




La capacidad de escribir código de una manera eficiente yo diría que viene naturalmente con el tiempo. Me acuerdo que al principio, escribía el código todo en la clase principal o solo en un archivo. Luego aprendí conceptos que me sirvieron para ser mejor coder, como herencia, abstracción, a organizar por paquetes/módulos, entre otr@s. Vamos, recuerda tu primer programa, te aseguro que será como el mío, dan ganas de llorar :'(. Sin entrar en detalles, cuando se poseen programas con sintaxis obtusa, API's poco claras o estándares poco convenciales, es cuando entramos a mejorar. Python desde su versión más antigua hasta la versión actual(3.6.3) ha realizado muchísimas mejores en el lenguaje, para que sea más claro, más comprendible, más limpio y mucho más fácil de escribir. Les enseñaré:

• contextlib y with.
• Comprensión de listas.
• Iteradores y generadores.
• Descriptores y propiedades.
• Los Decoradores.

Python como sabrán, nos proporciona un gran conjunto de tipo de datos. De la misma forma que es para las colecciones, lo es para los tipos numéricos.
Existen algunas diferencias poco conocidas por los desarrolladores, pero no tienes más opción que aprender. Las cosas cambia cuando se trata entre colecciones y strings(cadenas). Quisiera mencionar que algunos patrones de código que parecen intuitivos y simples para los principantes(newbies) generalmente son considerados no-pythonics(no pythónicos) por los programadores más experimentados porque son ineficientes o son muy detallados. Patrones como por ejemplo: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta que es usado para resolver problemas comunes, a menudo parecen ser solo estética. Realmente está mal. Como siempre, estaremos sujetos en que la comunidad de Python esté lleno de mitos y estereotipos de cómo funcionan las cosas. Sin embargo, profundizando solo tú y nadie más que tú, podrás saber cuáles de las declaraciones que se hacen realmente son ciertas y objetar las demás.

El tema de las strings o cadenas puede resultar cierta confusión para los programadores que están acostumbrados a programar solo en la versión de Python 2. En Python 3, SOLO hay un tipo de datos capaz de almacenar información textual. Es str o simplemente, string. Es una secuencia inmutable que almacena puntos de código UNICODE. Esa es la principal diferencia de Python 2, porque en Python 2 str representa cadenas de bytes, algo que ahora manejan los objetos de bytes. Las cadenas en Python son secuencias. Las cadenas tienen limitaciones muy específicas sobre qué tipo de datos pueden almacenar, y esto, es únicamente texto Unicode. bytes y su alternativa mutable (No tienes permitido ver los links. Registrarse o Entrar a mi cuenta) difiere de str al permitir solo bytes como un valor de secuencia-enteros en el rango 0 <= x <256. Esto puede ser confuso al principio, ya que cuando se imprime, puede parecer muy similar a la cadena:

Código: python
print(bytes([109, 111, 114, 116, 97, 108]))




Ilustración 8. Resultado de el anterior print.

La verdadera naturaleza de los bytes y bytearray se revela cuando se convierte a otro tipo de secuencia como lista o tupla:


Ilustración 9. Apreciando las diferencias.

Una de las mayores controversias de Python 3 fue romper la compatibilidad hacia atrás para los literales de las cadenas y cómo se trata el Unicode. A partir de Python 3, cada literal de cadena sin prefijo es Unicode. Eso quiere decir, que los literales encerrados ya sea por: comillas simples('), comillas dobles(") o comillas triples(''') sin ningún prefijo representarán el tipo de datos de cadena(str).


Ilustración 10. Verificando que se toma como Unicode lo mencionado arriba.

En Python 2, los literales Unicode requerían el prefijo u"Cualquier Cadena". Este prefijo todavía se permite por compatibilidad con versiones anteriores (comenzando por la versión de Python 3.3), pero no tiene ningún significado sintáctico en Python 3. Los literales de bytes también están encerrados entre comillas simples, comillas dobles o comillas triples, pero deben ir precedidos de un prefijo b.


Ilustración 12. Verificando que se toma como Bytes lo mencionado arriba.

Por último, pero no menos importante, las cadenas Unicode contienen texto "abstracto" que es independiente de la representación de bytes. Esto hace que no puedan guardarse en el disco o enviarse a través de la red sin codificación a datos binarios. Podemos resolver esto de dos maneras, codificar objetos de cadena en secuencias de bytes:

➛ Usando el método str.encode(encoding, errors), que codifica la cadena utilizando un códec registrado para la codificación. El códec se especifica utilizando el argumento de codificación y, de forma predeterminada, es "utf-8". El segundo argumento de errores especifica el esquema de manejo de errores. Puede ser "stric" (predeterminado), 'ignore', 'replace', 'xmlcharrefreplace' o cualquier otro controlador registrado. Puedes consultar más acerca de los códecs en el siguiente No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

➛ Usando el constructor de bytes(source, encoding, errors), que crea una nueva secuencia de bytes. Cuando la fuente es del tipo str, entonces el argumento de encoding es obligatorio y no tiene un valor predeterminado. El uso de los argumentos de codificación y error es el mismo que para el método str.encode().

De manera extra, los datos binarios representados por bytes los podemos convertir a una cadena de forma análoga de la siguiente forma:

➛ Utilizando el método bytes.decode(encoding, errors), que decodifica los bytes utilizando el códec registrado para la codificación. Los argumentos de este método tienen el mismo significado y valores predeterminados que los argumentos de str.encode().

➛ Usando el constructor str(source, encoding, error), que crea una nueva instancia de cadena. Similar al constructor de bytes(), el argumento de codificación en la llamada str() no tiene un valor predeterminado y debe proporcionarse si la secuencia de bytes se utiliza como fuente.

Sabemos que las cadenas de Python son inmutables. Es lo mismo para las secuencias de bytes. Es un hecho importante porque tiene ventajas y desventajas. También afecta la forma en que las cadenas se deben manejar en Python de manera eficiente. Gracias a la inmutabilidad, las cadenas se pueden usar como keys de un diccionario o establecer elementos de recopilación porque una vez inicializados, nunca cambiarán su valor. Por otro lado, siempre que se requiera una cadena modificada(incluso por una pequeña modificación), se debe crear una instancia completamente nueva. Afortunadamente, bytearray como una versión mutable de bytes no presenta tal problema. Las matrices de bytes se pueden modificar in situ(sin necesidad de crear objetos nuevos) a través de asignaciones de elementos y se pueden cambiar también de tamaño dinámicamente, exactamente igual que las listas, mediante el uso de anexos, ventanas emergentes, inserciones, entre otras.

Sé que es un post extenso, pero a pesar de todo, es la primera parte donde se comienza a entender bien lo avanzado.

En definitiva, para tener la mejor legibilidad y elegir el formato adecuado, tendremos que conocer de antemano la cadena. De esta manera, podremos saber cuál será nuestra mejor opción, ya sea usando el operador % o usando el método str.format(). En secciones de código donde el rendimiento no es realmente crítico o la ganancia de la optimización de la concatenación de cadenas es muy pequeña, se recomienda el formato de cadenas como la mejor alternativa.

Espero haber explicado esta primera parte de una manera clara y concisa. Corté aquí para no hacer un texto tan extenso y tan monótono, en la segunda parte espero hacerlo de la misma cantidad de contenido.

Tengo muchas más cosas por dar a conocer, espero y sea de su agrado.

Cualquier duda/sugerencia/comentario es bien recibido.

Un saludo.
[/font]
Become the change you seek in the world. -Gandhi.


Buen aporte, cuando veo mis códigos antiguos cuando estaba aprendiendo Python, me río de la mala optimización que tenia.
Pero con el tiempo se aprende.
No sabia que en Python 2.x se podía usar tambien <> como equivalente a != y eso que siempre me leo la documentación.
Y sobre la incompatibilidad de Python 3 sobre sus versiones anteriores, esta justificada, todo cambia con el tiempo, en realidad, ya estamos en la version de Python 3.7 que esta en beta aún. Pero nos quedaremos con Python 3 un largo tiempo...
Saludos!


Hola No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Así es, concuerdo con lo que mencionas.

Un saludo.
Become the change you seek in the world. -Gandhi.


Super el aporte, siempre es bueno aprender más de este maravilloso lenguaje Python 8)
Cordialmente:
Daniel Rodriguez L.
Ing. Electrónico