premiere version stable du cours de poo

This commit is contained in:
gwen 2017-10-02 09:10:51 +02:00
parent 86e9646de9
commit b73e7c85ff
20 changed files with 1016 additions and 406 deletions

View File

@ -0,0 +1,260 @@
Ojets en python
=================
un object est une entité possédant une identité, 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.
.. glossary::
é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 objet :
- des actions effectuées sur l'objet
- des demandes de services faites à l'objet
des 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.
héritage (est une sorte de)
---------------------------
Polymorphisme (un objet apparait comme une instance d'une classe parente)
(exemple un courrier (postal, colis, lettre) est représenté par une classe
abstraite ``Pli``::
class Pli:
get_prix(self):
raise NotImplementedError
class Lettre(Pli):
get_prix(self):
return 3
class Colis(Pli):
get_prix(self):
return 10
def genere_facture(pli):
return "prix : {0}".format(pli.get_prix())
la méthode ``get_prix`` selar appelée indépendamment du type de l'objet.
Méthode de modélisation (UML), réutilisation de code.
Mise en oeuvre de design patterns en python.
introspection
--------------
- Lintrospection est la possibilité davoir des informations sur lobjet lors de lexécution.
- `type(obj)` renvoie le type de lobjet.
- La fonction `dir(obj)` qui renvoie la liste des attributs et méthodes.
- Le module inspect contient plusieurs fonctions qui permettent davoir des informations sur les objets.
- la méthode `vars(obj)` renvoie les noms et les valeurs dun objet sous forme de
dictionnaire.
- la méthode `obj.__class__` renvoie la classe à laquelle appartient lobjet
- La fonction getattr renvoie la valeur associée à lattribut
- La fonction setattr est équivalente à obj.att = v.
- La fonction isinstance(obj, class) renvoie True si obj est une instance de class et
renvoie False sinon.
définition et syntaxe
----------------------
Une classe est la définition dun nouveau type utilisateur.
Ce type de variable rassemble plusieurs données : attributs et définit des
fonctions : méthodes.
- Un objet est une instance dune classe.
(classe <=> Type, objet <=> variable).
- Syntaxe:
Création une classe:
::
>>> class Vehicule:
pass
Création dun objet de type Vehicule:
>>> mon_vehicule = Vehicule()
attributs et méthodes
---------------------
- Les attributs permettent de stocker les informations au niveau de la classe.
- Les méthodes sont des fonctions définies dans une classe.
- Syntaxe:
::
>>> class Vehicule:
def __init__(self):
self.couleur = ''
self.vitesse = 0
def avancer(self):
self.vitesse = self.vitesse + 1
Les méthodes "__init__" et " __new__"
-------------------------------------
- La méthode `__init__` est une méthode qui est appelée automatiquement après
la création de lobjet.
- La méthode `__init__` permet dinitialiser les attributs, ce nest pas le
constructeur, cest `__new__` qui crée linstance.
Premier argument dune méthode
-------------------------------
Le premier paramètre dune méthode est une référence vers linstance, on
lappelle **self** par convention.
.. ifconfig: exercice
Définir une classe Étudiant qui a comme
attributs: nom, prenom et age et qui a
comme méthode Infos() qui affiche le nom,
le prénom et lâge de létudiant comme suit:
nom: [Prenom]
prenom: [NOM]
Age: [age]
attributs et méthodes privés
----------------------------
- En python, tout est publc. Toutes les méthodes et attributs sont
accessibles de lextérieur de la classe et peuvent être modifiés.
- Un membre (attribut ou méthode) est considéré public si nest pas précédé
dunderscore.
- Si le membre est précédé par un seul underscore il est considéré comme
protégé.
- Si le membre est précédé par deux underscores et qui se termine au plus par
un underscore, il est considéré comme "méthode spéciale".
attributs de classe et dinstance
---------------------------------
- Les attributs de classe sont accessibles sans avoir à créer une instance
de cette classe. Ce sont des variables appartenant à la classe elle-même.
- Les attributs dinstance sont accessibles après la création dun objet. Ces
attributs sont conventionnellement créés dans la méthode __init__(self).
- Exemple:
::
>>> class Vehicule:
nom = ''
def __init__(self):
self.couleur = ''
Lattribut **nom** est un attribut de classe et lattribut couleur est un
attribut dinstance.
On peut ajouter des attributs dinstance après la création de linstance.
>>> mon_vehicule.etat = 'bon'
héritage simple
---------------
- Lhéritage consiste à créer une classe dite classe fille à partir dune autre
classe dite classe mère.
- Soit B une classe qui hérite dune classe mère A
- B hérite tous les attributs et méthodes de la classe A.
- B peut avoir dautres attributs et méthodes.
- Quelques méthodes peuvent être redéfinies dans la classe B.
- Les classes B et A sont reliées par la relation est-un ( B est un A).
Syntaxe :
::
class B(A)
- Exemple:
>>> class Vehicule:
def __init__(self):
self.couleur = ''
self.vitesse = 0
>>> class Voiture(Vehicule):
pass
surcharge dattributs et de méthodes
------------------------------------
Surcharger un attribut est le fait de redéfinir sa valeur dans la classe
fille.
La surcharge dune méthode est la modification de son comportement. Il
suffit alors de redéfinir la méthode au sein de la classe. comment
appeler la méthode de la classe parente ?
Exemple:
Redéfinition de la méthode __init__:
::
>>> class Rectangle(object):
def __init__(self, a, b):
self.long = a
self.larg = b
>>> class Carre(Rectangle):
def __init__ (self, a):
self.long = a
self.larg = a
La méthode __init__ de la classe Rectangle nest appelée que si on
utilise la fonction super : super(Carre, self).__init__(a,a) appelle
automatiquement la méthode de la classe mère.
Exemple :
::
>>> class carre(Rectangle):
def __init__(self, a):
super().__init__(a, a)
héritage vs. composition
------------------------
- Lhéritage lie deux objets par une relation de type «est-un» alors que
la composition lie deux objets par une relation de type «a-un»
- Exemple:
::
>>> class Moteur:
pass
>>> class MoteurElectrique(Moteur):
pass
>>> class Voiture:
moteur = Moteur()
La classe MoteurElectrique est un Moteur (héritage).
La classe Voiture a un moteur (Composition).

View File

@ -0,0 +1,96 @@
``cli`` : command line interpreter
===================================
As Catherine Devlin, the author of `cmd2 <https://pythonhosted.org/cmd2/>`_ explained it:
| Slightly after the bronze age came the command line interpreter.
| I'm talking about **command line interpreters**
| that is somewhat more specific terms than **command line applications**
| or **command line utilities**
A command line interpreter is a program that is
- plain text
- gives you a prompt
- it gets all of its input at once
- produces his output usually as text lines
- gives you a prompt again
unix shell instructions are a good example of that.
A command line utilities is a unix-like program that gets all of its inputs at once
and gives a result at once.
At the other side, a text user interface is a litlle bit like a gui, it's closer to a gui.
at this time, you have to think of how much effort your interface is worth,
| otherwise it's gonna kill you to write it (Catherine Devlin)
Basic cli functionnalities
---------------------------
A complete command line interpreter written with ``cmd``
- it recognizes the concept of help (contextual help)
- the previous commands (history) can be called again with the keyboard's up and down arrows
- if yout hit Ctr-R and the first letters of a command you can call it again
(bash-style history)
- the tab key will finish out your command
how to use it
--------------
::
>>> from cli import Cli
>>> prompt = Cli()
>>> prompt.cmdloop()
cli (command line interpreter)
(type help or ? for commands list)
#Prompt> ?
Documented commands (type help <command>):
==========================================
EOF exit
Undocumented commands:
======================
cmd help quit
#Prompt>
to add a command, just use inheritance::
>>> from cli import Cli
>>> class Prompt(Cli):
... def do_hello(self, line):
... print "hello %s", line
...
>>> prompt = Prompt()
>>> prompt.cmdloop()
cli (command line interpreter)
(type help or ? for commands list)
#Prompt> ?
Documented commands (type help <command>):
==========================================
EOF exit
Undocumented commands:
======================
cmd hello help quit
#Prompt> hello world
.. glossary::
CLI
CLI stands for Command Line Interface, is a tool that, well, it gives you a prompt
.. literalinclude:: ../snippets/cli.py
:caption: basic command line utility library
If you want your :term:`cli` to have more functionalities, try `cm2 <http://www.phyast.pitt.edu/~micheles/python/cmd2.html>`_.
.. important:: Don't use `input()` but `raw_input()` for your command lines

View File

@ -4,6 +4,11 @@ Annexes
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
ojbML
ConstructionParFermeture
cli
symbol
wrapper
surete surete
agile agile
scrum scrum

View File

@ -0,0 +1,106 @@
Object en ocaml
===============
::
utop # let myPt =
object
val mutable x = 0
val mutable y = 0
method get_x = x
method get_y = y
method setcoord new_x new_y = x <- new_x ; y<- new_y
end;;
val myPt : < get_x : int; get_y : int; setcoord : int -> int -> unit > = <obj> ─( 17:23:21 )─< command 1 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─utop # myPt#get_x ;;
- : int = 0 ─( 17:23:24 )─< command 2 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─utop # myPt#setcoord 5 89 ;;
- : unit = () ─( 17:23:45 )─< command 3 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─utop # myPt#get_y
;;
- : int = 89
classe point
------------
::
(* ocamlg points.cmo pointClass.ml *)
open Graphics ;;
open Points ;;
open_graph " ";;
set_line_width 5 ;;
set_color magenta ;;
set_window_title "points" ;;
let p1 = new point (0,0)
let p2 = new point (3,4) ;;
p1#lineto (10,28) ;;
p1#lineto (222,55) ;;
print_string (p1#to_string ()) ;;
print_newline () ;;
p1#lineto (50, 125) ;;
ignore (read_key () ) ;;
close_graph () ;;
::
(* l'objet point comme la possibilite de lier
la representation et le dessin sur le graphe
*)
(* ocamlc graphics.cma points.ml *)
class point (x_init,y_init) =
object
val mutable x = x_init
val mutable y = y_init
method get_x = x
method get_y = y
method moveto (a,b) = x <- a ; y <- b
method rmoveto (dx,dy) = x <- x + dx ; y <- y + dy
method lineto (a, b) = Graphics.lineto a b ; x <- a ; y <- b
method to_string () =
"( " ^ (string_of_int x) ^ ", " ^ (string_of_int y) ^")"
method distance () = sqrt (float(x*x + y*y))
end ;;
(*
let p1 = new point (0,0)
let p2 = new point (3,4) ;;
p1#get_x;;
p2#get_y;;
p1#to_string();;
p1#moveto (1,2) ;;
p1#rmoveto (2,5) ;;
p1#to_string () ;;
*)
(* point avec un record
type color = Rouge | Vert | Bleu
type point = {x:int; c:color}
class point (x_init, y_init) =
object
val x = x_init
val y = y_init
method get_x = x
method get_y = y
(* a faire avec le self *)
method moveto (point:p) = point(p.get_a,p.get_b)
method rmoveto (point:p) = point(x + dx, y + dy)
method to_string () =
"( " ^ (string_of_int x) ^ ", " ^ (string_of_int y) ^")"
method distance () = sqrt (float(x*x + y*y))
end ;;
let p1 = new point (0, 0);;
let p2 = new point (3, 4);;
(*
p1#get_x;;
p2#get_y;;
p1#to_string();;
*)

View File

@ -0,0 +1,153 @@
Symbols
=======
Using sets
-----------
There are different ways of defining symbols.
You can do it very simply with sets::
>>> s = set("abc", "def", "ghi")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: set expected at most 1 arguments, got 3
>>> s = set(["abc", "def", "ghi"])
>>> s
set(['abc', 'ghi', 'def'])
>>> "abc" in s
True
>>>
If you are using python 3.X, the notation::
Python 3.5.2 (default, Sep 10 2016, 08:21:44)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 1 in {1,2,3}
True
>>>
is very effective for working with symbols.
Use immutable sets.
Using namespaces
-----------------
Here is a real world example from the tiramisu library
.. code-block:: python
# ____________________________________________________________
class _NameSpace(object):
"""convenient class that emulates a module
and builds constants (that is, unique names)
when attribute is added, we cannot delete it
"""
def __setattr__(self, name, value):
if name in self.__dict__: # pragma: optional cover
raise ConstError(_("can't rebind {0}").format(name))
self.__dict__[name] = value
def __delattr__(self, name): # pragma: optional cover
if name in self.__dict__:
raise ConstError(_("can't unbind {0}").format(name))
raise ValueError(name)
class GroupModule(_NameSpace):
"emulates a module to manage unique group (OptionDescription) names"
class GroupType(str):
"""allowed normal group (OptionDescription) names
*normal* means : groups that are not master
"""
pass
class DefaultGroupType(GroupType):
"""groups that are default (typically 'default')"""
pass
class MasterGroupType(GroupType):
"""allowed normal group (OptionDescription) names
*master* means : groups that have the 'master' attribute set
"""
pass
class OwnerModule(_NameSpace):
"""emulates a module to manage unique owner names.
owners are living in `Config._cfgimpl_value_owners`
"""
class Owner(str):
"""allowed owner names
"""
pass
class DefaultOwner(Owner):
"""groups that are default (typically 'default')"""
pass
class MultiTypeModule(_NameSpace):
"namespace for the master/slaves"
class MultiType(str):
pass
class DefaultMultiType(MultiType):
pass
class MasterMultiType(MultiType):
pass
class SlaveMultiType(MultiType):
pass
# ____________________________________________________________
def populate_groups():
"""populates the available groups in the appropriate namespaces
groups.default
default group set when creating a new optiondescription
groups.master
master group is a special optiondescription, all suboptions should be
multi option and all values should have same length, to find master's
option, the optiondescription's name should be same than de master's
option
groups.family
example of group, no special behavior with this group's type
"""
groups.default = groups.DefaultGroupType('default')
groups.master = groups.MasterGroupType('master')
groups.family = groups.GroupType('family')
def populate_owners():
"""populates the available owners in the appropriate namespaces
default
is the config owner after init time
user
is the generic is the generic owner
"""
setattr(owners, 'default', owners.DefaultOwner('default'))
setattr(owners, 'user', owners.Owner('user'))
def addowner(name):
"""
:param name: the name of the new owner
"""
setattr(owners, name, owners.Owner(name))
setattr(owners, 'addowner', addowner)
# ____________________________________________________________
# populate groups and owners with default attributes
groups = GroupModule()
populate_groups()
owners = OwnerModule()
populate_owners()

View File

@ -0,0 +1,53 @@
Wrapping
=========
a wrapper can restrict, heritage cannot.
::
# ____________________________________________________________
# Base objects
class Element:
def __init__(self, name):
self.name = name
def __repr__(self):
return "<Element %s>"% self.name
# ____________________________________________________________
# Wrapped objects
class W_Element:
def __init__(self, name, wrap):
self._name = "wrapped_element" or name
self._w = wrap
def __getattr__(self, name):
return getattr(self._w, name)
def get_w(self, name):
return getattr(self._w, name)
def set_w(self, name, value):
return setattr(self._w, name, value)
_w = property (get_w, set_w)
def __repr__(self):
return "[W_Element %s]"% repr(self._name)
# ____________________________________________________________
# tests
e = Element('element 1')
w_e = W_Element('w_element 1', e)
e.a = 2
print w_e.a
print w_e
w_e.b = 5
print w_e.b

View File

@ -1,17 +0,0 @@
let rec fact = function
|1 -> 1
| n -> n * fact (n-1) ;;
let print_fact n =
Printf.printf "factorielle %i = %i\n" n (fact n)
let main () =
begin
print_fact 5 ;
print_newline () ;
exit 0 ;
end
let _ = main ()

View File

@ -1,12 +0,0 @@
def factorielle(n):
if (n > 1):
r = n*factorielle(n-1)
else:
r = 1
return r
def print_fact(n):
print "factorielle {} = {}\n".format(5, factorielle(5))
if __name__ == '__main__':
print_fact(5)

View File

@ -56,7 +56,7 @@ source_suffix = '.txt'
master_doc = 'index' master_doc = 'index'
# General information about the project. # General information about the project.
project = u'Algorithmique Approfondie' project = u'POO'
copyright = u'2017, Gwen' copyright = u'2017, Gwen'
author = u'Gwen' author = u'Gwen'
@ -239,7 +239,7 @@ latex_elements = {
# (source start file, target name, title, # (source start file, target name, title,
# author, documentclass [howto, manual, or own class]). # author, documentclass [howto, manual, or own class]).
latex_documents = [ latex_documents = [
(master_doc, 'ProgrammationOrienteeObjet.tex', u'Cours de programmation orientée objet', (master_doc, 'ProgrammationOrienteeObjet.tex', u'Démarches objet',
u'INFAL26', 'manual'), u'INFAL26', 'manual'),
] ]
@ -269,7 +269,7 @@ latex_use_parts = False
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
(master_doc, 'algorithmique', u'Algorithmique Documentation', (master_doc, 'algorithmique', u'Démarches objet',
[author], 1) [author], 1)
] ]
@ -283,8 +283,8 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
(master_doc, 'Algorithmique', u'Algorithmique Documentation', (master_doc, 'Démarches objet', u'Démarches objet',
author, 'Algorithmique', 'One line description of project.', author, 'Démarches objet', 'One line description of project.',
'Miscellaneous'), 'Miscellaneous'),
] ]

View File

@ -0,0 +1,78 @@
Définitions
===========
Protocole à méta-objets
----------------------------
Principes ouverts, principes fermés.
exemple : les slots en python
expliquer le for en python : c'est parce que l'objet possède une méthode
__iter__
un objet avec des slots utilise moins de mémoire qu'un dict.
sinon, il en utilise plus
Termes
-------
.. glossary::
Abstraction
The details of the implementation are hidden in the object, and the external interface is just the set of publicly accessible methods.
Dynamic lookup
When a message is sent to an object, the method to be executed is determined by the implementation of the object, not by some static property of the program. In other words, different objects may react to the same message in different ways.
Subtyping
If an object a has all the functionality of an object b, then we may use a in any context where b is expected.
Inheritance
The definition of one kind of object can be reused to produce a new kind of object. This new definition can override some behavior, but also share code with its parent.
Open recursion
An object's methods can invoke another method in the same object using a special variable (often called self or this). When objects are created from classes, these calls use dynamic lookup, allowing a method defined in one class to invoke methods defined in another class that inherits from the first.
objet en python
>>> o = object()
>>> o.a = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'a'
>>>
l'objet est l'objet de base, tous les autres objets héritent de cet objet
>>> class A: pass
...
>>> isinstance(A, object)
True
>>>
Five are structural:
Abstraction Representing reality in a simplified form by removing certain distinctions so that we can see the commonalities.
Class A generalised description of similar objects that share a common structure and behaviour.
Encapsulation Data and behaviour are defined within an object and separated from everything else, protecting the internal representation of the object.
Inheritance Allows the attributes and methods of one class to be based on another existing class.
Object An individual, identifiable item, either real or abstract, which contains information about itself and the descriptions of its manipulations.
Three are behavioural:
Message The process by which an object sends Passing information or invokes a method.
Method Accessing, setting or manipulating an objects information.
Polymorphism Different objects can respond to the same message and implement it appropriately.

View File

@ -0,0 +1,92 @@
Points délicats de la programmation objet
=========================================
L'objectivisme
---------------
L'exemple des critiques de Edsger D. Dijkstra face aux objets (1983)
Les difficultés de l'objectivisme dans la programmation raisonnée.
Dans les années 60, les promesses de rédemption des "langages de haut niveau"
ne se sont pas matérialisées.
Les critiques de la lenteur du batch processing et du débugging de la
programmation procédurale ont débouché sur la nécessité de "l'interactive
programming". Cela devait "faciliter la programmation", "augmenter la
lisibilité et la compréhension du code".
Le fait est que une large part de l'histoire de la programmation peut être
écrit en termes de projets à plusieurs millions de dollars qui ont échoué dans
leurs objectifs.
Apparemment la programmation objet ne vient pas "naturellement", car
le desing objet demande beaucoup d'entrainement.
Une approche de la nouveauté consiste à se placer dans une position aussi
neutre que possible par rapport à cette nouveauté, par rapport à sa cohérence
interne. C'est comme d'apprendre une langue étrangère sans essayer de traduire
systématiquement dans sa propre langue. Il faut alors apprendre à "penser"
dans cette nouvelle langue.
La programmation objet est d'une telle nouveauté qu'il faut se libérer des
habitudes d'approcher le sujet en termes d'analogies.
La programmation raisonnée
--------------------------
**En programmation objet l'anthropomorphisme est le pire de tout.**
"And now we have the fad of making all sorts of systems and their components "intelligent"
or "smart". It often boils down to designing a wolly non-machine interface that makes
the machine as unlike a computer as possible."
Edsger D. Dijkstra
Dans le cas de la compréhension d'un programme, nous devrions nous intéresser
au programme dans sa logique propre, en ignorant temporairement le fait même
que le code va être compilé - transformé en code exécutable.
Cette approche est bien connue, elle s'appelle l'approche axiomatique.
Le point important est ici que le système de représentation anthropomorphique, l'utilisation
d'une terminologie antropomorphique érige une barrière à l'application du
programme. L'une des conséquences de l'anthropomorphisme en programmation
est que les manières les plus opérationnelles de programmer et de raisonner
sur les programmes sont alors rejetées comme "contre-intuitives", ou "trop
abstraites".
| "I think anthropomorphism is worst of all. I have now seen programs
| "trying to do things", "wanting to do things", "believing things to be
| true", "knowing things" etc. Don't be so naive as to believe that this use
| of language is harmless. It invites the programmer to identify himself
| with the execution of the program and almost forces upon him the use of
| operational semantics."
Edsger D. Dijkstra
"The anthropomorphic analogy is misleading. A computer program is a formal
system, not a collection of living beings. Forget that at your peril."
loup vaillant (loupvaillant.fr)
Le processus de la programmation raisonnée étant abstrait, sa réalisation est
subsumée à son design.
Dans ces conditions, un programme est comme un poème : on ne peut pas l'écrire
sans d'abord l'écrire. On ne le "conçoit" pas au préalable.
Mais aujourd'hui on parle de la programmation comme d'un processus de
production comme un autre, dont on peut mesurer la productivité.
(nombre de lignes de code produites, etc.)
"The pre-computer object that offers the closest analogy to a well designed
piece of software is an equally well-designed mathematical theory."
Edsger D. Dijkstra
Ceci se répercute dans notre manière d'enseigner la programmation.
Ce qui est appelé aujourd'hui "méthodologie" joue un rôle de plus en plus
important, on privilégie le design au détriment de la conception raisonnée
d'un programme.

View File

@ -1,17 +1,20 @@
Introduction à l'algorithmique Démarches objet
================================ ================================
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
presentation presentation
fondement BasesObjet
mechanism definition
prompt
langage
programme
modularite
modules
classes classes
fondement
langage
mechanism
programme
prompt
delicat
student
modularite
DesignPatterns DesignPatterns
annexes/index annexes/index

View File

@ -4,40 +4,42 @@ Mechanismes objets
L'impossible définition L'impossible définition
------------------------ ------------------------
- ObjectsAreDictionaries - maps that can readily contain "function pointers" or function containers, with language and/or syntax features that assist in or simplify the usage of these function maps.
Variation: "objects are maps that can map interfaces and/or references to other such maps."
- OO is the view that EverythingIsa a behavior (including data structures)
- OO is the "natural extension" of programmer-defined types (sometimes known as user-defined types).
- Inheritance + Encapsulation (no polymorphism): "Inheritance is what separates abstract data type (ADT) programming from OO programming." Section 19.1 of the Feb 2000 Usenet C++ FAQ, which is also published in expanded form in a popular and influential book. Inheritance without polymorphism, however, is little more than compiler-assisted CopyAndPasteProgramming. Useful, but OO?
Pour être qualifié de Orienté Objet, un langage doit être **pur**. Pour être qualifié de Orienté Objet, un langage doit être **pur**.
.. glossary:: .. glossary::
langage pur langage pur
Langae dans lequel tout est objet. Exemples : smalltalk, python Langage dans lequel tout est objet. Exemples : smalltalk, python
Les trois grandes qualités
- We should stop using the term "Object Oriented". - We should stop using the term "Object Oriented".
- plusiers définitions : http://wiki.c2.com/?DefinitionsForOo - plusieurs définitions : http://wiki.c2.com/?DefinitionsForOo
- on ne peut pas en choisir une seule : http://wiki.c2.com/?NobodyAgreesOnWhatOoIs - on ne peut pas en choisir une seule : http://wiki.c2.com/?NobodyAgreesOnWhatOoIs
- class based programming Quelques essais de définition technique :
In a class-based language (like JavaLanguage or SmalltalkLanguage), every object is an instance of a class. An object contains its own data (instance variables), but its class holds its behaviour (methods). To make a new object, you ask a class to "instantiate" itself.
- Les objets sont des dictionnaires, des clefs-valeurs qui peuvent contenir
des pointeurs sur des fonctions. Le reste n'est que sucre syntaxique.
- Variante: "objects are maps that can map interfaces and/or references to other such maps."
- OO is the view of **EverythingIsa** a behavior (including data structures)
- OO is the "natural extension" of programmer-defined types (sometimes known as user-defined types).
- Inheritance + Encapsulation (no polymorphism): "Inheritance is what separates abstract data type (ADT) programming from OO programming."
class based programming
------------------------
In a class-based language (like Python JavaLanguage or SmalltalkLanguage), every object is an instance of a class.
An object contains its own data (instance variables), but its class holds its behaviour (methods). To make a new object, you ask a class to "instantiate" itself.
An Object Oriented system, language, or environment should include at least Encapsulation, Polymorphism, and Inheritance. An Object Oriented system, language, or environment should include at least Encapsulation, Polymorphism, and Inheritance.
There is a largely accepted definition of OO: roughly the style encouraged by There is a largely accepted definition of OO: roughly the style encouraged by
Java (classes, encapsulation, inheritance, subtype polymorphism, and even Java (classes, encapsulation, inheritance, subtype polymorphism, and even
sometimes genericity). sometimes genericity).
@ -47,36 +49,41 @@ https://en.wikipedia.org/wiki/Class-based_programming
encapsulation encapsulation
-------------- --------------
- d'attributs - d'attributs
- de méthode (exposer une interface mais on ne sait pas comment cette interface est codée) - de méthode (exposer une interface mais on ne sait pas comment cette interface est codée)
Delegation Delegation
Than please define what you think delegation is. Let's start with something concrete: Than please define what you think delegation is. Let's start with something concrete:
If the method call: If the method call::
targetObject.method(x1,x2,...,x_n) targetObject.method(x1,x2,...,x_n)
Is then resolved in the body of TargetClass.method() to: Is then resolved in the body of TargetClass.method() to:
delegate.method(x1,x2,...,x_n) delegate.method(x1,x2,...,x_n)
Yet another reason is the popularity of languages that brand themselves "OO". Yet another reason is the popularity of languages that brand themselves "OO".
C++, Java, Python, Javascript, Self… New ones pop up daily. That doesn't help C++, Java, Python, Javascript, Self… New ones pop up daily. That doesn't help
define "OO", but it does makes it ever more present. define "OO", but it does makes it ever more present.
les méthodes spéciales
----------------------
Les méthodes spéciales permettent de changer la manière dont Python
réagit à certains opérateurs et accède aux attributs dune instance.
Les méthodes spéciales sont entourées de deux "__"
La liaison retardée La liaison retardée
------------------- -------------------
Internal polymorphism is the kind of polymorphism that you see in most OO computer languages. When you call a method on an object the actual function called is based on the dynamic type of the object. Internal polymorphism is the kind of polymorphism that you see in most OO computer languages. When you call a method on an object the actual function called is based on the dynamic type of the object.
Prototypes Prototypes
---------- ----------
A prototype is an object that is used as a template to create other objects. 2 mechanisms are used for this: copy and delegation. When creating a derived object from a prototype, you can copy part of the prototype. The part that isn't copied can still be accessed through a delegation pointer stored in the derived object. When you try to access a member of the derived object, and it isn't there, we walk up the delegation pointer to ask the prototype instead. A prototype is an object that is used as a template to create other objects. 2 mechanisms are used for this: copy and delegation. When creating a derived object from a prototype, you can copy part of the prototype. The part that isn't copied can still be accessed through a delegation pointer stored in the derived object. When you try to access a member of the derived object, and it isn't there, we walk up the delegation pointer to ask the prototype instead.
Prototype based programming have lots of interesting implications, that I have no experience with. I don't know how if it helps you write shorter or more modular code, especially compared to other mechanisms. I will just note that prototypes are easily implemented (or emulated) in any dynamic language with first class functions and associative maps. Prototype based programming have lots of interesting implications, that I have no experience with. I don't know how if it helps you write shorter or more modular code, especially compared to other mechanisms. I will just note that prototypes are easily implemented (or emulated) in any dynamic language with first class functions and associative maps.
@ -84,7 +91,6 @@ Prototype based programming have lots of interesting implications, that I have n
https://en.wikipedia.org/wiki/Prototype-based_programming https://en.wikipedia.org/wiki/Prototype-based_programming
In a prototype-based language, an object can contain both data and behaviour. It's a self-contained thing. To make a new object, you just call the "copy" method on an existing object. In a prototype-based language, an object can contain both data and behaviour. It's a self-contained thing. To make a new object, you just call the "copy" method on an existing object.
http://wiki.c2.com/?PrototypeBasedProgramming http://wiki.c2.com/?PrototypeBasedProgramming

View File

@ -1,313 +0,0 @@
La programmation modulaire
===========================
Il s'agit de décomposer un grand programme en
morceaux (**modules**) connectés entre eux par des **interfaces** bien
définies.
Ces modules doivent être aussi indépendants que possible.
module
ensemble de ressources liées sémantiquement
interface
mode demploi du module, avec en plus un principe de masquage
des informations (partie publique, partie secrète)
Signatures, type abstrait et langage de modules : la programmation modulaire
permet d'aller très loin dans la programmation structurée.
Définir des fonctions dans un fichier séparé
--------------------------------------------
Les fonctions peuvent être définies dans un fichier et le programme dans un
autre fichier séparé. Dans ce cas, pour pouvoir être exécuté directement avec
la commande python `nomfichierprogramme.py`, le fichier du programme doit
importer dabord les fonctions du fichier dans lequel les fonctions sont
définies.
1. Fichier de fonctions
~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: python
# Fichier foncmaxliste.py
# Recherche le premier élément maximal dans une liste ou
#dans une chaine de caractères
def max_list(L) :
k = len(L)
max, x = L[0], 0
i = 1
while i < k :
if max < L[i]:
max = L[i]
x = i
i = i + 1
return max, x
2. Fichier de programme
~~~~~~~~~~~~~~~~~~~~~~~~
Pour utilser les fonctions définies dans dautres fichiers, le fichier de
programme doit commencer par les instructions qui importent ces fichiers de
fonctions ou directement les fonctions de ces fichiers. Dans la syntaxe
ci-dessous, on importe une ou toutes les fonctions du fichier `foncmaxlist.py`.
.. code-block:: python
# Fichier progmaxlist.py
from foncmaxliste import max_list
# ou plus simple:
# from foncmaxliste import *
print max_list([4,5,6,9,12,5,10,3,18,5,6,7])
couple = max_list([4,5,6,9,12,5,10,3,18,5,6,7])
print Max de L est , couple[0]
print et se trouve à la position , couple[1]
print max_list(totovaaumarche)
couple = max_list(totovaaumarche)
print Max de L est , couple[0]
print et se trouve à la position , couple[1]
Au lieu dimporter les fonctions, on peut importer le fichier qui définit les
fonctions avec la syntaxe qui suit. Dans ce cas, le fichier de programme sera
changé comme suit :
.. code-block:: python
# Fichier prog2maxlist
import foncmaxliste
print foncmaxliste.max_list([4,5,6,9,12,5,10,3,18,5,6,7])
# la syntaxe indiquant le chemin dacces a la fonction max_list utiliser .
couple = foncmaxliste.max_list([4,5,6,9,12,5,10,3,18,5,6,7])
print Max de L est , couple[0]
print et se trouve à la position , couple[1]
print foncmaxliste.max_list(totovaaumarche)
couple = foncmaxliste.max_list(totovaaumarche)
print Max de L est , couple[0]
print et se trouve à la position , couple[1]
Lexécution directe du premier fichier de programme::
python prog max list.py
Lexécution directe du seconde fichier de programme::
python prog2 max list.py
Définition de l'implémentation d'un module
-------------------------------------------
Tout fichier qui contient au moins une définition dune fonction ou dune
variable est appelé un module (une bibliothèque). Le nom du module est le nom
du fichier enlevé le suffixe `.py`. Ainsi, un fichier de programme qui contient
au moins une définition dune fonction ou un fichier qui ne contient que des
définition de fonctions sont des modules. On peut importer un module ou des
fonctions ou variables dun module dans un programme, comme nous avons vu dans
les exemples ci-dessus.
.. important:: on peut importer un module, ou bien lancer un module en tant que
programme executable
.. code-block:: python
if __name__ == '__main__':
main()
Pour faciliter la programmation, Python définit un certain nombre de **modules internes**,
appelés les builtins (la librairie standard).
Par exemple :
Lors de louverture dune session interactive, on est dans un module interne nommé
main . Toutes les variables définies par affectation au niveau de ce module sont valides
globalement dans la session.
Dautres modules internes sont string, math, random
Dans une session de travail sous linterpréteur Python, la première importation dun mo-
dule qui, à part des fonctions quelle définit, contient des instruction de programme fait
exécuter ces instructions. Dans la même session, les importations suivantes ne font pas
exécuter ces instructions. Pour les exécuter, on utilise la fonction reload(nomdumodule)
(sans sufffixe .py).
Exemples d'interface
--------------------
::
type: son type
arguments
arg1 : description de l'argument 1
arg2 : description de l'argument 2
préconditions:
arg1 > 10
postconditions:
result < 19
raises: TypeError, AssertionError, SystemError...
test: tests nominaux pour chaque cas spécifié
- L'interface racine carrée
::
racine:
type: float -> float
arguments x: float, flottant dont on veut calculer la racine
pré: x >= 0
test: racine 25.0 -> 5.0 ; racine (-25) -> raises TypeError
- L'interface `lendemain`
Il faut définir auparavant un type spécifique appelé `date`
::
lendemain: le lendemain est la date qui désigne
le jour suivant de la date passée en argument
type: date -> date
arguments :
d: date
description: la date dont on veut calculer le lendemain
Le langages des modules
-------------------------
.. code-block:: ocaml
module type PILE = (* signature (interface) du module *)
sig
type a t
val create : unit -> a t
val push : a -> a t -> unit
val pop : a t -> a
end
(* implémentation du module *)
module Pile : PILE = (* le module est restreint
par la signature PILE *)
struct
type a t = a list ref
let create () = ref []
let push x p = p := x::!p
let pop p = match !p with [...]
let rec print p = match p with [...]
end
- `struct .. end` introduit une collection de définitions, valeurs, types ou modules.
C'est une **structure**.
- `module Nom = struct .. end` permet de donner un nom à cette structure et
c'est ça un module. C'est une structure nommée.
- `sig ... end` introduit une signature de module : une interface pour un module.
On restreint souvent une structure par une signature pour "cacher" certaines
définitions. Une signature de module fournit une **interface** entre l'extérieur
et l'intérieur d'un module.
En dehors du module, on accède à ses composants grâce à la notation pointée
.. code-block:: ocaml
let p = Pile.create()
Pile.push 45 p
Les foncteurs
--------------
Si un langage possède un langage de modules, on peut aller plus loin : on peut
considérer un module comme étant une expression de base du langage.
- La signature d'un module peut être considérée comme le type du module
- La structure du module peut être considéré comme sa valeur
Quel est l'intérêt ? On peut alors définir des **foncteurs**.
foncteur
"fonction" d'une structure vers une autre structure.
On peut ainsi paramétrer un module par un autre module.
.. code-block:: ocaml
module Nom (M1 :S1 ) (M2 :S2 ) (M3 :S3 ) ... =
struct
...
end
On applique un foncteur à des paramètres modules, pour
obtenir un nouveau module :
.. code-block:: ocaml
module M = F (Titi) (Toto)
Contrainte de type par signature
------------------------------------
::
module M =
struct
type t = int * int * int ;;
let make d m y = d, m, y ;;
end ;;
let d = M.make 8 5 8 ;;
module type S =
sig
type t ;;
val make : int -> int -> int -> t ;;
end ;;
module MS = (M:S) ;;
MS.make 5 1 2 ;;
Type et signature
------------------
::
# module type A = sig
val a: int -> int
end ;;
module type A = sig val a : int -> int end
# module B = struct
let a x = x + 1 ;;
end;;
module B : sig val a : int -> int end
# module C = (B:A) ;;
module C : A
# C.a 2 ;;
- : int = 3
#
Module auquel on impose une signature
-----------------------------------------
::
module type DATE = sig
type t
val make: int -> t
val get_year: t -> int
val get_month: t -> int
end ;;
module MR = struct
type t = int * int
let make x y = (x, y)
let get_month (x, y) = x
let get_year (x, y) = y
end ;;
module date = (MR:DATE) ;;

View File

@ -1,21 +1,18 @@
Avant propos Avant propos
============ ============
| "**Que nul n'entre ici s'il n'est géomètre**"
| Maxime apposée au porche d'entrée de l'École de Platon
| "The anthropomorphic analogy is misleading. A computer program is a formal
- L'honnête programmeur d'aujourd'hui **doit** avoir eu une réflexion approndie sur la nature | system, not a collection of living beings. Forget that at your peril."
des objets. Tous les programmeurs les utilisent, peu savent vraiment de quoi il en retourne, | Loup Vaillant
et très peu nombreux savent définir le paradigme et les mécanismes objets correctement.
.. FIXME
Introduction Introduction
~~~~~~~~~~~~ ~~~~~~~~~~~~
.. glossary:: POO .. glossary::
POO
La programmation orientée objet (POO), ou programmation par objet, est un La programmation orientée objet (POO), ou programmation par objet, est un
paradigme de programmation informatique élaboré par les Norvégiens Ole-Johan paradigme de programmation informatique élaboré par les Norvégiens Ole-Johan
@ -40,7 +37,15 @@ Objectifs de ce cours
Il s'agit de : Il s'agit de :
- maîtriser et concevoir des objets et des classes, - maîtriser et concevoir des objets et des classes,
- utiliser un langage avec une conception objet appropriée
- savoir repérer le type de support objet que propose un langage
- implémenter des objets et des classes en python
- choisir une représentation appropriée des classes, - choisir une représentation appropriée des classes,
- décomposer en sous-problèmes et affinements successifs à l'aide de la représenation objet, - décomposer en sous-problèmes et affinements successifs à l'aide de la
représentation objet ("design objet")
- devenir un honnête programmeur d'aujourd'hui, c'est-à-dire avoir une
réflexion approfondie sur la nature
des objets. Tous les programmeurs les utilisent, peu savent vraiment de quoi il en retourne,
et très peu nombreux sont ceux qui savent définir le paradigme et les mécanismes objets correctement.
.. FIXME .. FIXME

View File

@ -1,6 +1,8 @@
Interactions avec l'utilisateur Prompt objet
=============================== ===============================
Interactions avec l'utilisateur
les prompts les prompts
-------------- --------------

View File

@ -0,0 +1,34 @@
# coding: utf-8
# object oriented version
class Student:
def __init__(self, name, birth_date):
self.name = name
self.birth_date = birth_date
self.classroom = None
def move(self, classroom):
self.classroom = classroom
student1 = Student(name='pierre', birth_date=None)
student2 = Student(name='paul', birth_date=None)
student3 = Student(name='jacques', birth_date=None)
class Principal:
classrooms_registry = dict(pierre='4eme3', paul='4eme2', jacques='4eme5')
students = [student1, student2, student3]
def move_students(self):
for student in self.students:
classroom = self.classrooms_registry[student.name]
student.move(classroom)
for student in self.students:
print "The student: {} is assigned to the class {}".format(student.name, student.classroom)
principal = Principal()
if __name__ == "__main__":
principal.move_students()

View File

@ -0,0 +1,23 @@
# coding: utf-8
# procedural version
student1 = dict(name='pierre', birth_date=None)
student2 = dict(name='paul', birth_date=None)
student3 = dict(name='jacques', birth_date=None)
classrooms_registry = dict(pierre='4eme3', paul='4eme2', jacques='4eme5')
students = [student1, student2, student3]
def move_students():
for student in students:
classroom = classrooms_registry[student['name']]
student['classroom'] = classroom
for student in students:
print "The student: {} is assigned to the class {}".format(student['name'], student['classroom'])
if __name__ == "__main__":
move_students()

View File

@ -0,0 +1,36 @@
Comparaison entre style procédural et style objet
==================================================
Le principal d'un collège est debout en face d'élève de quatrième,
qui doivent être ventilés dans leurs classes respectives.
Seulement les élèves ne connaissent pas leur classe,
seul le principal les connaît.
Comment le principal peut-il affecter un élève à une classe ?
Deux solutions évidentes :
- emmener chaque étudiant dans sa classe respective
- dire à chaque étudiant quelle classe lui est assignée pour qu'il s'y rende pas lui-même
Dans le monde réel, la seconde solution est évidemment meilleure.
Dans le monde de la programmation, les deux se défendent.
Présentation antropomorphique
-----------------------------
Le cheminement procédural
-------------------------
.. literalinclude:: snippets/student_procedural.py
:language: python
:linenos:
Le cheminement objet
---------------------
.. literalinclude:: snippets/student_object.py
:language: python
:linenos: