POO Operadors

De Cacauet Wiki
Dreceres ràpides: navegació, cerca

Els operadors ens permeten operacions matemàtiques i lògiques. Els més coneguts serien:

  • Aritmètics: + , - , * , /
  • Lògics: and , or , not , xor
  • Comparacions: > , >= , < , <= , == , !=
  • Matemàtics: mod o % (resta divisió entera) , ...

Podeu llegir una referència més detallada del model de dades de Python.

Els més utilitzats son els operadors de comparació. Amb aquests podem definir comportaments dels objectes que definim a l'hora, per exemple, de fer ordenacions (sort) de llistes d'objectes.

Teniu altres exemples d'utilització d'operadors en POO operadors 2.


Exemple amb classes Python[modifica]

Per exemple, prenem el cas de la classe "Pilota".

class Pilota(object):
   # atributs
   velocitat = 10
   posx = 10
   posy = 12
   # mètodes
   def __init__(self, x=10, y=12):
      self.posx = x
      self.posy = y
   def accelera(self):
      self.velocitat = self.velocitat + 5
   def posicio(self,x,y):
      self.posx = x
      self.posy = y

Si intentem comparar 2 instàncies sense definir res, ho farà en virtut de la seva adreça de memòria, cosa que en principi no ens resulta útil per a res:

>>> a = Pilota()
>>> b = Pilota()
>>> id(a)
3073101612L
>>> id(b)
3073101580L
>>> a > b
True

Redefinint operadors[modifica]

Redefinirem els operadors: > , < i == . Utilitzarem el criteri de distància a l'origen (podria ser un altre criteri, com el tamany).

Es poden definir les següents funcions:

  • Major que (>): __gt__ (greater than)
  • Major igual (>=): __ge__ (greater equal)
  • Menor que (<): __lt__ (less than)
  • Menor igual (<=): __le__ (less equal)
  • Igualtat (==): __eq__ (equal)
  • No igualtat (!=): __ne__ (not equal)

La distància a l'origen es defineix per:

sqrt(posx2+posy2)

Però a efectes de comparació en tenim prou en comparar els quadrats (si a>b, també es compleix a2>b2). Per tant, podem comparar:

posx2+posy2

Definim els operadors bàsics: >, < i ==

   def __gt__(self, other):
	   return self.posx**2+self.posy**2 > other.posx**2+other.posy**2
   def __lt__(self, other):
	   return self.posx**2+self.posy**2 < other.posx**2+other.posy**2
   def __eq__(self, other):
	   return self.posx**2+self.posy**2 == other.posx**2+other.posy**2

Com podeu veure, els operadors necessiten 2 paràmetres: self i other. Un és l'objecte mateix i l'altre el que se li compara. Per veure que funciona farem:

>>> a = Pilota()
>>> b = Pilota()
>>> a == b
True
>>> a > b
False
>>> 
>>> a.posx = 100
>>> a == b
False
>>> a > b
True

Ordenant llistes[modifica]

Mercès a aquests operadors, ara podem ordenar un array de Pilotes. Per poder-ho comprovar, podem canviar la representació d'una pilota (quan fem un "print" o mostrem l'array):

   def __repr__(self):
	   return "(%d,%d)"%(self.posx,self.posy)

Ara podem veure les coordenades més fàcilment:

>>> a = Pilota()
>>> a
(10,12)
>>> print a
(10,12)

Fem un array i l'ordenem:

>>> c = [ Pilota(10,10) , Pilota(100,100) , Pilota(50,10) , Pilota(1,1) ]
>>> c
[(10,10), (100,100), (50,10), (1,1)]
>>> sorted(c)
[(1,1), (10,10), (50,10), (100,100)]

També tenim el mètode .sort() però aquest modifica permanentment l'ordre de la llista.

NOTA: de fet, per poder ordenar una llista, només és necessari implementar un dels dos operadors: > o bé < . Les funcions de Python ja s'encarreguen d'utilitzar el mètode que hem implementat per la classe.


Comparant diferents tipus de dades[modifica]

Si comparem una Pilota amb un integer veurem que ens dona un error:

>>> a = 10
>>> b = Pilota()
>>> a==b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "operadors.py", line 24, in __eq__
    return self.posx*self.posy == other.posx*other.posy
AttributeError: 'int' object has no attribute 'posx'

Si ens fixem bé veurem que és perquè el nostre mètode de comparació accedeix a un atribut "posx" que un int no té.

Si volem comparar 2 tipus de dades diferents caldrà implementar la selecció de tipus dins de l'operador de comparació.

...TODO... algo així:

   def __eq__(self, other):
      if type(other)==Pilota:
         return self.posx**2+self.posy**2 == other.posx**2+other.posy**2
      elif type(other)==int:
         return other == sqrt(self.posx**2+self.posy**2)