¿Cómo contratar al mejor desarrollador Python?

Indice del contenido

(Identificar al mejor desarrollador Python freelancer )

Enlace al articulo original: 11 Best Freelancer Python Developers for Hire in feb 2020 – TopTal

Si hay algo que no es fácil en estos días es contratar un desarrollador Python que cumpla con nuestras exigencias a un nivel profesional destacable, debido a su gran popularidad en auge. Según Giles Thomas (Co-fundador de PythonAnywhere) se estima en el mundo entre 1.8 y 4.3 millones de desarrolladores Python. Por lo que se nos dificultaría mucho encontrar un verdadero experto en este lenguaje más allá de la infinidad de programadores que podrían incluirlo en su curriculum. Por eso he decido traducir y enlazar un articulo que ha publicado recientemente Toptal con una serie de preguntas del tipo test para identificar a un verdadero gurú de Python!. Ya sea que pienses en contratar un desarrollador Python o que quieras convertirte en un experto del lenguaje creo que deberías tenerlas en cuenta.

Te conecta con el 3% de los mejores desarrolladores

Toptal es una startup de tecnología de Silicon Valley, Estados Unidos.​ Ofrece al mercado ingenieros de software y diseñadores con gran experiencia para empresas que necesitan de talentos freelance.

El desafío para identificar un verdadero desarrollador Python

Ciertamente no resultará difícil encontrar un desarrollador python que pueda legítimamente incluir este lenguaje en sus habilidades a la hora de postularse como desarrollador o programador. Pero si nuestro objetivo es encontrar uno que domine los matices y el verdadero poder del lenguaje entonces se nos podría tornar un poco más difícil.

Al igual que si eres un gurú del lenguaje y quieres postularte para un puesto que así lo requiera deberías tener en cuenta primeramente el articulo que han redactado “En busca de la elite: encontrar y contratar a los mejores desarrolladores de la industria”.

Y complementarlo con el desafío para programadores Python basado en preguntas y técnicas especificas a evaluar para diferenciar un verdadero experto del lenguaje de un simple novato. Porque sabemos que si se pretende encontrar al 1 % de los mejores desarrolladores se debe aplicar un filtro antes de la contratación para quedarnos solo con los mejores candidatos, aunque este desafío no nos asegura un candidato “A” seguramente nos brindará una especie de guía para acercarnos lo más posible.

Cuestionario para identificar un verdadero desarrollador Python

Un buen desarrollador Python normalmente no pierde tiempo aprendiéndose de memoria instrucciones que puede encontrar en cualquier documentación especifica de una API u Framework. Pero sin duda hay ciertos conceptos, características y fundamentos claves del lenguaje en los que se espera el candidato se encuentre bien instruido. Por ejemplo:

¿Porqué utilizar decoradores de funciones?. Ejemplificar

Entrevista desarrollador Python

(Recordarás hablamos de los decoradores de funciones y su importancia a la hora de ahorrar código y permitirnos su re-utilización.)

Un decorador es esencialmente un objeto Python invocable que se utiliza para modificar o ampliar una función o definición de clase. Una de las bellezas de los decoradores es que se puede aplicar una sola definición de decorador a múltiples funciones o clases. Por lo tanto, se puede lograr mucho con decoradores que de otro modo requerirían una gran cantidad de código repetitivo o redundante. Flask, por ejemplo, usa decoradores como mecanismo para agregar nuevos puntos finales a una aplicación web. Los ejemplos de algunos de los usos más comunes de los decoradores incluyen agregar sincronización, aplicación de tipo, registro o condiciones previas / posteriores a una clase o función.

requisitos desarrollador PythonUn desarrollador Python que no recurra a decoradores probablemente carece de teoría respecto a los beneficios  y fundamentos del lenguaje. Puesto que una de las principales ventajas de Python es la posibilidad de crear un código legible pero que a su vez ahorre tiempo de desarrollo y recursos, facilitando su comprensión e implementación. Desperdiciando así también la oportunidad de desarrollar un código fuente mantenible.

Pregunta para el desarrollador Python: ¿Qué son las expresiones lambda, las compresiones de listas y las expresiones generadoras?. ¿Cuales son las ventajas y el uso apropiado de cada una?

Python DeveloperUna pregunta que desde luego asustaría mucho en una entrevista por la gran cantidad de teoría a exponer como respuesta haciéndola sobre todo amplia y enredada. Pero enfocándonos en conservar un orden en el momento de la respuesta nos brinda la posibilidad de sobresalir recordando que la comprensión y el uso adecuado de cada uno de estos puntos son un factor clave del lenguaje Python y otorgan un gran beneficio al programador.

Partiendo de las expresiones lambda recordemos que son una forma abreviada de crear funciones anónimas de una sola linea. Su naturaleza simple a menudo conduce a un código más legible y conciso que la alternativa clásica de declaración de funciones formales. Pero por otro lado es preciso recordar que al ser tan simples reducen mucho su capacidad y aplicación. Por ende, al ser anónima es obvio que la única forma de volver a utilizarla es volviéndola a escribir por lo que estaríamos creando código redundante (en dicho caso). Esto quiere decir que en caso de necesitar recurrir a una función de este tipo numerosas veces nos seria más propicio declararla como una función formal a llamar cuando sea preciso.

Las comprensiones de listas proporcionan una sintaxis concisa a la hora de crear listas. Las listas por comprensión se utilizan a menudo para crear listas a partir de elementos que son resultado de operaciones aplicadas a cada miembro de otra secuencia o iterables pudiendo establecer una condición. Las comprensiones de listas proporcionan una alternativa al uso de funciones incorporadas en el lenguaje como filter() y map().

¿Pero cuando utilizar comprensiones de listas y cuando recurrir a funciones incorporadas?

Como el uso aplicado de las expresiones lambda y las comprensiones de listas pueden superponerse, las opiniones varían ampliamente en cuanto a cuándo y dónde usar uno frente al otro. Sin embargo, un punto a tener en cuenta es que una comprensión de la lista se ejecuta algo más rápido que una solución comparable que usa map y lambda (algunas pruebas rápidas arrojaron una diferencia de rendimiento de aproximadamente el 10%). Esto se debe a que llamar a una función lambda crea un nuevo marco de pila mientras se evalúa la expresión en la comprensión de la lista sin hacerlo.

Las expresiones generadoras son sintáctica y funcionalmente similares a las comprensiones de listas, pero existen algunas diferencias bastante significativas entre las formas en que operan las dos y, en consecuencia, cuándo deben usarse cada una. En pocas palabras, iterar usando una expresión generadora o  comprensión de listas esencialmente hará lo mismo, pero la comprensión de la lista creará la lista completa en la memoria primero, mientras que la expresión del generador creará los elementos sobre la marcha según sea necesario. Por lo tanto, las expresiones generadoras se pueden usar para secuencias muy grandes (e incluso infinitas) y su generación de valores bajo demanda da como resultado un rendimiento mejorado y un menor uso de memoria. Sin embargo, vale la pena señalar que los métodos de lista estándar de Python se pueden usar en el resultado de una comprensión de lista, pero no directamente en el de una expresión generadora.

ExclamaciónEl correcto uso de expresiones lambda nos asegura que se evitará declarar numerosas funciones formales que no se utilizarán más de un numero limitado de veces; asegurando así un código más limpio y libre de múltiples funciones basura de pocas lineas de código.

El uso de los iterables por comprensión y expresiones generadoras denota en nuestro candidato a desarrollador Python una administración optima de los datos y recursos disponibles.

Considere los dos enfoques a continuación para inicializar una matriz y las matrices que resultarán. ¿Cómo diferirán las matrices resultantes y por qué debería usar un enfoque de inicialización frente al otro?

>>> # INITIALIZING AN ARRAY -- METHOD 1
...
>>> x = [[1,2,3,4]] * 3
>>> x
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
>>>
>>>
>>> # INITIALIZING AN ARRAY -- METHOD 2
...
>>> y = [[1,2,3,4] for _ in range(3)]
>>> y
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
>>>
>>> # WHICH METHOD SHOULD YOU USE AND WHY?

Como podemos ver se nos presentan dos alternativas para la creación de matrices utilizando en el primer formato un operador que multiplica la matriz por 3 y en el segundo se crean a través de la repetición por iteración . Si bien ambos métodos parecen a primera vista producir el mismo resultado, existe una diferencia extremadamente significativa entre los dos. El método 2 produce, como era de esperar, una matriz de 3 elementos, cada uno de los cuales es una matriz independiente de 4 elementos. Sin embargo, en el método 1, todos los miembros de la matriz apuntan al mismo objeto. Esto puede conducir a lo que probablemente sea un comportamiento no anticipado y no deseado como se muestra a continuación:

>>> # MODIFYING THE x ARRAY FROM THE PRIOR CODE SNIPPET:
>>> x[0][3] = 99
>>> x
[[1, 2, 3, 99], [1, 2, 3, 99], [1, 2, 3, 99]]
>>> # UH-OH, DON’T THINK YOU WANTED THAT TO HAPPEN!
...
>>>
>>> # MODIFYING THE y ARRAY FROM THE PRIOR CODE SNIPPET:
>>> y[0][3] = 99
>>> y
[[1, 2, 3, 99], [1, 2, 3, 4], [1, 2, 3, 4]]
>>> # THAT’S MORE LIKE WHAT YOU EXPECTED!

Esto ocurre porque primeramente estamos seleccionando dentro del elemento x el sub-elemento de indice 0 y dentro de este el sub-elemento de indice 3 para darle un valor de “99”. ¿Pero porque se cambia en los 3 sub-elementos resultantes en el caso de x?, fácilmente porque estamos modificando el elemento del que derivan ( “x”) y luego al solicitar su valor se realiza una multiplicación clonándose 3 veces.

En cambio cuando modificamos el elemento que deriva de un bucle for (“y”) nuestra modificación solo aplica a la primera vuelta del bucle de iteración. Porque en el caso de “y” aplica al elemento 3 en la primer vuelta de bucle.

ExclamaciónEl ítem anterior compara mediante la creación de matrices si el programador comprende el funcionamiento del bucle for en el lenguaje Python y la diferencia con el uso de un simple operador. Demostrando la diferencia en los resultados al modificar la variable que almacena la expresión generadora de las mismas y volver a solicitar su valor.

¿Qué se imprimirá en la segunda instrucción append()?

>>> def append(list=[]):
...     # append the length of a list to the list
...     list.append(len(list))
...     return list
...
>>> append(['a','b'])
['a', 'b', 2]
>>>
>>> append()  # calling with no arg uses default list value of []
[0]
>>>
>>> append()  # but what happens when we AGAIN call append with no arg?

A continuación se nos brindó un código donde claramente se brinda como argumento a la función append() una expresión (almacenara argumentos en una lista llamada list), por lo cual bien sabemos se creará una lista a partir de los argumentos que brindemos y por siguiente se modifica el método append() del elemento list para que añada la longitud del mismo mediante el resultado de la función predeterminada len(). Por lo que resulta obvio que al añadir elementos a la lista, seguido a ellos se almacenara la longitud de la misma.

Pero se nos plantea también que pasaría si llamamos dos veces a la función append() sin ningún argumento. Es fácil saber que iría continuamente en incremento de + 1 en elementos y por en ende en longitud cada vez que sea llamada, porque recursivamente estamos almacenando el elemento resultado de len() que irá en incremento almacenándose como un nuevo elemento tomando la lista anterior sin inicializarse nuevamente.

¿Por qué sucede esto?

Cuando el valor predeterminado para un argumento de función es una expresión, la expresión se evalúa solo una vez, no cada vez que se llama a la función. Por lo tanto, una vez que el argumento de la lista se ha inicializado en una matriz vacía, las llamadas posteriores para agregar sin ningún argumento especificado continuarán utilizando la misma matriz en la que la lista se inicializó originalmente. Por lo tanto, esto producirá el siguiente comportamiento inesperado:

>>> append()  # first call with no arg uses default list value of []
[0]
>>> append()  # but then look what happens...
[0, 1]
>>> append()  # successive calls keep extending the same default list!
[0, 1, 2]
>>> append()  # and so on, and so on, and so on...
[0, 1, 2, 3]

ExclamaciónSe evalúa el conocimiento del desarrollador Python referente a funciones y argumentos.

¿Cómo podrías modificar el código anterior para evitar el comportamiento indeseado al utilizar el método append()?

Se nos pide una manera alternativa para solucionar este comportamiento y se nos brinda la siguiente como respuesta:

>>> def append(list=None):
...     if list is None:
            list = []
        # append the length of a list to the list
...     list.append(len(list))
...     return list
...
>>> append()
[0]
>>> append()
[0]

De esta manera al llamar append() sin especificar argumentos el valor de la lista sera None por lo que respetando el condicional se establecerá en una lista vacía que dará por resultado la longitud 0 y se almacenara como único elemento sin ningún incremento al volver a llamar la función append() sin argumento porque la lista será reiniciada nuevamente.

¿Cómo puede intercambiar los valores de dos variables con una sola línea de código en Python?

Se nos brinda el siguiente ejemplo:

>>> x = 'X'
>>> y = 'Y'

Y también como se haría en otros lenguajes:

>>> tmp = x
>>> x = y
>>> y = tmp
>>> x, y
('Y', 'X')

¿Crees que en Python necesitaríamos recurrir a una variable temporal para intercambiar sus valores?

En Python se hace posible hacer el intercambio con una sola línea de código (gracias al empaquetado y desempaquetado implícito de tuplas) de la siguiente manera:

>>> x,y = y,x
>>> x,y
('Y', 'X')

¿Qué se imprimirá en la ultima declaración a continuación?

>>> flist = []
>>> for i in range(3):
...     flist.append(lambda: i)
...
>>> [f() for f in flist]   # what will this print out?

En python las variables están unidas por su identificador. Es decir, que imprimirá el valor de i en forma de lista. Pero seguramente esperabamos esto: [0, 1, 2] sin embargo imprime lo siguiente:

[2, 2, 2]

¿Por qué crees que sucede esto?

Porque como dijimos en Python las variables están unidas por su nombre y ademas las funciones lambda apuntan a la variable en lugar de al valor de la misma. Por lo que al actualizarse “i” en la siguiente iteración esta actualización se refleja en todas las funciones. Aquí tienes mas información al respecto.

Una solución alternativa es crear una función separada o pasar los argumentos por nombre; p.ej.:

>>> flist = []
>>> for i in range(3):
...     flist.append(lambda i = i : i)
...
>>> [f() for f in flist]
[0, 1, 2]

Exclamación Estos ejercicios plantean al desarrollador python un problema clásico pero no por eso poco común que evalúa en parte algo del ingenio y sobre todo la teoría aplicada a la practica en un nivel bastante exigente.

¿Cuáles son las diferencias clave entre Python 2 y 3?

Aunque Python 2 se considera formalmente heredado en este momento, su uso todavía está lo suficientemente extendido como para que un desarrollador reconozca las diferencias entre Python 2 y 3.

Estas son algunas de las diferencias clave que un desarrollador debe tener en cuenta:

  • Python 3.0 utiliza los conceptos de texto y datos (binarios) en lugar de cadenas Unicode y cadenas de 8 bits. La mayor ramificación de esto es que cualquier intento de mezclar texto y datos en Python 3.0 genera un TypeError (para combinar los dos de manera segura, debe decodificar bytes o codificar Unicode, pero debe conocer la codificación adecuada, por ejemplo, UTF-8).

En Python 2, la mezcla de datos Unicode y 8 bits funcionaría si la cadena tuviera solo bytes de 7 bits (ASCII), pero obtendría UnicodeDecodeError si contuviera valores no ASCII. Además, la excepción ocurriría en el punto de combinación, no en el punto en el que los caracteres no ASCII se colocaron en el objeto str. Este comportamiento fue una fuente común de confusión y consternación para los programadores neófitos de Python.

  • En Python 3 la función print fue reemplazada por print(), donde se exige el uso de parentesis.
  • A partir de Python 3 deja de existir xrange() y en su lugar se utiliza range() que se comporta de igual manera como se comportaba xrange() excepto porque funciona en valores de tamaño arbitrarios. Ademas range() es considerado ahora un tipo de dato y no una función.
  • Cambios de API:

    zip (), map () y filter () ahora devuelven iteradores en lugar de listas.

    dict.keys (), dict.items () y dict.values ​​() ahora devuelven “vistas” en lugar de listas.

    dict.iterkeys (), dict.iteritems () y dict.itervalues ​​() ya no son compatibles.

  • Operadores de comparación: (<, <=,> =,>) ahora generan una excepción TypeError cuando los operandos no tienen un orden natural significativo. Algunos ejemplos de las ramificaciones de esto incluyen:

    Expresiones como 1 <‘ ‘, 0 > None o len <= len ya no son válidas

    None < None ahora genera TypeError en lugar de devolver False

    Ordenar una lista heterogénea ya no tiene sentido: todos los elementos deben ser comparables entre sí.

    Aquí puedes encontrar mas detallados los cambios a partir de Python 3.

Desarrollador Python 3Resulta de vital importancia que el desarrollador en python conozca los cambios en el traspaso de versiones de Python. No solo por las versiones anteriores o la actual; sino sencillamente por las nuevas versiones tanto del lenguaje como de software que puedan actualizarse en un futuro. Esto nos dice que el candidato se interesa por conocer a fondo las actualizaciones y sus beneficios.

¿Es Python interpretado o compilado?

Estoy seguro que más de uno se va a congelar con la respuesta correcta a esta pregunta engañosa.

Esta es, francamente, una pregunta engañosa en el sentido de que está mal formulada. Python en sí mismo no es más que una definición de interfaz (como es cierto con cualquier especificación de lenguaje) de la cual hay múltiples implementaciones. En consecuencia, la cuestión de si “Python” se interpreta o compila no se aplica al lenguaje Python en sí; más bien, se aplica a cada implementación específica de la especificación de Python.

Para complicar aún más la respuesta a esta pregunta es el hecho de que, en el caso de CPython (la implementación más común de Python), la respuesta es realmente “una especie de ambas”. Específicamente, con CPython, el código primero se compila y luego se interpreta. Más precisamente, no está pre-compilado en código máquina nativo, sino en código de bytes. Si bien el código de máquina es ciertamente más rápido, el código de bytes es más portátil y seguro. El bytecode se interpreta en el caso de CPython (o ambos interpretados y compilados en código de máquina optimizado en tiempo de ejecución en el caso de PyPy).

Python interpretado o compiladoNormalmente cualquier Pythoner enseguida hubiese respondido que es un lenguaje interpretado sin tener en cuenta la implementación del mismo. Pero ahora que ya lo sabes toca re-formular la clásica respuesta a esta pregunta que normalmente cualquier novato no logra comprender.

¿Cuáles son algunas implementaciones alternativas a CPython? ¿Cuándo y por qué podrías usarlos?

Una de las implementaciones alternativas más destacadas es Jython, una implementación de Python escrita en Java que utiliza Java Virtual Machine (JVM). Mientras que CPython produce bytecode para ejecutarse en CPython VM, Jython produce bytecode de Java para ejecutarse en JVM.

Otro es IronPython, escrito en C # y dirigido a la pila .NET. IronPython se ejecuta en Common Language Runtime (CLR) de Microsoft.

Como también se señaló en ¿Por qué hay tantas python’s ?, es completamente posible sobrevivir sin tocar una implementación de Python que no sea CPython, pero existen ventajas de cambiar, la mayoría de las cuales dependen de su pila de tecnología.

Otra implementación alternativa notable es PyPy cuyas características clave incluyen:

  • Velocidad. Gracias a su compilador Just-in-Time (JIT), los programas de Python a menudo se ejecutan más rápido en PyPy.
  • Uso de memoria. Los programas grandes de Python que consumen mucha memoria podrían terminar ocupando menos espacio con PyPy que en CPython.
  • Compatibilidad. PyPy es altamente compatible con el código python existente. Es compatible con cffi y puede ejecutar bibliotecas populares de Python como Twisted y Django.
  • Sandboxing. PyPy proporciona la capacidad de ejecutar código no confiable de una manera totalmente segura.
  • Modo apilable. PyPy viene por defecto con soporte para modo sin pila, proporcionando micro-hilos para concurrencia masiva.

¿Cuál es su enfoque para las pruebas unitarias en Python?

La respuesta más fundamental a esta pregunta se centra en el marco de prueba de Unit testing de Python. Básicamente, si un candidato no menciona unittest al responder esta pregunta, eso debería ser una gran señal de alerta.

Unittest admite la automatización de pruebas, el intercambio del código de configuración y apagado para las pruebas, la agregación de pruebas en colecciones y la independencia de las pruebas del reporte de informes. El módulo unittest proporciona clases que facilitan el soporte de estas cualidades para un conjunto de pruebas.

Suponiendo que el candidato sí menciona unittest (si no lo hace, ¡tal vez quiera terminar la entrevista en ese mismo momento!), También debe pedirles que describan los elementos clave del marco de unittest; a saber, accesorios de prueba, casos de prueba, suites de prueba y corredores de prueba.

Una adición más reciente al marco de unittest es simulada. El simulacro le permite reemplazar partes de su sistema bajo prueba con objetos simulados y hacer afirmaciones sobre cómo se van a utilizar. Mock ahora es parte de la biblioteca estándar de Python, disponible como unittest.mock en Python 3.3 en adelante.

El valor y el poder del simulacro se explican bien en Introducción a Mocking en Python. Como se señaló allí, las llamadas al sistema son las principales candidatas para moking: ya sea que escriba un script para expulsar una unidad de CD, un servidor web que elimine los archivos de caché anticuados de / tmp, o un servidor de socket que se une a un puerto TCP, todas estas llamadas no son deseadas efectos secundarios en el contexto de pruebas unitarias. Del mismo modo, mantener sus pruebas unitarias eficientes y eficaces significa mantener la mayor cantidad posible de “código lento” fuera de las ejecuciones de pruebas automatizadas, es decir, el sistema de archivos y el acceso a la red.

Desarrollador Python Unit TestingUnit Testing es un método para determinar si un módulo o un conjunto de módulos de código funciona correctamente. Y no se limita a ningún lenguaje específico, sino que es una herramienta de programación en general. Las pruebas unitarias se implementan a la par con el desarrollo de un  proyecto, y se ejecutan cuando este último sufre modificaciones para garantizar su funcionamiento.

Por lo que el candidato debe conocer sobre este método casi obligadamente.

Java vs Python (Solo para programadores que aplican también a Java)

desarrollador python vs java

Se nos ofrece aquí algunas preguntas para aquellos candidatos que también poseen conocimientos en Java. Y en la pregunta a continuación basta con recurrir a los conceptos y características particulares de cada lenguaje para dar a conocer las notables diferencias.

# 1. Las diferencias entre Java y Python son numerosas y probablemente sería un tema digno de su propia publicación (larga). A continuación se explica una breve muestra de algunas diferencias clave entre los dos lenguajes.

# 2. La intención aquí no es lanzarse a una batalla religiosa por los méritos de Python vs. Java (¡por muy divertido que sea!). Por el contrario, la pregunta está realmente orientada a ver qué tan bien comprende el desarrollador algunas diferencias prácticas entre los dos lenguajes. Por lo tanto, la siguiente lista evita deliberadamente discutir las ventajas discutibles de Python sobre Java desde una perspectiva de productividad de programación.

¿Cuáles son algunas diferencias clave a tener en cuenta al codificar en Python vs. Java?

  • Tipado fuerte vs tipado dinamico. Una de las mayores diferencias entre los dos lenguajes es que Java está restringido al tipado estático o fuerte, mientras que Python admite la el tipado dinámico o mutabilidad de variables.
  • Métodos estáticos vs de clase. Un método estático en Java no se traduce en un método de clase Python.
  • En Python, llamar a un método de clase implica una asignación de memoria adicional que no es llamar a un método o función estática.
  • En Java, el compilador busca los nombres de puntos (por ejemplo, método foo.bar.), por lo que en tiempo de ejecución realmente no importa cuántos de ellos tenga. En Python, sin embargo, las búsquedas se producen en tiempo de ejecución, por lo que “cada punto cuenta”.
  • Método de sobrecarga. Mientras que Java requiere una especificación explícita de múltiples funciones con el mismo nombre con diferentes firmas, lo mismo se puede lograr en Python con una sola función que incluye argumentos opcionales con valores predeterminados si el llamador no lo especifica.
  • Comillas simples versus dobles. Mientras que el uso de comillas simples versus comillas dobles tiene importancia en Java, se pueden usar indistintamente en Python (pero no, no permitirá comenzar la misma cadena con una comilla doble e intentar terminarla con una comilla simple, o ¡viceversa!).
  • Getters y setters (¡no!). Getters y setters en Python son superfluos; más bien, debe usar la “propiedad” incorporada (¡para eso está!). En Python, getters y setters son una pérdida de tiempo tanto de CPU como de programador.
  • Las clases son opcionales. Mientras que Java requiere que cada función se defina en el contexto de una definición de clase adjunta, Python no tiene ese requisito.
  • La identación si importa … en Python. Esto muerde a muchos programadores principiantes de Python.

¿Para qué es particularmente bueno Python? ¿Cuándo usar Python es la “elección correcta” para un proyecto?

Una pregunta que sin duda en cualquier entrevista van a hacerte.

Aunque los gustos y disgustos son muy personales, un desarrollador Python que “valga la pena” resaltará las características del lenguaje Python que generalmente se consideran ventajosas (lo que también ayuda a responder la pregunta de para qué Python es “particularmente bueno”). Algunas de las respuestas válidas más comunes a esta pregunta incluyen:

  • Facilidad de uso y facilidad de refactorización, gracias a la flexibilidad de la sintaxis de Python, que la hace especialmente útil para la creación rápida de prototipos.
  • Código más compacto, gracias de nuevo a la sintaxis de Python, junto con una gran cantidad de bibliotecas de Python funcionalmente ricas (distribuidas libremente con la mayoría de las implementaciones de lenguaje Python).
  • Un lenguaje de tipo dinámico y de tipo fuerte, que ofrece la rara combinación de flexibilidad de código y al mismo tiempo evita molestos errores de conversión de tipo implícito.
  • ¡Es gratis y de código abierto! ¿Necesitamos decir más?

Con respecto a la cuestión de cuándo usar Python es la “opción correcta” para un proyecto, la respuesta completa también depende de una serie de cuestiones ortogonales al lenguaje en sí, como la inversión tecnológica previa, el conjunto de habilidades del equipo, etc. . Aunque la pregunta como se indicó anteriormente implica interés en una respuesta estrictamente técnica, un desarrollador Python que planteará estos problemas adicionales en una entrevista siempre “obtendrá más puntos” ya que indica una conciencia y sensibilidad hacia la “un panorama más grande” (es decir, más allá de la tecnología empleada). Por el contrario, una respuesta de que Python siempre es la elección correcta es una clara señal de un desarrollador poco sofisticado.

Y por ultimo:

¿Cuáles son algunos inconvenientes del lenguaje Python?

Para empezar, si conoces bien un lenguaje, conoces sus inconvenientes, por lo que las respuestas como “no hay nada que no me guste” o “no tiene inconvenientes” son muy reveladoras.

Las dos respuestas de la mayoria de desarrolladores Python válidas a esta pregunta (de ninguna manera pretenden ser una lista exhaustiva) son:

El Global Interpreter Lock (GIL).

CPython (la implementación de Python más común) no es completamente segura para subprocesos. Para admitir programas Python multiproceso, CPython proporciona un bloqueo global que debe mantener el subproceso actual antes de que pueda acceder de forma segura a los objetos Python. Como resultado, no importa cuántos subprocesos o procesadores estén presentes, solo se ejecuta un subproceso en un momento dado. En comparación, vale la pena señalar que la implementación de PyPy discutida anteriormente en este artículo proporciona un modo sin pila que admite microhilos para una concurrencia masiva.

Velocidad de ejecución.

Python puede ser más lento que los lenguajes compilados, ya que se interpreta. (Bueno, más o menos como sabemos en los equipos actuales esto pierde cierta relevancia)

Las preguntas y consejos presentados aquí pueden ser ayudas extremadamente valiosas para identificar verdaderos maestros desarrolladores Python. Esperamos que los encuentre como una base útil para “separar el trigo de la paja” en su búsqueda de los pocos elite entre los desarrolladores Python. Sin embargo, es importante recordar que estos son meramente como herramientas para incorporar en el contexto más amplio de su caja de herramientas y estrategia de reclutamiento general.

Y, para aquellos que pueden haber leído esta guía por error con la esperanza de aprender a capturar un reptil (¡lo siento, tipo de pitón equivocado!), Recomendamos consultar el Desafío Python de la Fundación de Vida Silvestre de Florida.

Ayudame compartiendo este blog de programación