IIC2115 / Syllabus-2021-1

Syllabus del curso IIC2115 - Programación como Herramienta para la Ingeniería 2021/I
9 stars 48 forks source link

Duda respecto a uso de atributos *args y **kwargs en objetos heredados #11

Closed iavasquez1 closed 3 years ago

iavasquez1 commented 3 years ago

Estuve revisando la materia, especificamente en la parte de diccionarios y cuando se crean las clases contacto y cliente se utiliza super().init, que se refiere a los metodos y atributos de la o las clases heredadas, sin embargo al poner como atributo **kwargs no me queda claro si se refiere a los de AdressHolder o a los de Contacto en la clase cliente. Además no me queda claro por qué las clases AdressHolder y Contacto tienen que llamar a una clase que heredó sus atributos si son clases que no heredan de otra clase especifica en el programa. Envío imagen de lo planteado.

Otra duda respecto a las kwargs, ¿estas también consideran argumentos que tienen igualdad? por ejemplo a="hola" y b = "chao" ¿estas kwargs representarían a los strings mencionados tal como en los diccionarios que representan los values? y la otra duda es respecto a como trabajar estos argumentos (*args y **kwargs) si no se tiene conocimiento de qué otros atributos se entregarían a los objetos. De antemano muchas gracias! Duda

pcseisdedos commented 3 years ago

Hola, es una pregunta bastante grande por lo que voy a responder por partes.

  1. Al hacer super().__init__(**kwargs), lo que debe recibir en los keyworded arguments (**kwargs) son los argumentos del init de la clase padre. En este caso hay multiherencia, sin embargo, python igual tiene una jerarquía interna para modelar esto (el orden es de izquierda a derecha). En este caso, el super en Cliente llama al init de Contacto y el super en Contacto llama al init de AdressHolder. Para verificar la jerarquía que existe en una clase puedes ocupar el método mro.
  2. Los keyworded arguments (**kwargs), se utilizan (entre otras cosas) para recibir parámetros que tienen una llave (nombre) y valor asociado, son ocupados para pasar argumentos y evitar errores con la cantidad de argumentos que se requieran, lo que se hace es definir en el método o función que corresponda los nombres (basicamente las variables/parámetros) de los argumentos que recibe, y al llamarla le paso kwargs, que debe contener en sus keys las variables que requiere la función o método en cuestión, pero también puede contener más argumentos que no se ocupan en ningún momento. Si no usamos kwargs, python interpreta que debe recibir los argumentos en orden, y si no recibe exactamente la cantidad de argumentos que requiere alega, puesto que considera que hay un error (no tiene claridad de cómo asignar los valores ingresados).
  3. Espero que en el punto 1 haya quedado claro porqué Contacto también llama al super. En este caso, AdressHolder no requiere que se llame al super, sin embargo, está ahí como una buena práctica (en principio Cliente u otra clase podría heredar primero de AdressHolder y luego de Contacto). Esto puede evitar problemas y no genera ningún inconveniente si finalmente AdressHolder no es subclase de ninguna otra, dado que TODAS las clases heredan de object, por lo tanto al llamar al super no se genera un error.
  4. Los kwargs son diccionarios que al aplicarle el operador ** quedan desempaquetados, por lo que python los interpreta como variables tal como indicas, es decir, funcion(a="hola", b="chao") es equivalente a funcion(**kwargs) con kwargs = {"a":"hola","b":"chao"}.
  5. La pregunta:

como trabajar estos argumentos (*args y **kwargs) si no se tiene conocimiento de qué otros atributos se entregarían a los objetos

Creo que queda respondida en el punto 2.

Saludos, Pablo 😁👍

iavasquez1 commented 3 years ago

Me quedo mucho mas claro!. Muchas gracias!. Disculpa la extensión de la pregunta, ya que no sabia si hacer una nueva issue o hacerla en la misma.