Depois da saga sobre a criação de Getters e Setters em Python, por que não estender as funcionalidades dos nossos objetos? Uma situação que muitos programadores certamente passam é a de ter que transformar um objeto em uma string, inteiro, float etc., seja para imprimir na tela ou para prepará-lo para o banco de dados.
O que se faz normalmente nesta situação é criar um método como *2str, que faz a conversão, retornando uma string, por exemplo. Assim, para a classe Clock, proposta nos textos anteriores, haveria um método como clock2str, que seria chamado como print clock.clock2str(), retornando algo como HH:MM:SS (obviamente, o retorno depende da implementação).
Python oferece uma maneira interessante de realizar esta tarefa. Para isto, basta que o programador implemente, dentro da classe, o método __str__(). Este método não recebe qualquer atributo (exceto pelo self) e deve sempre retornar uma string. Retornar qualquer tipo diferente de string gera um erro em tempo de execução, terminando o programa. A grande vantagem de se utilizar este método é que, para imprimir a representação em string do objeto, basta fazer algo como print clock.
Similar ao __str__(), há o __int__(), que retorna um inteiro que representa o objeto. Neste caso, a conversão pode ser feita com o uso da função embutida, int(). Ao encontrar esta função, o interpretador irá procurar o método __int__() do objeto, executando-o em seguida. Da mesma forma, existem os métodos __float__(), __oct__(), __hex__(), __complex__() e __long__(), que são executados, respectivamente, para as funções float(), oct(), hex(), complex() e long().
Desta forma, podemos converter facilmente os objetos que criamos para um dos tipos primitivos de Python. Esta forma de conversão também possibilita a criação de objetos mais adaptados ao interpretador Python, uma vez que, em vez de fazer a conversão assim: objeto.toint(), pode-se fazê-la assim: int(object). Uma forma padronizada de se converter e que não exige muito esforço.
Como de praxe, segue um código de exemplo, com a classe Clock implementando os métodos citados.
O que se faz normalmente nesta situação é criar um método como *2str, que faz a conversão, retornando uma string, por exemplo. Assim, para a classe Clock, proposta nos textos anteriores, haveria um método como clock2str, que seria chamado como print clock.clock2str(), retornando algo como HH:MM:SS (obviamente, o retorno depende da implementação).
Python oferece uma maneira interessante de realizar esta tarefa. Para isto, basta que o programador implemente, dentro da classe, o método __str__(). Este método não recebe qualquer atributo (exceto pelo self) e deve sempre retornar uma string. Retornar qualquer tipo diferente de string gera um erro em tempo de execução, terminando o programa. A grande vantagem de se utilizar este método é que, para imprimir a representação em string do objeto, basta fazer algo como print clock.
Similar ao __str__(), há o __int__(), que retorna um inteiro que representa o objeto. Neste caso, a conversão pode ser feita com o uso da função embutida, int(). Ao encontrar esta função, o interpretador irá procurar o método __int__() do objeto, executando-o em seguida. Da mesma forma, existem os métodos __float__(), __oct__(), __hex__(), __complex__() e __long__(), que são executados, respectivamente, para as funções float(), oct(), hex(), complex() e long().
Nota: Na versão 3.0, o tipo long foi embutido no int, recebendo o nome deste último. Assim, a função long() foi abolida. Apesar de não ter lido especificamente isso, inferi que o método __long__() também deixou de existir.
Desta forma, podemos converter facilmente os objetos que criamos para um dos tipos primitivos de Python. Esta forma de conversão também possibilita a criação de objetos mais adaptados ao interpretador Python, uma vez que, em vez de fazer a conversão assim: objeto.toint(), pode-se fazê-la assim: int(object). Uma forma padronizada de se converter e que não exige muito esforço.
Como de praxe, segue um código de exemplo, com a classe Clock implementando os métodos citados.
class Clock: def __init__(self, hour_, minute_, second_): self.hour = hour_ self.minute = minute_ self.second = second_ def __getattr__(self, name): if name == "hour": return self._hour elif name == "minute": return self._minute elif name == "second": return self._second else: raise AttributeError, name def __setattr__(self, name, value): if name == "hour": if 0 <= value <= 23: self.__dict__["_hour"] = value else: raise ValueError, "Invalid %s value: %s" % (name, value) elif name == "minute": if 0 <= value <= 59: self.__dict__["_minute"] = value else: raise ValueError, "Invalid %s value: %s" % (name, value) elif name == "second": if 0 <= value <= 59: self.__dict__["_second"] = value else: raise ValueError, "Invalid %s value: %s" % (name, value) else: raise AttributeError, name def __str__(self): return "%d:%d:%d" % (self.hour, self.minute, self.second) def __int__(self): return int("%d%d%d" % (self.hour, self.minute, self.second)) def __float__(self): return float(int(self)) def __hex__(self): return hex(int(self)) def __oct__(self): return oct(int(self)) def __complex__(self): return complex(int(self)) def __long__(self): return long(int(self)) # Main clock = Clock(22, 48, 28) print "Object to string.: ", clock print "Object to int....: ", int(clock) print "Object to float..: ", float(clock) print "Object to octal..: ", oct(clock) print "Object to hex....: ", hex(clock) print "Object to complex: ", complex(clock) print "Object to long...: ", long(clock)
Listagem 1. Classe Clock com implementação de conversões para tipos primitivos.
Série Orientação a Objetos: Acessos a Atributos
- Getters e Setters – O básico sobre o assunto.
- Atributos Privados em Python – Como usar tais atributos nesta linguagem.
- Getters e Setters em Python como em Java – Como implementar em Python, esses métodos, no estilo Java.
- Getters e Setters em Python como em Python – Como implementar em Python, esses métodos, no estilo Python.
Leia Também
- Python 3000, Python 3.0 e Py3K – Algumas das mudanças desta versão da linguagem.
- Manipulação do PATH de Python – Como funciona e como alterar a procura por módulos em Python.
- O Estilo de Programação PEP 8 – Um ótimo estilo de programação para programadores Python.
- O Zen de Python – Um zen para boas práticas de programação.
Fala brow!
ResponderExcluirBom texto kra. Você cita uma facilidade imensurável da linguagem.
Porém, se me permite fazer uma sugestão, você poderia realizar uma nova postagem para essa série como override dos __and__, __or__, __repr__. Você poderia estender essa postagem.
Abraço brow.
Fala bro!
ResponderExcluirVocê me deu uma idéia: vou fazer uma com sobrecarga nos métodos adição e subtração, que eu esqueci os nomes agora.
Aí será possível isso:
clock0 = Clock(19, 40, 11)
clock1 = Clock(23, 0, 9)
clock2 = clock0 + clock1
clock3 = clock1 - clock0
Abraço, brother!