You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A continuación se detallan comentarios de lo corregido para la actividad AC03.
En general, la actividad tuvo cantidad baja de entregas, de las cuales pocas tuvieron avance significativo :( La temática semanal era particularmente densa y nueva, y la actividad requería un nivel de entendimiento moderado en vez de uno bajo. Por esto, como excepción se bajó el mínimo esperado para ser considerado como significativo para las décimas de aquellos y aquellas que realizaron esta actividad.
A modo de ayuda, en este documento se proveerán explicaciones de los contenidos aplicados en la AC, y también se listan comentarios más particulares. Recuerden que también cuentan con el cierre de la clase correspondiente a la AC, que se encuentra en la carpeta Clases en syllabus.
Como siempre, si tienen alguna duda respecto a cualquier cosa expuesta aquí, ¡No duden en preguntarla en esta o en una nueva issue! 😄
Errores generales
En relación a los decoradores, se notó cierta confusión en los parámetros que ingresan a cada función al momento de decorar.
Un decorador, en general, es una función que recibe como argumento otra función a decorar, y retorna otra función que reemplazará a la función recibida. La función reemplazante representa una versión “mejorada” o “extendida” de la función recibida.
Utilizando la sintaxis @decorador sobre una función, se aplica la función decoradora, dándole de input la definición de la función que está definida justo abajo, y el valor retornado lo almacena bajo el nombre de esta misma definición.
defdecorador(funcion_recibida):
defnueva_funcion(*args, **kwargs):
# códigoreturnnueva_funcion@decoradordeffuncion_a_decorar(param1, …):
# códigofuncion_a_decorar(param1, ...) # Llama realmente a “nueva_funcion”, retornada por decorador
Luego, aplicando el @decorador sobre def funcion_a_decorar, se reemplaza la definición escrita dentro por el resultado devuelto por decorador, que sería nueva_funcion. Por otro lado, la definición de nueva_funcion recibe *args y **kwargs, lo anterior tiene como objetivo recibir todos los argumentos que debía recibir la función original, pues nueva_funcionreemplazará a la función decorada.
Por otro lado, en ocasiones es deseable otorgarle parámetros a nuestros decoradores, esto nos permite definir decoradores similares, pero que se diferencian en campos simples. Para esto, es necesario escribir otro nivel de función, que sería una función creadora de decoradores, que recibe argumentos para el decorador y retorna el decorador específico con los argumentos dentro de su definición:
La sentencia @constructor_decordor(3) tiene dos partes, primero se evalúa constructor_decorador(3), lo cual retorna un decorador, digamos decor; este decorador retornado se une al @, formando: @decor, que será un decorador aplicará sobre la definición de función, de igual forma que en el ejemplo explicado anteriormente.
En estos casos particulares la dificultad es identificar los distintos argumentos, y cuáles deben usarse dónde. En este caso los argumentos son funcion_a_decorar, funcion_decodificadora, tipo_archivo y *args.
Para este ejemplo decodificar y “canciones” entran como argumentos para un decorador específico para leer_canciones. decodificar ingresa como funcion_decodificadora y “canciones” ingresá como tipo_archivo al creador de decoradores desencriptar. Luego leer_canciones ingresará como funcion_a_decorar a decorador, mientras que path y eventualmente más argumentos ingresan como *args a wrapper.
De la explicación revisada sobre el uso de la sintaxis @, podemos argumentar que la forma en que se decora del ejemplo anterior será equivalente a hacer:
Junto a lo anterior, estaba la particularidad de que las funciones a decorar, como leer_canciones, eran funciones generadoras, es decir, que retornan objetos generadores. Luego, el decorador debía retornar una función generadora, específicamente, una función generadora de instancias de namedtuples. Por lo tanto, la función decorada (wrapper) debe o retornar un objeto generador, o ser función generadora y utilizar yield para retornar instancias.
Errores específicos de la actividad
Muchos usaron un diccionario de la forma { letra: valor_correspondiente_al_decodificar }, en sí es una muy buena idea para lo pedido. Pero como eran solo algunas las letras que se codificaban, tuvieron problemas sobre lo que debían hacer cuando una letra no era transformada. Recuerden que pueden usar if/else en las listas por comprensión de la siguiente manera : [f(x) if algo else g(x) for x in iterable]. La expresión f(x) if algo else g(x) es una expresión condicional de Python aplicable no solo en listas por comprensión, si no en cualquiera, como en asignación de variables. Es sumamente útil.
Respecto al diccionario mencionado en el punto anterior, muchos lo definieron a mano, si bien en este caso particular el diccionario era pequeño, recuerden que siempre pueden haber formas más rápidas de escribir este tipo de datos, por ejemplo a = list(“abc”) devuelve [“a”, ”b”, ”c”].
Sobre como hacer el diccionario no a mano, también era posible a través del método zip para hacer los pares “letras-numeros” y “numeros-letras” y luego hacer un gran iterable con el método chain.
Uno de los objetivos de la actividad era que lograran implementarla sin el uso de for ni while, estas dos sentencias de Python podían ser reemplazadas por el uso de las funciones map, filter o listas por comprensión, o incluso usar librerías del módulo itertools que podrían ser de gran utilidad.
Recordar que una lista se puede desempaquetar en variables, por ejemplo, si tenemos [“a”, “b”], esto podemos guardarlo en dos variables de la forma var1, var2 = [“a”, “b”].
Se les pedía utilizar las namedtuples, que se daban definidas, las cuales recibían los argumentos decodificados que entregaba la función leer_{archivos}, por lo tanto, no había que recorrer estos argumentos ni entregarlos directamente, sino que ocupar funcion_decodificadora que recibía el constructor de decorador para decodificar primero, y luego instanciar la namedtuples correspondiente.
Nuevamente les recordamos, cualquier duda que tengan, pueden preguntarla en esta o en una nueva issue 😄
The text was updated successfully, but these errors were encountered:
Resumen:
A continuación se detallan comentarios de lo corregido para la actividad AC03.
En general, la actividad tuvo cantidad baja de entregas, de las cuales pocas tuvieron avance significativo :( La temática semanal era particularmente densa y nueva, y la actividad requería un nivel de entendimiento moderado en vez de uno bajo. Por esto, como excepción se bajó el mínimo esperado para ser considerado como significativo para las décimas de aquellos y aquellas que realizaron esta actividad.
A modo de ayuda, en este documento se proveerán explicaciones de los contenidos aplicados en la AC, y también se listan comentarios más particulares. Recuerden que también cuentan con el cierre de la clase correspondiente a la AC, que se encuentra en la carpeta
Clases
ensyllabus
.Como siempre, si tienen alguna duda respecto a cualquier cosa expuesta aquí, ¡No duden en preguntarla en esta o en una nueva issue! 😄
Errores generales
Un decorador, en general, es una función que recibe como argumento otra función a decorar, y retorna otra función que reemplazará a la función recibida. La función reemplazante representa una versión “mejorada” o “extendida” de la función recibida.
Utilizando la sintaxis
@decorador
sobre una función, se aplica la función decoradora, dándole de input la definición de la función que está definida justo abajo, y el valor retornado lo almacena bajo el nombre de esta misma definición.Se puede obtener un comportamiento equivalente a:
Haciendo lo siguiente:
Luego, aplicando el
@decorador
sobredef funcion_a_decorar
, se reemplaza la definición escrita dentro por el resultado devuelto pordecorador
, que seríanueva_funcion
. Por otro lado, la definición denueva_funcion
recibe*args
y**kwargs
, lo anterior tiene como objetivo recibir todos los argumentos que debía recibir la función original, puesnueva_funcion
reemplazará a la función decorada.Por otro lado, en ocasiones es deseable otorgarle parámetros a nuestros decoradores, esto nos permite definir decoradores similares, pero que se diferencian en campos simples. Para esto, es necesario escribir otro nivel de función, que sería una función creadora de decoradores, que recibe argumentos para el decorador y retorna el decorador específico con los argumentos dentro de su definición:
La sentencia
@constructor_decordor(3)
tiene dos partes, primero se evalúaconstructor_decorador(3)
, lo cual retorna un decorador, digamosdecor
; este decorador retornado se une al@
, formando:@decor
, que será un decorador aplicará sobre la definición de función, de igual forma que en el ejemplo explicado anteriormente.Ahora, específico para la AC, se tenía:
En estos casos particulares la dificultad es identificar los distintos argumentos, y cuáles deben usarse dónde. En este caso los argumentos son
funcion_a_decorar
,funcion_decodificadora
,tipo_archivo
y*args
.Para este ejemplo
decodificar
y“canciones”
entran como argumentos para un decorador específico paraleer_canciones
.decodificar
ingresa comofuncion_decodificadora
y“canciones”
ingresá comotipo_archivo
al creador de decoradoresdesencriptar
. Luegoleer_canciones
ingresará comofuncion_a_decorar
adecorador
, mientras quepath
y eventualmente más argumentos ingresan como*args
awrapper
.De la explicación revisada sobre el uso de la sintaxis
@
, podemos argumentar que la forma en que se decora del ejemplo anterior será equivalente a hacer:Junto a lo anterior, estaba la particularidad de que las funciones a decorar, como
leer_canciones
, eran funciones generadoras, es decir, que retornan objetos generadores. Luego, el decorador debía retornar una función generadora, específicamente, una función generadora de instancias denamedtuples
. Por lo tanto, la función decorada (wrapper
) debe o retornar un objeto generador, o ser función generadora y utilizaryield
para retornar instancias.Errores específicos de la actividad
Muchos usaron un diccionario de la forma
{ letra: valor_correspondiente_al_decodificar }
, en sí es una muy buena idea para lo pedido. Pero como eran solo algunas las letras que se codificaban, tuvieron problemas sobre lo que debían hacer cuando una letra no era transformada. Recuerden que pueden usarif/else
en las listas por comprensión de la siguiente manera :[f(x) if algo else g(x) for x in iterable]
. La expresiónf(x) if algo else g(x)
es una expresión condicional de Python aplicable no solo en listas por comprensión, si no en cualquiera, como en asignación de variables. Es sumamente útil.Respecto al diccionario mencionado en el punto anterior, muchos lo definieron a mano, si bien en este caso particular el diccionario era pequeño, recuerden que siempre pueden haber formas más rápidas de escribir este tipo de datos, por ejemplo
a = list(“abc”)
devuelve[“a”, ”b”, ”c”]
.Sobre como hacer el diccionario no a mano, también era posible a través del método
zip
para hacer los pares “letras-numeros” y “numeros-letras” y luego hacer un gran iterable con el métodochain
.Uno de los objetivos de la actividad era que lograran implementarla sin el uso de
for
niwhile
, estas dos sentencias de Python podían ser reemplazadas por el uso de las funcionesmap
,filter
o listas por comprensión, o incluso usar librerías del móduloitertools
que podrían ser de gran utilidad.Recordar que una lista se puede desempaquetar en variables, por ejemplo, si tenemos [“a”, “b”], esto podemos guardarlo en dos variables de la forma var1, var2 = [“a”, “b”].
Se les pedía utilizar las
namedtuples
, que se daban definidas, las cuales recibían los argumentos decodificados que entregaba la funciónleer_{archivos}
, por lo tanto, no había que recorrer estos argumentos ni entregarlos directamente, sino que ocuparfuncion_decodificadora
que recibía el constructor de decorador para decodificar primero, y luego instanciar lanamedtuples
correspondiente.Nuevamente les recordamos, cualquier duda que tengan, pueden preguntarla en esta o en una nueva issue 😄
The text was updated successfully, but these errors were encountered: