Bienvenido a la Comunidad de Treehouse

¿Quieres colaborar en errores de código? ¿Tienes errores que necesitan comentarios? ¿Buscas un par de ojos adicionales en tu último proyecto? aquí.

¿Buscas aprender algo nuevo?

Treehouse ofrece una prueba gratuita de siete días para estudiantes nuevos. Obtén acceso a miles de horas de contenido y únete a miles de

Inicia tu prueba gratuita

Python Conceptos Básicos de SQLAlchemy Trabajar con SQLAlchemy Creación de Nuestra Base de Datos de Libros

Usando variable como atributo

Comencé a escribir el siguiente código:

def editar():
    aeditar = str(input('Qué libro deseas editar'))
    parte = input('¿Qué deseas cambiar al respecto? \nEscribe número para seleccionar lo siguiente: \n1. Título \n2. Autor\n3. Fecha de publicación\n4. Precio\n')
    if parte == '1':
        cambia = input('¿De acuerdo, a qué deseas cambiar el título?')
        bookie = models.sesión.query(models.Libro).filter_by(title=aeditar)
        para bkie en bookie:
            bkie.title = cambia
        print(bkie)

Y repetí este bloque para cada atributo del objeto. Luego me di cuenta de que podría hacerlo más conciso escribiendo solo la parte inferior del bloque una vez e insertando algunas variables así:

    elif parte == '3':
        parte = 'pubdate'
    cambia = input(f'¿De acuerdo, a quién debo cambiar {part}?')
    bookie = models.sesión.query(models.Libro).filter_by(parte=aeditar)
    para bkie en bookie:
        bkie.parte = cambia

Esto no funciona porque una variable no puede pasarse como atributo. ¿O puede? ¿Hay alguna forma de hacer que esto funcione?

1 Respuesta

Chris Freeman
Chris Freeman
68,469 puntos

Hola Andy McDonald, ¡excelente pregunta!

Utilizando notación de asterisco, un dict puede usarse como pares de palabras clave. Si se usa part como variable, el diccionario puede definirse y expandirse como kwargs.

# definir
kwdict = {parte: aeditar}

# usar como
bookie = models.sesión.query(models.Libro).filter_by(**kwdict)

# luego 
    para bkie en bookie:
        setattr(bkie, parte, cambia)

Publica de nuevo si necesitas más ayuda. ¡Buena suerte!

A menos que me esté perdiendo algo. No creo que esta sea una sintaxis válida. Necesito pasar esto como (atributo = 'valor'}. Pasar un par clave-valor sería más como ('clave' : 'par')

Chris Freeman
Chris Freeman
68,469 puntos

He creado el siguiente código. Guarda en un archivo local y ejecuta usando python <filename>. Puede ayudarte a entender cómo usar la "notación de asterisco" para desempacar un diccionario en atributos.

import datetime


class def_init:
    def __init__(self, **kwargs):
        para clave, valor en kwargs.elementos():
            setattr(self, clave, valor)

    def __str__(self):
        return fmis atributos son: {self.__dict__}

parte = pub_date
valor1 = datetime.datetime.ahora()

kwarg_dict = {parte: valor1}

# la línea inferior muestra que un diccionario se expandirá a
# la clave se convierte en el atributo y el valor se convierte en el valor del atributo
# **{part1: value1} se convierte en (pub_date=<datetime_object>)
print("\nCreando nueva instancia usando notación de asterisco para diccionario a kwargs")
print(flos kwargs son {kwarg_dict})
an_instance = def_init(**kwarg_dict)
print(an_instance)
print(fverificar atributo pub_date: {an_instance.pub_date})

salidas:

$ python dict_init.py 

Creando new instancia usando estrella notación para dict a kwargs
kwargs son {'pub_date': datetime.datetime(2021, 8, 6, 23, 14, 6, 941012)}
mi atributos son: {'pub_date': datetime.datetime(2021, 8, 6, 23, 14, 6, 941012)}
verificación attr pub_date: 2021-08-06 23:14:06.941012

Acabo de darme cuenta de cómo usar esto y esta próxima pregunta es totalmente hipotética: Digamos que hay mucha notación de punto apilada en un objeto. ¿Cómo usarías setattr para hacer eso con el último atributo? ¿Es simplemente que cada atributo tiene su propio argumento posicional y el último argumento es aquello a lo que se establece?

Chris Freeman
Chris Freeman
68,469 puntos

Respecto a setattr usar, aquí hay algunos otros ejemplos:

class ThirdLevel:
    def __init__(self):
        self.color = red
        self.name = 3Level

    def __str__(self):
        return self.name


class SecondLevel:
    def __init__(self):
        self.s_attr = ThirdLevel()
        self.name = 2Level

    def __str__(self):
        return self.name


class TopLevel:
    def __init__(self):
        self.t_attr = SecondLevel()
        self.name = TLevel

    def __str__(self):
        return self.name

t = TopLevel()
print(1, t, t.t_attr, t.t_attr.s_attr, t.t_attr.s_attr.color)

target = t
setattr(target.t_attr.s_attr, color, blue)
print(2, t, t.t_attr, t.t_attr.s_attr, t.t_attr.s_attr.color)

deep = t.t_attr.s_attr
setattr(deep, color, green)
print(3, t, t.t_attr, t.t_attr.s_attr, t.t_attr.s_attr.color)

Resultados:

1 TLevel 2Level 3Level red
2 TLevel 2Level 3Level azul
3 TLevel 2Level 3Level green

Juega con esto. Publica si necesitas más ayuda. ¡Buena suerte!

Te volveré a contactar en 4 semanas sobre ese