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)