¿Cómo crear un List de setters y getters en python?

publicado por: Anonymous

Así luce en java, tengo pasarlo a python y no tenga idea de como hacerlo.

public List<Archivo> getArchivos() {     

   return archivos;

    }


    public void setArchivos(List<Archivo> archivos) {
        this.archivos = archivos;
    }

y llevo esto en python :

class ResponseUpdateDTO(object):

def set_serial(self,serial):
    self._serial = serial
@property
def get_serial(self):
    return self._serial

def set_synergy(self,value):
    self._synergy = value
@property
def get_synergy(self):
    return self._synergy


def set_responseAzure(self,value):
    self._responseAzure = value

@property
def get_responseAzure(self):
    return self._responseAzure

#falta list de archivo

solución

Primero que nada, no hay getters o setters al estilo Java en Python. No hay forma, no existen. Se puede hacer algo parecido, si, sin duda, pero lo que hagamos no va a tener nunca la filosofía de Java. Hay un concepto que describe bien la diferencias en este sentido entre ambos lenguajes, lo puedes encontrar mencionados en muchos lugares, y es la idea del “Programador Malvado”, en Java hay un encapsulamiento muy fuerte en los objetos, ciertas propiedades las podemos acceder solo mediante los métodos apropiados, la idea es que en Java se cuida a los objetos de este hipotético Programador Malvado, en Python esa idea se la reemplaza por un: “somos todos adultos”, es decir cada uno sabe lo que está haciendo, si quieres modificar un atributo interno de un objeto, perfecto, se supone que sabes lo que estás haciendo. Por favor que nadie malinterprete esto, es simplemente una metáfora para describir las diferencias en cuanto a esta pregunta y entre ambos lenguajes, ninguna cosa es mejor que la otra, son distintas concepciones. Todo esto para volver a recalcar “no hay getters o setters al estilo Java en Python“, por más esfuerzo que le pongamos, siempre pero siempre tendremos alguna forma de acceder a los atributos internos de un objeto. Dicho esto, vayamos a tu pregunta en particular:

Voy a reescribir tu código para simplificarlo, definimos la clase ResponseUpdateDTO, a tener dos atributos serial que en principio podría ser un string, y archivos, que será una lista.

class ResponseUpdateDTO(object):

    def __init__(self):
        self._serial = ""
        self._archivos = []        

    def set_serial(self, serial):
        self._serial = serial

    def get_serial(self):
        return self._serial

    def get_archivos(self):
        return self._archivos

    def set_archivos(self, archivos):
        self._archivos = archivos

Algunos comentarios:

  • Es conveniente la mayoría de las veces definir el método __init__, no es un constructor, es simplemente uno de los primeros métodos que se ejecuta al instanciarse un objeto y por convención se suele inicializar aquí todos los atributos del objeto, también eventualmente se definen en los parámetros, que atributos se pasan en la inicialización.
  • Otra convención que has usado muy bien es nombrar atributos y métodos con el guión bajo _ delante, con esto le decimos a cualquier otro programador: “mira, estos datos y estas funciones no las uses por favor”, de hecho se quitan automáticamente de la documentación que podrías obtener mediante help(), pero no quiere decir que no puedan usarse.
  • Como puedes ver además, el pseudo getter y setter para los archivos no difiere de los otros que has definido.

Claramente como está ahora el código, podrías hacer:

r = ResponseUpdateDTO()
r.set_archivos(['archivo1', 'archivo2'])
print(r.get_archivos())

Pero también puedes hacer esto:

r._archivos = ['archivo1', 'archivo2']

Claramente no hay encapsulamiento, estás accediendo directamente al atributo _archivos que imaginamos privado, de hecho si tu setter tiene alguna lógica de validación, esta no estaría ejecutándose.
Originalmente has intentado usar “decoradores” para acercarte a la funcionalidad que esperas ver y efectivamente vas por el buen camino. Veamos como usarlos y que podemos lograr realmente:

class ResponseUpdateDTO(object):

    def __init__(self):
        self._serial = ""
        self._archivos = []        

    @property
    def serial(self):
        return self._serial

    @serial.setter
    def serial(self,serial):
        self._serial = serial

    @property
    def archivos(self):
        return self._archivos

    @archivos.setter
    def archivos(self, archivos):
        self._archivos = archivos


r = ResponseUpdateDTO()

r.archivos = ['archivo1', 'archivo2']
print(r.archivos)

¿Que hemos logrado con esto?

  • En primer lugar el método archivos se comportará como getter o
    setter en función de como lo usemos
  • Podremos incorporar lógica, en particular al setter, por ejemplo para validar los datos ingresados.

Pero, como dije al principio, siempre cabe la posibilidad de hacer esto:

r._archivos =  ['archivo1', 'archivo2']
print(r._archivos)

Pero como el concepto en Python es que todos somos adultos no debería ser un problema demasiado grande, aún así, hay una forma de impedir hacer lo anterior, que es nombrar todas las variables privadas con el doble guión bajo __, por ejemplo:

    @archivos.setter
    def archivos(self, archivos):
        self.__archivos = archivos

De esta forma, al hacer esto:

r._archivos =  ['archivo1', 'archivo2']

Obtendrás una hermosa Excepcion:

Traceback (most recent call last): File “python”, line 29, in
AttributeError: ‘ResponseUpdateDTO’ object has no attribute
‘__archivos’

Esto es nada más que un truco, lo que hace el interprete en estos casos, es “renombrar” internamente la variable como _classname__archivos, por lo que también podrías eventualmente hacer

r._ResponseUpdateDTO__archivos = ['archivo1', 'archivo2']
Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *