A série sobre acesso a atributos foi muito boa para que eu fixasse alguns conceitos de OO (Orientação a Objetos) e aprendesse um pouco mais sobre Python. Com isso, foram apresentados os métodos para acesso a atributos __getattr__() e __setattr__() e os métodos para conversão de objetos complexos, criados pelo usuário, para tipos primitivos (que também são objetos em Python, que fique claro) __str__(), __int__(), __float__(), __oct__(), __hex__(), __complex__() e __long__().
Uma outra característica interessante da linguagem é a possibilidade de sobrecarregar operadores, permitindo que o desenvolvedor crie classes cujos objetos possam ser manipulados de forma mais intuitiva. Dessa forma, no caso do exemplo que eu venho citando, da classe Clock, dados dois objetos c1 e c2 é possível que os mesmos sejam somados ou subtraídos como em c3 = c1 + c2 e c3 = c1 - c2. Sem o uso deste método, o desenvolvedor teria que fazer algo como c3 = c1.add(c2), que é menos intuitivo e mais trabalhoso de se fazer.
Acontece que Python permite a sobrecarga de alguns métodos especiais, responsáveis por realizar estas operações. Um exemplo é o método __add__(), que é responsável por sobrecarregar o operador de soma. Assim, caso a classe Clock possua este método implementado, ao se somar dois objetos Clock, o interpretador executa o método __add__() do objeto da esquerda, passando como parâmetro o objeto da direita. Vamos a um exemplo:
Neste exemplo, podemos ver implementados os métodos __add__() (10-13), __sub__() (15-29), __eq__() (31-33), __ne__() (35-36), __gt__() (38-57), __ge__() (59-60), __lt__() (62-63) e __le__() (65-66), que sobrecarregam, respectivamente, os operadores +, -, ==, !=, >, >=, < e <=. Como pode ser observado na implementação de cada um, o trabalho consiste basicamente em tratar cada atributo do objeto (self) e daquele que está sendo operado em conjunto com ele (chamado de other, na implementação). É um recurso bastante simples de se implementar e que provê um resultado excelente. Há muitos outros métodos que podem ser sobrecarregados, que possibilitam criar objetos similares aos do exemplo citado, mais adaptados à linguagem e mais fáceis de manipular. Evidentemente, o programador não precisa implementar estes métodos para todo objeto que criar: apenas quando for necessário. ;-)
Uma outra característica interessante da linguagem é a possibilidade de sobrecarregar operadores, permitindo que o desenvolvedor crie classes cujos objetos possam ser manipulados de forma mais intuitiva. Dessa forma, no caso do exemplo que eu venho citando, da classe Clock, dados dois objetos c1 e c2 é possível que os mesmos sejam somados ou subtraídos como em c3 = c1 + c2 e c3 = c1 - c2. Sem o uso deste método, o desenvolvedor teria que fazer algo como c3 = c1.add(c2), que é menos intuitivo e mais trabalhoso de se fazer.
Acontece que Python permite a sobrecarga de alguns métodos especiais, responsáveis por realizar estas operações. Um exemplo é o método __add__(), que é responsável por sobrecarregar o operador de soma. Assim, caso a classe Clock possua este método implementado, ao se somar dois objetos Clock, o interpretador executa o método __add__() do objeto da esquerda, passando como parâmetro o objeto da direita. Vamos a um exemplo:
class Clock(object): def __init__(self, hour_, minute_, second_): self.hour = hour_ self.minute = minute_ self.second = second_ def __str__(self): return "%0.2d:%0.2d:%0.2d" % (self.hour, self.minute, self.second) def __add__(self, other): return Clock((self.hour + other.hour) % 24, (self.minute + other.minute) % 60, (self.second + other.second) % 60) def __sub__(self, other): hour = self.hour - other.hour minute = self.minute - other.minute second = self.second - other.second if hour < 0: hour = 24 + hour if minute < 0: minute = 60 + minute if second < 0: second = 60 + second return Clock(hour, minute, second) def __eq__(self, other): return (self.hour == other.hour and self.minute == other.minute and self.second == other.second) def __ne__(self, other): return not(self == other) def __gt__(self, other): if self.hour > other.hour: return True elif self.hour == other.hour: if self.minute > other.minute: return True elif self.minute == other.minute: if self.second > other.second: return True else: return False else: return False else: return False def __ge__(self, other): return (self > other) or (self == other) def __lt__(self, other): return not(self > other) and not(self == other) def __le__(self, other): return (self < other) or (self == other) # # Main # c1 = Clock(18, 37, 32) c2 = Clock(20, 0, 30) print type(c1) exit(0) print "c1 object :", c1 print "c2 object :", c2 print "c1 + c2 =", c1 + c2 print "c1 - c2 =", c1 - c2 print "c1 == c2 ?", c1 == c2 print "c1 != c2 ?", c1 != c2 print "c1 > c2 ?", c1 > c2 print "c1 < c2 ?", c1 < c2 print "c1 >= c2 ?", c1 >= c2 print "c1 <= c2 ?", c1 <= c2
Listagem 1. Classe Clock implementando sobrecarga de operadores.
Neste exemplo, podemos ver implementados os métodos __add__() (10-13), __sub__() (15-29), __eq__() (31-33), __ne__() (35-36), __gt__() (38-57), __ge__() (59-60), __lt__() (62-63) e __le__() (65-66), que sobrecarregam, respectivamente, os operadores +, -, ==, !=, >, >=, < e <=. Como pode ser observado na implementação de cada um, o trabalho consiste basicamente em tratar cada atributo do objeto (self) e daquele que está sendo operado em conjunto com ele (chamado de other, na implementação). É um recurso bastante simples de se implementar e que provê um resultado excelente. Há muitos outros métodos que podem ser sobrecarregados, que possibilitam criar objetos similares aos do exemplo citado, mais adaptados à linguagem e mais fáceis de manipular. Evidentemente, o programador não precisa implementar estes métodos para todo objeto que criar: apenas quando for necessário. ;-)
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.
- Convertendo Objetos Complexos para Tipos Primários em Python - Como fazer esta conversão.
- Python 3000, Python 3.0 e Py3K – Algumas das mudanças desta versão da linguagem.
- 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.
E ai Zezim da Porquinha cor-de-rosa! ahuahauhaua
ResponderExcluirKra gostei da postagem. Você pegou alguns dos principais métodos de sobrecargas, exatamente o que estava faltando na postagem anterior.
O mais interessante é a sobrecarga inteligente, você sabe como o interpretador faz esse reconhecimento?
Abraço.
Porquinha cor de rosa... ¬¬'
ResponderExcluirQual sobrecarga inteligente você diz? O fato do interpretador encontrar o sinal de soma, por exemplo, e executar o método __add__()?
Se for isso, sei que ele faz com todos os objetos. Se uma classe precisa realizar tais operações, ela deve implementar o método e então, o interpretador, ao encontrar um operador, aciona o método específico do operador mais à esquerda (na verdade, aqui entra toda aquela história de precedência de operadores), passando como argumento, o operador da direita.
Para exemplificar, saiba que isto é o usual no interpretador: >>> '2' + '2' Mas isto também vale: >>> '2'.__add__('2'). Sabe me explicar o por quê?!
[]!