Cómo entrevistar a un ingeniero backend de Python
Preguntas de la entrevista
1. ¿Cómo gestiona Python la memoria?
La gestión de memoria de Python tiene principalmente tres mecanismos: mecanismo de recuento de referencias, mecanismo de recolección de basura y mecanismo de grupo de memoria.
a. Recuento de referencias
Cuando a un objeto se le asigna un nuevo nombre o se coloca un objeto en un contenedor (lista, tupla o diccionario), el recuento de referencias del objeto cambiará. Aumentar.
Cuando se usa del para destruir explícitamente un objeto o la referencia excede su alcance o se reasigna, el recuento de referencias del objeto se reducirá.
Puedes utilizar la función sys.getrefcount() para obtener el recuento de referencia actual de un objeto. En la mayoría de los casos, el recuento de referencias es mucho mayor de lo que suponemos. Para datos inmutables (números y cadenas), el intérprete comparte memoria entre diferentes partes del programa para ahorrar memoria.
b. Recolección de basura
Cuando el recuento de referencias de un objeto llega a cero, será procesado por el mecanismo de recolección de basura.
Cuando
dos objetos a y b se refieren entre sí, la declaración del puede disminuir los recuentos de referencias de a y b y destruir los nombres utilizados para referirse a los objetos subyacentes. Sin embargo, dado que cada objeto contiene una aplicación a otros objetos, el recuento de referencias no volverá a cero y el objeto no será destruido. (Provocando así una pérdida de memoria). Para solucionar este problema, el intérprete ejecuta periódicamente un detector de ciclos, busca ciclos de objetos inaccesibles y los elimina.
c. Mecanismo del grupo de memoria
Python proporciona un mecanismo de recolección de basura para la memoria, pero coloca la memoria no utilizada en el grupo de memoria en lugar de devolverla al sistema operativo.
1) Mecanismo de Pymalloc. Para acelerar la eficiencia de ejecución de Python, Python introduce un mecanismo de grupo de memoria para administrar la aplicación y liberar pequeños bloques de memoria.
2) Todos los objetos de menos de 256 bytes en Python usan el asignador implementado por pymalloc, mientras que los objetos grandes usan el malloc del sistema.
3) Los objetos de Python, como números enteros, números de punto flotante y listas, tienen sus propios grupos de memoria privados independientes y los objetos no comparten sus grupos de memoria. Esto significa que si asigna y libera una gran cantidad de números enteros, la memoria utilizada para almacenar en caché estos números enteros ya no se puede asignar a números de punto flotante.
Resumen de 12 preguntas de la entrevista de Python en el entorno Python
2. ¿Qué es una función lambda? ¿Cuáles son sus beneficios?
Las expresiones lambda generalmente se usan cuando se necesita una función pero no queremos molestarnos en nombrar una función, es decir, funciones anónimas
Función lambda: el propósito principal es señalar breves función de devolución de llamada
lambda [argumentos]: expresión
>>> a=lambda x, y: x+y
>>> a(3 , 11 )
3. ¿Cómo realizar la conversión entre tupla y lista en Python?
Simplemente use las funciones tupla y lista directamente. type() puede determinar el tipo de objeto.
4. Escriba un fragmento de código Python para eliminar elementos duplicados en una lista.
Esto se puede lograr usando set.
5. ¿Cómo copiar un objeto en Python? (La diferencia entre asignación, copia superficial y copia profunda)
La asignación (=) crea una nueva referencia al objeto. La modificación de cualquiera de las variables afectará a la otra.
Copia superficial: Crea un nuevo objeto, pero contiene una referencia a los elementos contenidos en el objeto original (si uno de los objetos se modifica por referencia, el otro también se modificará) {1, Método de corte completo; 2. Funciones de fábrica, como list(); 3. La función copy() del módulo de copia}
Copia profunda: crea un nuevo objeto y copia recursivamente los objetos que contiene (Modificar). uno de ellos, el otro no cambiará) {función deep.deepcopy() del módulo de copia}
6. ¿Introducir el uso y la función de excepción?
intentar…excepto…excepto…[else…][finalmente…]
Ejecutar la declaración bajo intento. Si se lanza una excepción, el proceso de ejecución saltará a la declaración excepto. Intente ejecutar cada rama excepto secuencialmente. Si la excepción generada coincide con el grupo de excepciones en excepción, ejecute la declaración correspondiente. Si todas las excepciones no coinciden, la excepción se pasará al siguiente código de prueba de nivel más alto que llame a este código.
Si la declaración bajo try se ejecuta normalmente, se ejecutará el código del bloque else. Si ocurre una excepción, no se ejecutará
Si hay una declaración finalmente, siempre se ejecutará al final.
Resumen de 12 preguntas de la entrevista de Python en el entorno de Python
7. ¿Cuál es la diferencia entre match() y search() en Python?
match(pattern, string [, flags]) en el módulo re comprueba si el comienzo de la cadena coincide con el patrón.
La investigación (patrón, cadena [, banderas]) en el módulo re busca el primer valor coincidente del patrón en la cadena.
>>> print(re.match('super', 'superstición').span())
(0, 5)
>> > print(re.match('super', 'insuperable'))
Ninguno
>>> print(re.search('super', 'superstición').span ())
(0, 5)
>>> print(re.search('super', 'insuperable').span())
(2, 7)
8. Cuando se utiliza Python para unir etiquetas HTML, <.*> y <.*? >¿Cuál es la diferencia?
Los términos se denominan coincidencia codiciosa (<.*>) y coincidencia no codiciosa (<.*?>)
Por ejemplo:
prueba
<.*>:
prueba
<.*? >>
9. ¿Cuál será el resultado del siguiente código? Da tu respuesta y explica
Resultado:
Lo que te confunde o te sorprende es que el resultado de la última línea es 3 2 3 en lugar de 3 2 1. ¿Por qué cambiar el valor de Parent.x también cambia el valor de Child2.x, pero al mismo tiempo el valor de Child1.x no cambia?
La clave de esta
respuesta es que en Python
las variables de clase se tratan internamente como diccionarios. Si el nombre de una variable no se encuentra en el diccionario de la clase actual, se buscarán las clases antecesoras (como las clases principales) hasta que se encuentre el nombre de la variable referenciada (si el nombre de la variable referenciada no es propio. Si la clase es no se encuentra en la clase ancestral, se generará una excepción AttributeError).
Por lo tanto, establecer x = 1 en una clase principal hace que la variable de clase X tenga un valor de 1 en referencias a esa clase y cualquiera de sus subclases. Esto se debe a que el resultado de la primera declaración impresa es 1 1 1.
Posteriormente, si alguna de sus subclases anula el valor (por ejemplo, ejecutamos la instrucción Child1.x = 2), entonces el valor se cambia solo en la subclase. Es por eso que el resultado de la segunda declaración impresa es 1 2 1.
Finalmente, si se cambia el valor en la clase padre (por ejemplo, ejecutamos la sentencia Parent.x = 3), este cambio afectará al valor en cualquier subclase que no anule el valor (en La subclase afectada en este ejemplo es Child2). Por eso el tercer resultado impreso es 3 2 3.
10. ¿Qué generará el siguiente código?
Respuesta
El código anterior generará [] y no causará un IndexError.
Como era de esperar, intentar acceder a un miembro que excede el índice de la lista resultará en un IndexError (como acceder a la lista[10] de la lista anterior). Sin embargo, intentar acceder a una porción de una lista que comienza en un índice que excede el número de miembros de la lista no provocará un IndexError y simplemente devolverá una lista vacía.
Resumen de 12 preguntas de la entrevista de Python en el entorno Python
Un pequeño problema desagradable es que causa errores, y el problema es difícil de rastrear porque no causa un error en error de tiempo de ejecución.
11. ¿Cuál será el resultado del siguiente código? Dime tu respuesta y explícame.
¿Cómo modificarías la definición de extendList para producir los resultados deseados?
El resultado del código anterior es:
Mucha gente pensará erróneamente que list1 debería ser igual a [10] y list3 debe ser igual a ['a']. Se cree que los parámetros de la lista se establecerán en sus valores predeterminados [] cada vez que se llame a extendList.
Sin embargo, lo que realmente sucede es que la nueva lista predeterminada solo se crea una vez cuando se define la función. Cuando posteriormente se llama a extendList sin un argumento de lista específico, utiliza la misma lista. Es por eso que la expresión se evalúa con argumentos predeterminados cuando se define la función, no cuando se llama.
Por lo tanto, lista1 y lista3 son las mismas listas de operaciones. Y list2 opera en una lista separada que crea (pasando su propia lista vacía como valor del argumento de la lista).
La definición de la función extendList se puede modificar de la siguiente manera, pero cuando no se especifica ningún nuevo parámetro de lista, siempre se iniciará una nueva lista, que es más probable que sea el comportamiento deseado.
12. ¿Qué genera el siguiente programa?
Bien
Bien, la primera línea de código me parece correcta por primera vez. El resultado de la primera línea es [[], [], [], []. , [ ]], una lista que contiene 5 listas vacías y la salida de la segunda línea es [[10],
[10], [10], [10],
[ 10]], solo puedo explicar que estas 5 listas apuntan a la misma lista, por lo que modificar cualquiera de las otras 4 cambiará. Puedes usar list[0]=10 para desconectar una conexión y probarla.