Design Patterns Python¶
Singleton¶
class Singleton(object):
""" renvoie tjrs la même instance """
_ref = None
def __new__(cls, *args, **kw):
if cls._ref is None:
cls._ref = super(Singleton, cls).__new__(cls, *args, **kw)
return cls._ref
class S(Singleton):
pass
Observer¶
class Event(object):
""" Classe événement """
def __init__(self, name):
self.name = name
self._observateurs = []
def __iadd__(self, observateur):
""" ajoute un observateur """
if not callable(observateur):
raise TypeError("Doit être un objet appelable")
observateurs = self._observateurs
if observateur not in observateurs:
observateurs.append(observateur)
return self
def __isub__(self, observateur):
""" retire un observateur """
observateurs = self._observateurs
if observateur in observateurs:
observers.remove(observateur)
return self
def __call__(self, *args, **kw):
""" déclenche l'événement auprès de tous les inscrits """
[observateur(*args, **kw) for observateur in self._observateurs]
utilisation
class Fenetre(object):
def __init__(self, name):
self.name = name
self.titre = 'titre de la fenêtre'
self.contenu = 'contenu de la fenêtre'
self.titreEvent = Event('titre')
self.contenuEvent = Event('contenu')
globalTitreEvent = Event('titre global')
def changeTitre(self, titre):
self.titre = titre
self.titreEvent(titre)
Fenetre.globalTitreEvent(self.name, titre)
def changeContenu(self, contenu):
self.titre = contenu
self.contenuEvent(contenu)
class ObservateurTitre(object):
def __init__(self, fenetre):
fenetre.titreEvent += self
def __call__(self, titre):
print ('le titre a été changé en "%s" !' % titre)
class ObservateurContenu(object):
def __init__(self, fenetre):
fenetre.contenuEvent += self.contenuChange
def contenuChange(self, contenu):
print('le contenu a été changé en "%s" !' % contenu)
class ObservateurGlobal(object):
def __init__(self, fenetre):
fenetre.globalTitreEvent += self
def __call__(self, name, titre):
print('le titre de "%s" a été changé en "%s" !' % (name, titre))
fenetre = Fenetre('fenetre 1')
fenetre2 = Fenetre('fenetre 2')
ob1 = ObservateurTitre(fenetre)
ob2 = ObservateurContenu(fenetre)
ob3 = ObservateurGlobal(fenetre)
fenetre.changeTitre('nouveau titre')
fenetre.changeContenu('nouveau contenu')
fenetre2.changeTitre('nouveau titre2')
Gestion des additions et soustractions d’attribut¶
méthode simple mais tout les attributs sont testés
class C(object):
def __init__(self):
self.x = 0
self.y = 0
def __setattr__(self, name, value):
"""Ne modifie pas x si la valeur est négative"""
if name == 'x' and value < 0:
return
# Pour tout autre attribut on affecte la valeur
object.__setattr__(self, name, value)
méthode plus fine
class UserList(object):
def __init__(self, val=""):
self._val = val
def __add__(self, x):
if len(self._val) > 0:
return UserList(self._val + ',' + x)
return UserList(x)
def __iadd__(self, x):
if len(self._val) > 0:
self._val = self._val + ',' + x
else:
self._val = x
return self
def __sub__(self, x):
return UserList(','.join([item for item in self._val.split(',') if item != x]))
def __isub__(self, x):
self._val = ','.join([item for item in self._val.split(',') if item != x])
return self
def __str__(self):
return str(self._val)
def __repr__(self):
return str(self._val)
class Mail(object):
def __init__(self, server="", subject="", to="", cc=None, dest=None):
self._cc = UserList()
self._for = UserList()
self.server = server
self.subject = subject
self.msg = ""
self.to = to
if cc != None: self.cc += cc
if dest != None: self.dest += dest
def getcc(self):
return self._cc
def setcc(self, val):
if not isinstance(val, UserList):
val = UserList(val)
self._cc = val
def getdest(self):
return self._for
def setdest(self, val):
if not isinstance(val, UserList):
val = UserList(val)
self._for = val
cc = property(getcc, setcc)
dest = property(getdest, setdest)
mail = Mail(server='srvxxxx1',
subject='test',
to='informatiquepz@myprop-group.com',
cc='f.bourel@myprop-group.com',
dest='a.billard@myprop-group.com')
mail.cc += 'f.gaborit@myprop-group.com'
mail.cc = mail.cc + 'f.aoustin@myprop-group.com'
mail.dest += 'appro3@myprop-group.com'
print mail.cc
print mail.dest
mail.cc -= 'f.bourel@myprop-group.com'
mail.cc = mail.cc - 'f.aoustin@myprop-group.com'
print mail.cc
producteur/consommateur¶
Le principe est le suivant:
- des objets produisent des données (ou d’autres objets)
- des objets consomment les données (ou des objets) produits par les producteurs
Il n’est possible que de consommer que ce qui est produit.
ON peut limiter le nombre d’objet à consommer ou à produire à un moment t.
Tout cela est le principe de la queue qui peut être du type FIFO, LILO ou prioritaire
Il existe pour gérer cette queue le module Queue dans python.
Dans l’exemple suivant nous gérons un magasin de stroumphs
import random
from Queue import *
from threading import Thread
import time
enStock = Queue(10)#notre pile, qui peut contenir 10 elements max( 0 pour enlever la limite)
class Magasin(Thread):
""" Le 'producteur' : va remplir ses rayons de paquets de schtroumpfs"""
def __init__(self):
self.ouvert = True
Thread.__init__(self)
def run(self):
while self.ouvert :
while not enStock.full() :
try :
enStock.put("ajout d'un paquet de schtroumpf",True,1000)
### le Magasin va ajouter un paquet dans le rayon, et s'il y a plus de place,
### va attendre pendant 1 seconde qu'un paquet soit achete .
except Full,e :
print( "Il n'y a pas de place pour un paquet !\n");
else:
print( "On ajoute un paquet de schtroumpfs dans le rayon\n")
time.sleep(10)
#on attend 10 secondes avant que le magasin aille alimenter le rayon
class Client(Thread):
""" le consommateur, va prendre un/des paquet(s) de schtroumpf"""
def __init__(self,faim,numero):
self.jAiFaim = faim
self.numero = numero
Thread.__init__(self)
def run(self):
while self.jAiFaim :
time.sleep(1)
#le client arrive au bout d'une seconde au rayon
ok=False
paquet = random.randint(1,4)
#nombre de paquet qu'il va prendre
i=1
print( "Le client n "+str(self.numero)+ " veut "+str(paquet)+ "paquet(s) de schtroumpfs\n")
while i<=paquet :
try:
enStock.get(True,500)
ok = True
print( "n "+ str(self.numero) + ": Prend un paquet\n")
except Empty, e:
ok = False
break
else:
i+=1
if ok :
print( "Il reste "+ str( enStock.qsize() ) + " paquet(s) de schtroumpfs\n")
else :
print( "n "+ str(self.numero) + ": Il n'y a pas assez de paquets\n")
self.jAiFaim = False
if __name__=='__main__':
magasin = Magasin()
magasin.ouvert = True
print("##### Le magasin ouvre ses portes #####")
magasin.start()
i=1
while i < 10:
Client(faim = True ,numero = i).start()
i=i+1
time.sleep(60)
magasin.ouvert=False
print("##### Le magasin ferme ses portes #####")
les principales types de queues
- Queue.Queue(maxsize=0)
- Queue.LifoQueue(maxsize=0)
- Queue.PriorityQueue(maxsize=0)
les principales fonctions
- Queue.qsize()
- Queue.empty()
- Queue.full()
- Queue.put(item[, block[, timeout]])
- Queue.put_nowait(item)
- Queue.get([block[, timeout]])
- Queue.get_nowait()
- Queue.task_done()
- Queue.join()