modifs apres la formation a Nantes

This commit is contained in:
gwen 2013-05-15 10:47:55 +02:00
parent cdaba77a67
commit e3efe7d917
17 changed files with 217 additions and 248 deletions

View File

View File

View File

View File

View File

@ -21,8 +21,102 @@ le comportement d'un :term:`objet` :
envois de messages à l'objet = appel de **méthodes**
classes d'objets
------------------
programmation objet (première approche)
-----------------------------------------
- le type et le protocole d'un objet sont définis par sa classe
- une classe possède un ensemble d'attributs et de méthodes
deux relations possibles
~~~~~~~~~~~~~~~~~~~~~~~~~
.. glossary::
heritage
relation "est une espèce de " utilisée entre une classe et une autre classe
instantiation
relation "est une instance de " entre un objet et une classe
- est une instance de (objets par rapport à classe)
- est une espèce de (classe par rapport à classe, :term:`heritage`)
**instance**
- définition d'une classe
- instance de classe : on peut créer des objets à partir d'un type "classe"
(une classe est instanciable)
>>> class A:
... pass
...
>>> a = A()
:term:`heritage` : notation en python
>>> class A: pass
...
>>> class B(A): pass
...
>>> b = B()
>>> type(b) == B
>>> isinstance(b, A) == True
possibilité en python d'héritage multiple::
class A(B, C): pass
introspection contre encapsulation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
voir un objet comme un espace de nommage. C'est plus **agile**.
attributs et méthodes vus comme des ajouts dans l'espace de nommage
>>> a.a = 2
>>> def function(x):
... print x
...
>>> a.f = function
>>> a.f("hello")
hello
>>>
la nécessité d'un design objet
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
affichage d'une calculette, il faut créer un type `Touche`
qui contient deux désignations : `Chiffre` et `operation`::
type operation = Plus | Moins | Divise
type touche = Chiffre of int | Memoire | Op of operation
soit, on définit un type touche, soit on ne définit pas ce type::
type operation = Plus | Moins | Divise
type memoire = Memoire
type chiffre = Chiffre
- les structures de données (int, str, list, dict...) : types de base
- les structures de données utilisateur : les classes !
.. function:: type (objname)
:param objname: l'objet dont on veut connaître le type
Manipulations sur les classes et les objets
---------------------------------------------
En python un type et une classe c'est la même chose. Une classe
est un type standard. En python tout est objet, et tout provient d'un seul objet
(qui s'appelle ``object``).
- encapsulation (cacher les attributs (variables d'état)) d'un objet.
@ -32,10 +126,10 @@ 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 un ensemble d'interfaces.
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'agrégation, la délégation
.. todo:: travailler l'héritage, l'aggrégation, la délégation
Voici un exemple de classe `Voiture` :
@ -159,3 +253,12 @@ AttributeError: O instance has no attribute 'u'
>>> f.attr
'decorated'
>>>
autre exemple : les méthodes statiques
>>> class A(object):
... @staticmethod
... def my_class_method(cls):
... # do stuff here

View File

@ -7,19 +7,19 @@ L'objectif de ce cours est de vous apprendre à programmer en
:term:`python`. Ce cours a été fait avec :term:`sphinx`, l'outil de
gestion de documentation en python utilisé pour documenter python lui-même.
Avec python :
avec python :
- vous n'avez pas grand chose à savoir pour arriver à faire beaucoup de choses ;
- vous n'avez pas grand chose à savoir pour arriver à faire beaucoup de choses,
- vous allez pouvoir travailler de manière :
- vous allez pouvoir travailler de manière
- entièrement autonome ;
- rapide ;
- agile (au sens des méthodes agiles) ;
- entièrement autonome
- rapide
- agile (au sens des méthodes agiles)
- vous allez progresser rapidement ;
- vous allez progresser rapidement
- aucune connaissance préalable en programmation n'est requise ;
- aucune connaissance préalable en programmation n'est requise
- le hello world en une ligne::
@ -49,7 +49,7 @@ Avec python :
- lorsqu'on lance python sans spécifier de nom de fichier, c'est l'interpréteur
python qui est lancé (le "prompt")
Taper "python" dans votre console.
Taper "python" dans votre console
::
@ -72,20 +72,20 @@ Taper "python" dans votre console.
les modules, :ref:`namespaces` et la librairie standard
:doc:`stdlib`
Pour avoir de l'aide, taper dans le prompt :
pour avoir de l'aide, taper dans le prompt :
>>> help(function)
Usage de python
usage de python
------------------
À peu près tous les domaines de l'informatique, du scripting système à la génération
à peu près tous les domaines de l'informatique, du scripting système à la génération
de pdf en passant par le développement web et le développement rapide d'applications.
exemple : web server
Pour créer un serveur web simplement::
pour créer un serveur web simplement::
python -m SimpleHTTPServer 8000 localhost

View File

@ -9,7 +9,8 @@ apprentissage de la programmation avec python
settings
type
structures
prompt
testsunitaires
programmation python, connaissances de base
--------------------------------------------
@ -17,9 +18,9 @@ programmation python, connaissances de base
:maxdepth: 1
classes
prompt
specialmethods
stdlib
testsunitaires
Index et recherche
-------------------

View File

@ -1,7 +1,7 @@
Interactions avec l'utilisateur
===============================
Les prompts
les prompts
--------------
`raw_input` ou `input`
@ -14,10 +14,10 @@ Les prompts
.. _cmdlabel:
Le module :mod:`cmd` et les interpréteurs
le module :mod:`cmd` et les interpréteurs
--------------------------------------------
Le monde des interpréteur ligne de commande...
le monde des interpréteur ligne de commande...
Peu après l'âge de bronze vint le temps de l'interpréteur ligne de commande,
c'est-à-dire quelque chose de plus spécifique que **l'application ligne de commande**,
@ -26,18 +26,18 @@ ou que l'utilitaire ligne de commande.
Un interpréteur ligne de commande est un programme qui :
- est forcément plein texte ;
- vous donne un prompt ;
- prend toutes ses entrées d'un coup ;
- produit une sortie (typiquement des lignes de texte) ;
- vous redonne un prompt.
- est forcément plein texte
- vous donne un prompt
- prends toutes ses entrées d'un coup
- produit une sortie (typiquement des lignes de texte)
- vous redonne un prompt
Le shell unix est un bon exemple d'interpréteur ligne de commande.
Un utilitaire ligne de commande est un programme unix-like qui prend toutes
les entrées d'un coup, et qui vous renvoie une sortie d'un coup.
Le module :mod:`cmd` : exemple d'utilisation
le module :mod:`cmd` : exemple d'utilisation
.. module:: cmd
:synopsis: interpréteur ligne de commande
@ -65,8 +65,7 @@ Le module :mod:`cmd` : exemple d'utilisation
#Prompt>
Pour ajouter une commande, utilisez juste l'héritage::
pour ajouter une commande, utiliser simplement l'héritage::
>>> from cli import Cli
>>> class Prompt(Cli):
@ -92,10 +91,10 @@ Pour ajouter une commande, utilisez juste l'héritage::
.. todo:: faire un petit projet d'interpréteur ligne de commande du jeu C+/C-
Lire et écrire dans un fichier
lire et écrire dans un fichier
-------------------------------
Les **handle de fichier** (file handles)
les **handle de fichier** (file handles)
>>>

View File

@ -1,7 +1,7 @@
Mettre en place son environnement de travail
=============================================
Un framework de développement intégré : :term:`IDLE`
un framework de développement intégré : :term:`IDLE`
.. glossary::
@ -21,9 +21,9 @@ Un framework de développement intégré : :term:`IDLE`
.. _`librairie standard`: http://docs.python.org/2.7/library/index.html
Premier réflexe : consulter la doc en ligne ou bien installée sur votre disque dur.
Premier réflexe : la doc en ligne ou bien installée sur votre disque dur.
La page d'accueil de la doc officielle python :
la page d'accueil de la doc officielle python :
.. image:: images/DocPython.png
@ -32,7 +32,7 @@ modules :
.. image:: images/ModuleIndex.png
Configurer son éditeur
configurer son éditeur
----------------------
- les fichiers sources ont l'extenstion `.py`
@ -40,7 +40,7 @@ Configurer son éditeur
- les blocs sont marqués par l'indentation (utilser 4 espaces), règler
l'éditeur pour transformer les tabulations en espaces
Configurer son prompt python
configurer son prompt python
-------------------------------
.. envvar:: PYTHONPATH
@ -48,14 +48,16 @@ Configurer son prompt python
pointe par défaut sur le répertoire courant, il est possible d'ajouter
un path
À mettre dans votre `.bashrc` :
à mettre dans votre `.bashrc` :
::
export PYTHONPATH:`pwd`
export PYTHONPATH=$PYTHONPATH:'/usr/share':'/home/gwen/local
export PYTHONPATH=$PYTHONPATH:'/usr/share':'/toto/titi/tata'
alias pyenv='export PYTHONPATH=`pwd`:$PYTHONPATH'
export PYTHONSTARTUP='/home/gwen/.pystartup'
.. envvar:: PYTHONSTARTUP

0
python/formation/snippets/cli.py Executable file → Normal file
View File

View File

@ -1,10 +1,13 @@
class NotFoundError(Exception):
pass
class MaClasse:
pass
class MaClasseDeux:
pass
binding = dict('un'=MaClasse, 'deux'=MaClasseDeux)
binding = dict(un=MaClasse, deux=MaClasseDeux)
def ma_factory(key):
if key in binding:

View File

@ -1,6 +1,6 @@
class Wrap(object):
def __init__(self, name, wrap):
self.slots = ('_name', '_wrap')
self.slots = ('_name', '_w')
self._name = name or "wrapped_element"
self._w = wrap

View File

@ -3,7 +3,7 @@ Programmation python courante
.. _namespaces:
Les espaces de nommage
les espaces de nommage
-----------------------
Packages et modules::
@ -15,9 +15,9 @@ Packages et modules::
__init__.py
module2.py
À utilser pour organiser votre projet.
Permet de minimiser les risques de conflits de nom.
Permet de diminuer les entrées dans le :envvar:`PYTHONPATH`.
A utilser pour organiser votre projet
Permet de minimiser les risques de conflits de nome
Permet de diminuer les entrées dans le :envvar:`PYTHONPATH`
::
@ -35,31 +35,31 @@ Permet de diminuer les entrées dans le :envvar:`PYTHONPATH`.
from os import *
Lancer un module en tant que script :
lance un module en tant que script :
::
if __name__ == "__main__":
main()
Organisation modulaire :
Organisation modulaire
- construire des composants élémentaires ;
- combiner ces composants ;
- construire des composants élémentaires
- combiner ces composants
- utiliser une structure pyramidale : les composants sont les éléments de
composants plus complexes.
- découplage de l'ensemble en composants indépendants (gros programmes réalisables) ;
- donner de la structure (rendre les gros programmes compréhensibles) ;
- spécifier les liens entre les composants (rendre les programmes maintenables) ;
- identifier les sous-composants indépendants (rendre les programmes réutilisables) ;
- forcer l'abstraction (augmenter la sureté du programme).
- découplage de l'ensemble en composants indépendants (gros programmes réalisables)
- donner de la structure (rendre les gros programmes compréhensibles)
- spécifier les liens entre les composants (rendre les programmes maintenables)
- identifier les sous-composants indépendants (rendre les programmes réutilisables)
- forcer l'abstraction (augmenter la sureté du programme)
Les méthodes spéciales
-----------------------
Méthodes spéciales correspondant aux interfaces des types de bases :
méthodes spéciales correspondants aux interfaces des types de bases :
.. function:: __init__(self, *args, **kwargs)
le constructeur de l'instance d'objet
@ -106,9 +106,9 @@ aux attributs est règlable.
>>> cobj.__dict__['insattr']
'an instance attribute'
Les attributs ne sont pas systématiquement encapsulés en python.
les attributs ne sont pas systématiquement encapsulées en python.
Pour contrôler l'accès aux attributs, on utilise les méthodes spéciales::
pour contrôler l'accès aux attributs, on utilise les méthodes spéciales::
__getattr__(self, name)
@ -134,51 +134,6 @@ Pour contrôler l'accès aux attributs, on utilise les méthodes spéciales::
if callable(func):
func(args)
.. todo:: émulation de defaultdict
Dict with a default value
--------------------------
Il est possible d'hériter des types de base
>>> a = dict.defaultdict(default=0)
>>> a
{}
>>> a[1] = 2
>>> print a
{1: 2}
>>> a[0]
0
>>> a.keys()
[1]
>>> a["machin"]
0
::
class defaultdict(dict):
def __init__(self, default=None):
dict.__init__(self)
self.default = default
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return self.default
def __getitem__(self, key):
if key in self:
return dict.__getitem__(self, key)
else:
return self.default
def get(self, key, *args):
if not args:
args = (self.default,)
return dict.get(self, key, *args)
- un **attribut** spécial : `__slots__`
permet de fixer les attributs possibles d'une classe
@ -197,6 +152,12 @@ permet de fixer les attributs possibles d'une classe
File "<stdin>", line 1, in ?
AttributeError: 'Bar' object has no attribute 'd'
les slots
~~~~~~~~~~~
.. important:: l'encapsulation n'est pas une condition de base de la programmation
par objects, surtout que le contrôle nuit à l'agilité.
>>> class Point(object):
... __slots__ = 'x', 'y'
...

View File

@ -1,6 +1,9 @@
La :term:`librairie standard`
================================
les builtins
-------------
.. module:: builtins
:synopsis: les fonctions directement à disposition sans import spécifique
@ -134,8 +137,7 @@ Password:
.. module:: shelve
:synopsis: linéarisation de données
Linéarisation de données
==========================
- linéarisation de données
>>> import shelve
>>> shelve.open("database", 'c')

View File

@ -60,7 +60,7 @@ deux
1
>>>
Fonctions
fonctions
-----------
>>> def blabla(x):
@ -69,7 +69,7 @@ Fonctions
...
>>>
Il n'y a que des fonctions (et pas de procédures):
il n'y a que des fonctions (et pas de procédures):
>>> def ma_func(x):
@ -132,28 +132,28 @@ argumments nommés {'tata': 3, 'tutu': 2}
9
>>>
- espaces de nommage à l'intérieur d'une fonction :
- espaces de nommage à l'intérieur d'une fonction :
>>> def toto(x):
... print vars()
...
...
>>> toto("sdfsdf")
{'x': 'sdfsdf'}
>>> class A(object):pass
...
...
>>> a = A()
>>> a.a = "titi"
>>> a.b = "toto"
>>> vars(a)
{'a': 'titi', 'b': 'toto'}
Puisque tout est objet en python, ``vars(mon_objet)`` est équivalent à
puisque tout est objet en python, ``vars(mon_objet)`` est équivalent à
``mon_objet.__dict__``
- générateurs et compréhension de liste
Les compréhensions de listes permettent de générer de nouvelles listes
les compréhensions de listes permettent de générer de nouvelles listes
exemple :
@ -169,7 +169,7 @@ exemple :
[(2, 4), (2, 5), (2, 6), (2, 7), (3, 4), (3, 5), (3, 6), (3, 7), (4, 4), (4, 5), (4, 6), (4, 7)]
>>>
Les expressions générateurs
les expressions générateurs
>>> expr = (2*i for i in range(10))
>>> expr
@ -190,10 +190,10 @@ Les expressions générateurs
>>>
Le polymorphisme paramétrique
le polymorphisme paramétrique
-----------------------------
Polymorphisme exemple de contexte :
polymorphisme exemple de contexte :
la fonction print
>>> print 1
@ -203,7 +203,7 @@ la fonction print
.. todo:: `print 1` et `print "1"` renvoient le même résultat. Pourquoi ?
La programmation par exceptions
la programmation par exceptions
-------------------------------------
>>> def function_raise(x):
@ -222,84 +222,3 @@ Pas le bon type
.. important:: règle du Samouraï : une fonction doit renvoyer le résultat escompté
ou bien lever une exception
Programmation objet
--------------------
- la programmation objet définit des classes
- le type et le protocole d'un objet sont définis par sa classe
- une classe possède un ensemble d'attributs et de méthodes
>>> class A:
... pass
...
>>> a = A()
>>> a.a = 2
>>> def function(x):
... print x
...
>>> a.f = function
>>> a.f("hello")
hello
>>>
- instance de classe : on peut créer des objets à partir d'un type "classe"
(une classe est instanciable)
- définition d'une classe :
Méthode classique :
>>> class A:
... pass
...
Méthode dynamique (la fonction :func:`type` est ici un **constructeur** :
>>> type("A", (), {})
<class '__main__.A'>
>>> A = type("A", (), {})
>>> a = A()
>>> type(a)
<class '__main__.A'>
Types et classe
~~~~~~~~~~~~~~~~~
Affichage d'une calculette, il faut créer un type `Touche`
qui contient deux désignations : `Chiffre` et `operation`::
type operation = Plus | Moins | Divise
type touche = Chiffre of int | Memoire | Op of operation
Soit on définit un type touche, soit on ne définit pas ce type::
type operation = Plus | Moins | Divise
type memoire = Memoire
type chiffre = Chiffre
- les structures de données (int, str, list, dict...) : types de base
- les structures de données utilisateur : les classes !
.. function:: type (objname)
:param objname: l'objet dont on veut connaître le type
.. todo:: tout hérite de la classe `object`
>>> object
<type 'object'>
>>> type(object)
<type 'type'>
>>> type(type)
<type 'type'>
>>> type(type(type))
<type 'type'>
>>> isinstance(type, object)
True
>>> isinstance(object, object)
True
**conclusion** : en python un type et une classe c'est la même chose. Une classe
est un type standard !

View File

@ -3,14 +3,14 @@ Tests unitaires et pile d'appels
Les tests automatiques sont un complément à la déclaration des types.
Que tester, quoi tester ?
que tester, quoi tester ?
- que les composants interagissent bien entre eux
- que les unités (fonctions, objets...) réagissent bien à une entrée spécifique
- que le code se comporte de la manière attendue dans des environnements différents
(systèmes d'exploitation, etc...)
Les types de tests :
les types de tests :
- tests unitaires
- tests fonctionnels
@ -52,7 +52,7 @@ http://pytest.org/latest/
- écrire un fichier commençant par `test_` qui teste les fonctions du fichier
Options utiles dans `py.test`
options utiles dans `py.test`
------------------------------
::
@ -67,10 +67,10 @@ Options utiles dans `py.test`
py.test -k test_simple
Utiliser la pile d'appel pour débugger
utiliser la pile d'appel pour débugger
---------------------------------------
Utiliser la pile d'appels, elle se lit de bas en haut. Il est possible de
utiliser la pile d'appels, elle se lit de bas en haut. Il est possible de
provoquer cette pile d'appels.
::
@ -79,7 +79,7 @@ provoquer cette pile d'appels.
traceback.print_exc()
Traiter une exception avec
traiter une exception avec
::
@ -95,9 +95,9 @@ Traiter une exception avec
bla bla
Créer le plus possible ses propres exceptions spécifiques au programme.
créer le plus possible ses propres exceptions spécifiques au programme
Utiliser le module :mod:`pdb`
utiliser le module :mod:`pdb`
.. module:: pdb
:synopsis: debugger de la lib standard
@ -144,7 +144,7 @@ Remarquons que :mod:`pdb` utilise le module :mod:`cmd`, voir :ref:`cmdlabel` qu'
(Pdb)
Last but not least :
last but not least :
utiliser pylint ou pychecker

View File

@ -21,7 +21,7 @@ python est un langage dynamiquement typé. qu'est-ce que cela signifie ?
- ouvrir l'interpréteur python
- dans la console créer un objet de type integer, float, string, liste, dictionnaire
- vérifier les types à l'aide de la fonction `type()`
- vérifier les types à l'aide de la fonction
- vérifier que en python tout est objet
- type de base et types conteneurs
- types mutables et types immutables
@ -86,6 +86,8 @@ True
'hu'
>>>
>>> s = "ssdfsdf {0} sdfsdfsdf {1}".format("blah", "blih")
>>> s= 'a'
>>> dir(s)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
@ -118,11 +120,13 @@ index(), find(), replace()
- enlever les accents
>>> import unicodedata
>>> s = u"un été même pas chaud"
>>> import unicodedata as U
>>> s2 = ''.join(U.normalize('NFD', x)[0] for x in s)
>>> s2
u'un ete meme pas chaud'
>>>
- enlever la ponctuation
@ -132,7 +136,7 @@ u'un ete meme pas chaud'
>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
- l'encodage (unicode et la compression utf-8):
- l'encodage (unicode):
>>> u = u"éèà bla"
>>> u
@ -141,6 +145,7 @@ u'\xe9\xe8\xe0 bla'
'\xc3\xa9\xc3\xa8\xc3\xa0 bla'
>>> print u.encode("utf-8")
éèà bla
>>>
manips importantes de traitement unicode (si on n'est pas en python 3)
@ -166,6 +171,7 @@ ordinal not in range(128)
>>> s = u.encode("utf-8")
>>> type(s)
<type 'str'>
>>>
# il faut utiliser .encode(), et pas .decode()...
@ -193,6 +199,9 @@ ordinal not in range(128)
>>> l
['e', 'q']
>>>
.. important:: utiliser get plutôt que l'accès par items lorsque l'on n'est pas sûr
::
@ -361,17 +370,14 @@ Ensemble vide :
::
>>> import sets
>>> e = sets.Set()
>>> e = set()
>>> e
Set([])
>>> import sets
>>> e = sets.Set("toto")
>>> e = set("toto")
>>> e
Set(['t', 'o'])
>>> d = {"a":1,"b":2}
>>> f = sets.Set(d)
>>> f = set(d)
>>> f
Set(['a', 'b'])
@ -391,15 +397,9 @@ Appartenance et définition en extension
b
t
o
</pre>
Ajout :
<pre class="shell">
>>> e.add("a")
>>> e
Set(['a'])
>>> e.add("b", "c")
Traceback (most recent call last):
TypeError: add() takes exactly 2 arguments (3 given)
>>> for i in range(5):
... e.add(i)
...
@ -414,7 +414,6 @@ Appartenance et définition en extension
...
>>> e
# Suppression :
<pre class="shell">
>>> f = e.copy()
>>> f
Set(['a', 0, 2, 3, 4, 1])
@ -482,7 +481,6 @@ Opérations sur les ensembles
Opérations ensemblistes
::
#Pas d'opération "+" :
@ -490,14 +488,13 @@ Opérations ensemblistes
Traceback (most recent call last):
TypeError: unsupported operand type(s) for +: 'Set' and 'Set'
#La réunion :
<pre class="shell">
>>> g = e or f
>>> g
Set(['t', 'o'])
autre notation :
>>> h | e
Set(['a', 'b', 't', 'o'])
>>> h &amp; e
>>> h & e
Set(['t', 'o'])
>>>
Le complémentaire :
@ -510,28 +507,7 @@ Opérations ensemblistes
L'intersection, la réunion, le complémentaire :
>>> f
Set(['a', 2, 3, 4, 1])
>>> f &amp; e
Set(['a', 1, 2, 3, 4])
>>> f | e
Set(['a', 1, 2, 3, 4, 0])
>>> f ^ e
Set([0])
Manipulations diverses
::
>>> ''.join( sets.Set('ciao there!') &amp; sets.Set('hello!') )
'!heo'
Set(['a', 0, 2, 3, 4, 1])
>>> f = e.copy()
>>> f
Set(['a', 0, 2, 3, 4, 1])
>>> f.remove(0)
>>> f
Set(['a', 2, 3, 4, 1])
>>> f &amp; e
>>> f & e
Set(['a', 1, 2, 3, 4])
>>> f | e
Set(['a', 1, 2, 3, 4, 0])
@ -592,10 +568,13 @@ compatible, ça marche. Le typage est fort, on demande des types
TypeError: cannot concatenate 'str' and 'int' objects
>>> addition_forte("1", 4)
TypeError: cannot concatenate 'str' and 'int' objects
>>> addition_faible("a", "b")
5
Remarquons que `addition_forte` renvoie forcément un type `int` tandis
que `addition_faible` peut renvoyer un autre type, ceci est dû au
Remarquons que `addition_faible` renvoie forcément un type `int` tandis
que `addition_forte` peut renvoyer un autre type, ceci est dû au
polymorphisme paramétrique.
.. todo:: en python un type et une classe, c'est la même chose