Criando getters e setters no modo “pythonico”. (#dev #python #oop)

Neste post mostro um exemplo de como criar getters e setters de forma que você possa criar fluxos mais complexos. O exemplo que utilizo vai ser uma classe que te informa se ela foi modificada ou nao desde que foi criada.

A classe que vou utilizar chama-se User e possui as seguintes propriedades: Name, Login, Password, Email e uma “propriedade privada” chamada “is_modified”.

Veja o código:

class User(object):
    def __init__(self, name: str, login: str, password: str, email: str):
        self.name = name
        self.login = login
        self.password = password
        self.email = email
        self.__is_modified__ = False

    def is_modified(self):
        return self.__is_modified__

 

Bom, esta é uma classe normal. Nada demais nela. O que vamos fazer agora é adicionar 2 métodos para cada uma das propriedades (exceto a __is_modified__, ela nao deve ser acessada de fora da classe).

Começando pela propriedade name, vamos fazer o getter:

    @property
    def name(self):
        return self.__name

O  getter é composto pelo decorator @property (nativo do python, nao precisa instalar pacotes extras), o método com o mesmo nome da propriedade que queremos criar o getter e o setter. (no caso, name). Este método apenas retorna uma propriedade chamada __name. Todavia, este nome é arbitrário, você pode colocar o nome que desejar, mas repetir o nome da propriedade, incluindo os indicadores de que ela é privada, costuma a ser uma boa ideia.

 

Agora vamos fazer o setter da propriedade name:

    @name.setter
    def name(self, value):
        if value is None:
            raise ValueError("Name cannot be none!")
        self.__is_modified__ = True
        self.__name = value

O decorator do setter é o nome do método getter, chamando o setter (@name.setter). Este método recebe um argumento, que é o novo valor da propriedade.

Você nao precisa, mas eu coloquei uma validação ali. O nome não pode ser nulo. Então, se a pessoa tentar passar uma string nula como o nome, será lançada uma exception. Também mudei o valor da propriedade __is_modified__ para True e depois fiz o que o setter deveria fazer: definir o valor da propriedade Name.

Assim como no setter, a propriedade interna nao precisa se chamar __name, mas elas tem que ter o mesmo nome entre si, ou seja, o que você usar no setter, tem que usar no getter.

 

A apliquei a mesma lógica as outras propriedades da classe:

class User(object):
    def __init__(self, name: str, login: str, password: str, email: str):
        self.name = name
        self.login = login
        self.password = password
        self.email = email
        self.__is_modified__ = False

    def is_modified(self):
        return self.__is_modified__

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, value):
        if value is None:
            raise ValueError("Name cannot be none!")
        self.__is_modified__ = True
        self.__name = value

    @property
    def login(self):
        return self.__login

    @login.setter
    def login(self, value):
        if value is None:
            raise ValueError("Login cannot be none!")
        self.__is_modified__ = True
        self.__login = value

    @property
    def password(self):
        return self.__password

    @password.setter
    def password(self, value):
        if value is None:
            raise ValueError("Password cannot be none!")
        self.__is_modified__ = True
        self.__password = value

    @property
    def email(self):
        return self.__email

    @email.setter
    def email(self, value):
        if value is None:
            raise ValueError("Email cannot be none!")
        self.__is_modified__ = True
        self.__email = value

Obviamente, a classe ficou bem maior, mas agora temos o controle sobre o que é devolvido e definido em cada propriedade da classe. No caso, garanti que nenhuma das propriedades dela serão nulas.

 

Agora para testar o método que detecta se o objeto foi modificado:

if __name__ == '__main__':
    user = User(name="John User", login="j.user", email="j.user@gmail.com", password="p4ssw0rd!")

    print(f"Created an User. Is it modified? {user.is_modified()}")

    user.name = "Updated name"

    print(f"Changed an User. Is it modified? {user.is_modified()}")

 

Exemplo de saída:

Created an User. Is it modified? False
Changed an User. Is it modified? True

 

Coloquei este exemplo no meu Github.

 

 

Espero ter ajudado!

 

The following two tabs change content below.
Arquiteto de Software e Desenvolvedor Backend (quase Fullstack), geralmente trabalho com C#, PowerShell, Python, Golang, bash e Unity (esse é mais por hobby). Estou sempre buscando algo novo para aprender, adicionando novas ferramentas ao meu cinto de utilidades.
Posted in Dev, Python and tagged , .