
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ê?!
[]!