formations/python/formation/classes.txt

162 lines
3.7 KiB
Plaintext

Définir et manipuler des classes
=================================
.. glossary::
objet
Un object est une entité possédant un type, un état, et un comportement.
Un object correspondant généralement à une entité du monde réel, mais
cette entité peut être abstraite.
On parle aussi d'**instance**.
**état d'un objet** : ensemble de propriétés auxquelles sont associées des
valeurs.
Les variables de l'objet sont appelées des **attributs**.
le comportement d'un :term:`objet` :
- des actions effectuées sur l'objet
- des appels faits sur l'objet
envois de messages à l'objet = appel de **méthodes**
classes d'objets
------------------
- encapsulation (cacher les attributs (variables d'état)) d'un objet.
- interfaces : chaque aspect d'une classe peut être vu comme une interface.
Une interface décrit un ensemble de comportements.
on peut considérer une interface comme un protocole d'utilisation d'un objet
dans un contexte donné.
on peut alors créer des outils qui sauront traiter n'importe quel objet
pourvu qu'il respecte une ensemble d'interfaces.
.. todo:: travailler l'héritage, l'aggrégation, la délégation
Voici un exemple de classe `Voiture` :
.. literalinclude:: snippets/heritage.py
:pyobject: Voiture
j'instancie ma classe `Voiture` :
>>> ma_voiture = Voiture("ma_marque", "150km/h")
>>> ma_voiture.roule()
'vroummm'
>>> ma_voiture.signaletique()
'constructeur : ma_marque, vitesse_max 150km/h'
.. todo:: faire des traitements dans l'init
- héritage (est une sorte de)
- polymorphisme : un objet apparait comme une instance d'une classe parente
.. literalinclude:: snippets/heritage.py
:pyobject: Turbo
>>> v = DoDoche("marque", 160)
>>> v.get_prix()
'7000'
>>> isinstance(v, Prix)
True
>>>
mais l'objet conserve son identité :
>>> type(v)
<type 'Voiture'>
la fonction ``achete_voiture()`` sera appelée indépendamment du type de l'objet,
du moment que l'objet a une méthode `get_prix()`, c'est le duck typing, qu'il
est préférable de ramener au polymorphisme d'objet, ou bien utiliser les :mod:`abc`
(abstract base classes).
.. literalinclude:: snippets/heritage.py
:pyobject: achete_voiture
tout le code :
.. literalinclude:: snippets/heritage.py
:download:`télécharger le code <snippets/heritage.py>`
- **l'aggrégation**
un attribut est lui-même un objet (ce qui est fréquent en python)...
.. literalinclude:: snippets/aggregation.py
- **la délégation**
la fonction "property" est un élément du design de python lui-même
.. function:: property()
les patrons de conception
---------------------------
- le patron **factory**
.. literalinclude:: snippets/patrons.py
:download:`télécharger usine (factory) <snippets/patrons.py>`
- le patron **wrapper**
:download:`télécharger wrapper <snippets/wrap.py>`
.. literalinclude:: snippets/wrap.py
exemple d'utilisation de `Wrap()`
>>> class O:
... pass
...
>>> o = O()
>>> o.a = "blah"
>>>
>>> from wrap import Wrap
>>> w = Wrap("monwrap", o)
>>> w._name
'monwrap'
>>> w._w
<__main__.O instance at 0x7fbf177aaa28>
>>> w._w.a
'blah'
>>> w.a
'blah'
>>> w.u
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "wrap.py", line 11, in __getattr__
return getattr(self._w, name)
AttributeError: O instance has no attribute 'u'
>>>
- le patron de conception **itérable**
:download:`télécharger iterable <snippets/iterable.py>`
.. literalinclude:: snippets/iterable.py
- le patron **decorateur**
:download:`télécharger decorateur <snippets/decorateur.py>`
.. literalinclude:: snippets/decorateur.py
>>> def deco(func):
... func.attr = 'decorated'
... return func
...
>>> @deco
... def f(): pass
...
>>> f.attr
'decorated'
>>>