IIC2233 / syllabus-2019-1

Repositorio oficial del curso IIC2233 Programación Avanzada 🎉 🎊
43 stars 69 forks source link

Forma rápida de asignar atributos de parámetros al definir una clase #18

Closed Oisangui closed 5 years ago

Oisangui commented 5 years ago

Al definir una clase para inicializar instancias con cierto grupo de parámetros para tener como atributos a, b, c, d, e, f, etc., la forma típica es,

class MyClass():
    def __init__(self, a, b, c, d, e, f, etc.):
        self.a = a
        self.b = b
        self.c = c
        #etc.

¿Existe una forma más rápida de hacer esto?

jmwielandt commented 5 years ago

En Python 3.6.X, que es el que deben usar, no hay una forma de hacerlo. Acabo de intentarlo usando args (ver material de esta semana, se explica en multiherencia) y lanza el error: SyntaxError: can't use starred expression here

Lo que mencionas sobre usar el diccionario de la clase lo desaconsejo completamente, pues haría tu tarea difícil de corregir, lo que queramos o no puede acabar influyendo negativamente en tus resultados. En todo caso, sería escribir más.

PD: en python 3.7.X sí hay una forma, sin embargo de usarla no nos correrán tus tareas, por lo tanto no lo hagan.

Oisangui commented 5 years ago

Encontré una forma de hacerlo! :D Así:

class ManyParameters():
    def __init__(self, a, b, c, d, e, f, g):
        parameters = (a, b, c, d, e, f, g)
        strings = ('a', 'b', 'c', 'd', 'e', 'f', 'g')
        self.__dict__ = {**self.__dict__, **dict(zip(strings, parameters))}

myinst = ManyParameters(1, 2, 3, 4, 5, 6, 7)
print(myinst.b)

retorna:

2

Lo pude hacer recordando que todos los objetos tienen un __dict__, y traté de modificarlo y funcionó!

jmwielandt commented 5 years ago

Hola! Cuando uno programa debe procurar seguir ciertos estándares mínimos, el de legibilidad del código es uno y muy fundamental. De ahí salen convenciones como PEP8, que esperamos (y formativamente obligamos) que se sigan.

Si bien el método que descubriste es ingenioso (y te felicito por investigar más), dificulta la lectura del mismo y es importante que te acostumbres a escribir un código que sea fácilmente entendible por otras personas, no solo para nosotros los que lo corregiremos sino para el futuro, cuando formes parte de un equipo de programadores. También para ti mismo que, créeme, después de 6 meses sin ver el código que escribiste agradecerás mucho haber seguido ese estándar de hacer un código legible.

Como última acotación, si haces esto queda mejor (pero no lo hagas!):

class MyClass:
    def __init__(self, nombres, valores):
        # nombres: lista de nombres de los atributos
        # valores: lista de valores de los atrubutos
        self.__dict__.update(dict(zip(nombres, valores)))

instancia = MyClass(['a', 'b', 'c'], [1, 2, 3])
print(instancia.__dict__)
entamburini commented 5 years ago

Hola :)

Encuentro genial que hayas buscado una forma de hacerlo :) hay formas quizás más pythonicas de hacer lo que tu pedías (como lo que puso el @jmwielandt, es un acercamiento).

De todas formas el tema de pep8 es estricto para código en actividades y en tareas, pero no tanto para códigos de ejemplo así que te pido de que sigas con ese tipo de dudas y sigas con ese espíritu 💪

Nos vemos pronto!! ^^

Oisangui commented 5 years ago

Lo mejoré y ahora es más legible!

class Camion():
    def __init__(self, *parameters):
        attris = ('altura', 'peso', 'tonelaje', 'chofer')
        self.__dict__ = dict(zip(attris, parameters))

ahora se pueden colocar directamente sin tuplas ni listas!

camion = Camion(219, 23455, 2324, "Mauricio")
print(camion.peso)
print(camion.altura)
print(camion.chofer)
23455
219
Mauricio

y si se le colocan más argumentos de los que pide no ocurren errores porque el zip no entrega tuplas de un solo elemento.

naquiroz commented 5 years ago

Marcaré como resuelto, este issue dado que encontraste una forma de hacerlo, y los ayudantes te respondieron. Si deseas seguir discutiendo este issue, solo etiqueta a algun ayudante para que te la re-abran!.

✌️