Definició de classes
====================
Per què cal definir classes?
----------------------------
- Els tipus predefinits resulten incòmodes: `Nutrició
`_,
`Perfums
`_, ...
.. rubric:: Sense classes
.. code:: python3
>>> al1 = ('Cigrons',18,5,61)
>>> nom1 = al1[0]
>>> proteines1 = al1[1]
>>> lipids1 = al1[2]
>>> carbohidrats1 = al1[3]
.. rubric:: Amb classes
.. code:: python3
>>> al1 = Aliment('Cigrons',18,5,61)
>>> nom1 = al1.nom
>>> proteines1 = al1.proteïnes
>>> lipids1 = al1.lípids
>>> carbohidrats1 = al1.carbohidrats
- Volem agrupar dades i operacions:
:external+inf:doc:`temes/classes/Classe_Punt2D/index`,
:external+inf:doc:`temes/classes/Polinomi/index`, ...
- Tenim tipus molt semblants i volem reaprofitar codi: ``Cercle`` i
``SectorCircular`` en el mòdul :download:`figures `, ...
- ...
Què és una classe?
------------------
- Una *classe* és una plantilla a partir de la qual es poden crear
(*instanciar*) objectes.
- Direm que l'objecte ``o`` és una *instància* de la classe ``C`` si
el tipus d'``o`` és ``C``. Per exemple:
- ``3`` és una instància de la classe ``int`` perquè
>>> type(3) == int
True
>>> isinstance(3, int)
True
- ``[3, 'a']`` és una instància de la classe ``list`` perquè
>>> type([3, 'a']) == list
True
>>> isinstance([3, 'a'])
True
- Normalment les definicions de classes contenen definicions de
mètodes que operen sobre instàncies de la classe.
Sentència class
---------------
.. code:: python
class Nom:
sentències
- Defineix un nou espai de noms.
- *Atributs*: noms que es creen en executar les ``sentències``.
- *Atributs de dades*: atributs creats per assignacions. Són
*atributs de la classe*.
- *Mètodes*: atributs creats per la definició de funcions.
- Tenen un paràmetre com a mínim: ``self``.
- Crea un nou objecte (de tipus *type*).
.. include:: class.txt
:code: python
Operacions de les classes
-------------------------
- Les classes (objectes de tipus *type*) tenen dues operacions:
- Referència a un atribut.
- Instanciació: retorna una instància de la classe.
Referència a un atribut
~~~~~~~~~~~~~~~~~~~~~~~
- Sintaxi::
objecte.atribut
- Exemples:
.. include:: class_objects.txt
:code: python
`Referència a un atribut al Python Tutor `_
Instanciació
~~~~~~~~~~~~
- Sintaxi de crida a funció:
.. code:: python
io = Nom()
- Crea una instància de la classe amb els atributs de la classe
``Nom``.
- Immediatament abans de retornar la instància crida al mètode
especial ``__init__()``.
.. include:: instanciacio.txt
:code: python
`Instanciació d'una classe al Python Tutor `_
.. _metode_init:
El mètode __init__()
--------------------
- El mètode ``__init__()`` no retorna res (retorna ``None``). S'usa
per inicialitzar els *atributs de dades* de la instància. Són
*atributs de la instància*.
- El mètode ``__init__()`` pot tenir paràmetres. Aleshores l'operació
d'instanciació ha de proporcionar el arguments.
.. include:: init.txt
:code: python
`El mètode __init__() al Python Tutor `_
(Paràmetres opcionals)
~~~~~~~~~~~~~~~~~~~~~~
- Sintaxi dels paràmetres de les funcions:
.. code:: python
def f(p, o1=3, o2="abc"):
return "{2}: {0}, {1}".format(p, o1, o2)
- Exemples de crides:
.. code:: python
>>> f(-2)
'abc: -2, 3'
>>> f(-2, 5)
'abc: -2, 5'
>>> f(-2, 5, 'xyz')
'xyz: -2, 5'
>>> f(-2, o2='rst')
'rst: -2, 3'
`Paràmetres opcionals al Python Tutor `_
.. danger:: No poseu objectes mutables com a valor per defecte.
Vegeu `Why are default values shared between objects?
`__
a les :doc:`python:faq/programming`
__init__() amb paràmetres opcionals
-----------------------------------
.. include:: init_2.txt
:code: python
`El mètode __init__() amb paràmetres opcionals al Python Tutor `_
Instàncies
----------
- L'objecte ``o`` és una *instància* de la classe ``C`` si
el tipus d'``o`` és ``C``.
- Només tenen l'operació de referència a un atribut.
- L'atribut pot ser un atribut de dades o un mètode.
- Podem consultar i modificar els valors dels atributs de dades de
la instància.
- Podem cridar els mètodes de la instància.
.. include:: instance.txt
:code: python
`Instàncies al Python Tutor `_
.. _sobrecarrega_operadors:
Sobrecàrrega d'operadors
------------------------
- Els noms ``__nom__`` tenen un `significat especial
`_.
- S'usen per sobrecarregar operadors.
- Exemples:
- Operadors aritmètics: classe `Punt`__.
- Operadors relacionals: afegir a la classe punt `igualtat`__,
`menor`__ i `tota la resta`__.
- Contenidors: classe `Punt`__ com a contenidora, classes
`Escaquer`__ i `Polinomi`__.
__ http://pythontutor.com/live.html#code=class%20Punt%3A%0A%0A%20%20%20%20def%20__init__%28self,%20x%3D0,%20y%3D0%29%3A%0A%20%20%20%20%20%20%20%20self.x%20%3D%20x%0A%20%20%20%20%20%20%20%20self.y%20%3D%20y%0A%0A%20%20%20%20def%20__add__%28self,%20p%29%3A%0A%20%20%20%20%20%20%20%20return%20Punt%28self.x%2Bp.x,%20self.y%2Bp.y%29%0A%0Ap1%20%3D%20Punt%282,%203%29%0Ap2%20%3D%20Punt%281,%20-2%29%0Ap3%20%3D%20p1%20%2B%20p2&cumulative=false&curInstr=19&heapPrimitives=false&mode=display&origin=opt-live.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false
__ http://pythontutor.com/live.html#code=class%20Punt%3A%0A%0A%20%20%20%20def%20__init__%28self,%20x%3D0,%20y%3D0%29%3A%0A%20%20%20%20%20%20%20%20self.x%20%3D%20x%0A%20%20%20%20%20%20%20%20self.y%20%3D%20y%0A%0A%20%20%20%20def%20__eq__%28self,%20p%29%3A%0A%20%20%20%20%20%20%20%20return%20%28self.x,%20self.y%29%20%3D%3D%20%28p.x,%20p.y%29%0A%0Ap1%20%3D%20Punt%282,%203%29%0Ap2%20%3D%20Punt%282,%204%29%0Ap3%20%3D%20Punt%282,%203%29%0A%0Ab0%20%3D%20p1%20%3D%3D%20p3%0Ab1%20%3D%20p1%20%3D%3D%20p2%0Ab2%20%3D%20p1%20%3C%20p2%0Ab3%20%3D%20p1%20%3E%3D%20p2%0A&cumulative=false&curInstr=25&heapPrimitives=false&mode=display&origin=opt-live.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false
__ http://pythontutor.com/live.html#code=class%20Punt%3A%0A%0A%20%20%20%20def%20__init__%28self,%20x%3D0,%20y%3D0%29%3A%0A%20%20%20%20%20%20%20%20self.x%20%3D%20x%0A%20%20%20%20%20%20%20%20self.y%20%3D%20y%0A%0A%20%20%20%20def%20__eq__%28self,%20p%29%3A%0A%20%20%20%20%20%20%20%20return%20%28self.x,%20self.y%29%20%3D%3D%20%28p.x,%20p.y%29%0A%0A%20%20%20%20def%20__lt__%28self,%20p%29%3A%0A%20%20%20%20%20%20%20%20return%20%28self.x,%20self.y%29%20%3C%20%28p.x,%20p.y%29%0A%20%20%20%20%0A%0Ap1%20%3D%20Punt%282,%203%29%0Ap2%20%3D%20Punt%282,%204%29%0Ap3%20%3D%20Punt%282,%203%29%0A%0Ab0%20%3D%20p1%20%3D%3D%20p3%0Ab1%20%3D%20p1%20%3D%3D%20p2%0Ab2%20%3D%20p1%20%3C%20p2%0Ab3%20%3D%20p1%20%3E%3D%20p2%0A&cumulative=false&curInstr=29&heapPrimitives=false&mode=display&origin=opt-live.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false
__ http://pythontutor.com/live.html#code=import%20functools%0A%0A%40functools.total_ordering%0Aclass%20Punt%3A%0A%0A%20%20%20%20def%20__init__%28self,%20x%3D0,%20y%3D0%29%3A%0A%20%20%20%20%20%20%20%20self.x%20%3D%20x%0A%20%20%20%20%20%20%20%20self.y%20%3D%20y%0A%0A%20%20%20%20def%20__eq__%28self,%20p%29%3A%0A%20%20%20%20%20%20%20%20return%20%28self.x,%20self.y%29%20%3D%3D%20%28p.x,%20p.y%29%0A%0A%20%20%20%20def%20__lt__%28self,%20p%29%3A%0A%20%20%20%20%20%20%20%20return%20%28self.x,%20self.y%29%20%3C%20%28p.x,%20p.y%29%0A%0Ap1%20%3D%20Punt%282,%203%29%0Ap2%20%3D%20Punt%282,%204%29%0Ap3%20%3D%20Punt%282,%203%29%0A%0Ab0%20%3D%20p1%20%3D%3D%20p3%0Ab1%20%3D%20p1%20%3D%3D%20p2%0Ab2%20%3D%20p1%20%3C%20p2%0Ab3%20%3D%20p1%20%3E%3D%20p2&cumulative=false&curInstr=39&heapPrimitives=false&mode=display&origin=opt-live.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false
__ http://pythontutor.com/live.html#code=class%20Punt%3A%0A%0A%20%20%20%20def%20__init__%28self,%20x%3D0,%20y%3D0%29%3A%0A%20%20%20%20%20%20%20%20self.x%20%3D%20x%0A%20%20%20%20%20%20%20%20self.y%20%3D%20y%0A%0A%20%20%20%20def%20__getitem__%28self,%20i%29%3A%0A%20%20%20%20%20%20%20%20if%20i%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20r%20%3D%20self.x%0A%20%20%20%20%20%20%20%20elif%20i%20%3D%3D%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20r%20%3D%20self.y%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20IndexError%28%22L'%C3%ADndex%20nom%C3%A9s%20pot%20ser%200%20o%201%22%29%0A%20%20%20%20%20%20%20%20return%20r%0A%0A%20%20%20%20def%20__setitem__%28self,%20i,%20v%29%3A%0A%20%20%20%20%20%20%20%20if%20i%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.x%20%3D%20v%0A%20%20%20%20%20%20%20%20elif%20i%20%3D%3D%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.y%20%3D%20v%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20IndexError%28%22L'%C3%ADndex%20nom%C3%A9s%20pot%20ser%200%20o%201%22%29%0A%0Ap1%20%3D%20Punt%282,%203%29%0A%0Ax1%20%3D%20p1%5B0%5D%0Ay1%20%3D%20p1%5B1%5D%0Ab1%20%3D%20x1%20%3D%3D%20p1.x%20and%20y1%20%3D%3D%20p1.y%20%23%20b1%20ha%20de%20ser%20True%0A%0Ap1%5B0%5D%20%3D%20-5%0Ab2%20%3D%20p1.x%20%3D%3D%20-5%20%23%20b2%20ha%20de%20ser%20True&cumulative=false&curInstr=26&heapPrimitives=false&mode=display&origin=opt-live.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false
__ http://pythontutor.com/live.html#code=class%20Peca%3A%0A%0A%20%20%20%20tipus_m%20%3D%20%28'Rei',%20'Cavall',%20'%C3%80lfil',%20'Pe%C3%B3'%29%0A%20%20%20%20tipus_f%20%3D%20%28'Dama',%20'Torre'%29%0A%20%20%20%20colors_m%20%3D%20%28'Blanc',%20'Negre'%29%0A%20%20%20%20colors_f%20%3D%20%28'Blanca',%20'Negra'%29%0A%0A%20%20%20%20def%20__init__%28self,%20tipus%3D'Pe%C3%B3',%20color%3D'Blanc'%29%3A%0A%20%20%20%20%20%20%20%20self.tipus%20%3D%20tipus%0A%20%20%20%20%20%20%20%20self.color%20%3D%20color%0A%0Aclass%20Escaquer%3A%0A%0A%20%20%20%20dlletres%20%3D%20%7B'a'%3A0,%20'b'%3A1,%20'c'%3A2,%20'd'%3A3,%20'e'%3A4,%20'f'%3A5%20,%20'g'%3A6,%20'h'%3A7%7D%0A%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20def%20__init__%28self%29%3A%0A%20%20%20%20%20%20%20%20self.graella%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20for%20e%20in%20range%288%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.graella.append%28%5B'Buida'%5D*8%29%0A%0A%20%20%20%20def%20__getitem__%28self,%20pos%29%3A%0A%20%20%20%20%20%20%20%20if%20len%28pos%29%20%3D%3D%202%20and%20%28'a'%20%3C%3D%20pos%5B0%5D%20%3C%3D%20'h'%29%20and%20%28'1'%20%3C%3D%20pos%5B1%5D%20%3C%3D%20'8'%29%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20fila%20%3D%20self.dlletres%5Bpos%5B0%5D%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20columna%20%3D%20int%28pos%5B1%5D%29%20-%201%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20self.graella%5Bfila%5D%5Bcolumna%5D%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20IndexError%28'Coordenades%20no%20v%C3%A0lides'%29%0A%0A%20%20%20%20def%20__setitem__%28self,%20pos,%20peca%29%3A%0A%20%20%20%20%20%20%20%20if%20len%28pos%29%20%3D%3D%202%20and%20%28'a'%20%3C%3D%20pos%5B0%5D%20%3C%3D%20'h'%29%20and%20%28'1'%20%3C%3D%20pos%5B1%5D%20%3C%3D%20'8'%29%3A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20fila%20%3D%20self.dlletres%5Bpos%5B0%5D%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20columna%20%3D%20int%28pos%5B1%5D%29-1%0A%20%20%20%20%20%20%20%20%20%20%20%20self.graella%5Bfila%5D%5Bcolumna%5D%20%3D%20peca%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20IndexError%28'Coordenades%20no%20v%C3%A0lides'%29%0A%0Ap1%20%3D%20Peca%28'Rei',%20'Negre'%29%0Ae%20%3D%20Escaquer%28%29%0Ap2%20%3D%20e%5B'a1'%5D%0Ae%5B'a1'%5D%20%3D%20p1%0A&cumulative=false&curInstr=42&heapPrimitives=false&mode=display&origin=opt-live.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false
__ http://pythontutor.com/visualize.html#code=class+Polinomi%3A%0A%0A+++def+__init__(self)%3A%0A++++++%22%22%22%0A++++++Crea+un+polinomi+amb+tots+els+coeficients+nuls%0A++++++%22%22%22%0A++++++self.coefs+%3D+%7B%7D%0A%0A%0A+++def+__setitem__(self,+i,+v)%3A%0A++++++%22%22%22%0A++++++Assigna+v+al+coeficient+i-%C3%A8ssim+del+polinomi.%0A++++++%22%22%22%0A++++++if+v+%3D%3D+0%3A%0A+++++++++if+i+in+self.coefs%3A%0A++++++++++++self.coefs.pop(i)%0A++++++else%3A%0A+++++++++self.coefs%5Bi%5D+%3D+v%0A++++++%0A%0A+++def+__getitem__(self,+i)%3A%0A++++++%22%22%22%0A++++++Retorna+el+coeficient+i-%C3%A8ssim+del+polinomi.%0A++++++%22%22%22%0A++++++return+self.coefs.get(i,+0)%0A++++++%0A%0A+++def+grau(self)%3A%0A++++++%22%22%22%0A++++++Retorna+el+grau+del+polinomi%3B+zero+si+%C3%A9s+el+polinomi+nul.%0A++++++%22%22%22%0A++++++if+len(self.coefs)+%3D%3D+0%3A%0A+++++++++g+%3D+0%0A++++++else%3A%0A+++++++++g+%3D+max(self.coefs.keys())%0A++++++return+g%0A%0A%0A+++def+__str__(self)%3A%0A++++++%22%22%22%0A++++++Retorna+un+string+corresponent+a+la+representaci%C3%B3+del+%0A++++++polinomi+on+la+variable+es+representa+pel+car%C3%A0cter+'x'.%0A++++++%22%22%22+%0A++++++s+%3D+''%0A++++++for+i+in+range(0,self.grau()%2B1)%3A%0A+++++++++ai+%3D+self%5Bi%5D%0A+++++++++if+ai!%3D0%3A%0A++++++++++++if+ai%3E0.0%3A%0A+++++++++++++++sgn+%3D+'%2B'%0A++++++++++++else%3A%0A+++++++++++++++sgn+%3D+''%0A++++++++++++if+i%3D%3D0%3A%0A+++++++++++++++pot+%3D''%0A++++++++++++elif+i%3D%3D1%3A%0A+++++++++++++++pot+%3D+'x'%0A++++++++++++else%3A%0A+++++++++++++++pot+%3D+'x'%2B'%5E'%2Bstr(i)%0A++++++++++++coef+%3D+str(ai)%0A++++++++++++if+i%3E0%3A%0A+++++++++++++++if+ai%3D%3D1%3A%0A++++++++++++++++++coef+%3D+''%0A+++++++++++++++elif+ai%3D%3D-1%3A%0A++++++++++++++++++coef+%3D+'-'%0A++++++++++++s+%3D+sgn+%2B+coef+%2B+pot+%2B+s%0A++++++if+s%3D%3D''%3A%0A+++++++++s+%3D+'0'%0A++++++if+s.startswith('%2B')%3A%0A+++++++++s+%3D+s%5B1%3A%5D%0A++++++return+s%0A&mode=edit&origin=opt-frontend.js&cumulative=false&heapPrimitives=true&textReferences=false&showOnlyOutputs=false&py=3&rawInputLstJSON=%5B%5D
Polimorfisme
------------
- Funcions que poden ser cridades amb paràmetres de tipus diferents.
- La sobrecàrrega d'operadors és polimorfisme.
- Exemples: operadors, mòdul :download:`figures `.
.. _copia:
Còpia d'objectes
----------------
- Els objectes de les classes definides per l'usuari són mutables.
- Còpia de contenidors: llistes i diccionaris.
- Exemple: mòdul :download:`cp `.
- `cp (àlies) al Python Tutor `_
- `cp (scopia) al Python Tutor `_
- `cp (dcopy) al Python Tutor `_
Exercicis
---------
Disseny de classes sense mètodes especials (llevat de :code:`__str__`)
- :doc:`inf:temes/classes/Classe_Pessa/index`
- :doc:`inf:temes/classes/Classe_Punt2D/index`
- :doc:`inf:temes/classes/Classe_cercle/index` (llevat d\':code:`__eq__`)
- :doc:`inf:temes/classes/Classe_quadrat/index`
Disseny de classes amb mètodes especials
- :class:`~pessa_musical.PeçaMusical` i :class:`~album_base.AlbumBase`
a :doc:`inf:temes/classes/Àlbum_de_música/index`
.. eq
.. getitem, setitem, contains, len, iter
.. llista de mida fixa de peces
- :class:`~trens.Tren` a :doc:`inf:temes/classes/Classe_Tren/index`
.. getitem, len, str
.. llista dinàmica de vagons
- :class:`~polinomis.Polinomi` a :doc:`inf:temes/classes/Polinomi/index`
.. getitem, setitem
.. str, add, mul
.. vector quasi nul
- :class:`~exposicio.Exposicio` a
:doc:`inf:examens/curs2021-2022/2/RecuParcial/exposicio`
.. getitem, contains, len, iter
.. Diccionari autor, llista de fotos
- :class:`~artropode.Artropode` a
:doc:`inf:temes/classes/Artròpodes_i_aràcnids/index`
.. getitem, setitem
.. Diccionari quasi nul de (apèndix, nombre)