Les Finesses de Python

Microclub 1er juin 2018

Philippe Guglielmetti


Encore Python ???

Il ne vaut pas la peine de connaître un langage qui ne modifie pas votre façon de penser la programmation. (Alan Perlis)

Python est un langage de programmation objet, multi-paradigme (wikipedia))

= on peut programmer :

  1. comme une patate
  2. comme on en a l’habitude (classes, objets, ...)
  3. comme on en a pas l’habitude
  4. comme un dieu Guido van Rossum

Notamment, Python intègre ou facilite certains patron de conception

"Gang of four" (GOF) Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides “Design Patterns - Catalogue de modèles de conceptions réutilisables” Vuibert, 1999, 490 p



mais commençons par importer quelques librairies standard et "maison" utilisées dans la suite

In [1]:
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
import itertools
import functools
import operator

from Goulib import itertools2, decorators

Types et Objets (Classes)

Python utilise un typage:

  • FORT : chaque variable désigne un objet dont le type est connu
  • DYNAMIQUE : mais une variable peut changer pour désigner un autre objet d'un autre type
  • PAS vérifié à la compilation (à moins que...)
In [2]:
a=256
print(a,type(a)) # a désigne un OBJET de type (classe...) int
256 <class 'int'>
In [3]:
print(255+1 == a, 255+1 is a) # == compare les valeurs, is compare les objets
print(a+1 == 257, a+1 is 257) # une idée de ce qui se passe ???
True True
True False
In [4]:
langue_au_chat='! nohtyP ne sinifédérp stejbo sed tnos 652 à 5- ed sreitne sel'
''.join(reversed(langue_au_chat))
Out[4]:
'les entiers de -5 à 256 sont des objets prédéfinis en Python !'
In [5]:
s="a = "+str(a) # le str est obligatoire : pas de conversion implicite
print(s,type(s))
a = 256 <class 'str'>
In [6]:
a=str(a) # a ne change pas de type, il désigne un nouvel objet (nuance...)
print(a,type(a))
256 <class 'str'>
In [7]:
def fib(n):
    """une très mauvaise implémentation de la suite de Fibonacci"""
    if n < 1: return 0
    if n < 2: return 1
    return fib(n-1) + fib(n-2)

print(fib,type(fib)) # les fonctions sont des objets aussi
<function fib at 0x0000015E3812AEA0> <class 'function'>
In [8]:
class LateX (str): # on peut dériver une classe de n'importe quel type
    
    def __init__(self, s=''): # constructeur
        self = str(s)     # utilise la méthode d'assignation de la classe str
        
    def _repr_latex_(self): # affichage dans Jupyter Notebook
        return r'$%s$'%self
    
    # une méthode est juste un champ de type fonction 
    # les "magic methods" permettent de redéfinir les opérateurs
    __add__=lambda self,right:LateX('{%s}+{%s}'%(self, right))  
    __sub__=lambda self,right:LateX('{%s}-{%s}'%(self, right)) 
    __mul__=lambda self,right:LateX('{%s}{%s}'%(self, right))
    __div__=lambda self,right:LateX('\\frac{%s}{%s}'%(self, right)) 
    __truediv__= __div__ # nécessaire pour / au lieu de //
    
(LateX(2)*'x'+1)/2
Out[8]:
$\frac{{{2}{x}}+{1}}{2}$
In [9]:
# on peut ajouter/modifier dynamiquement des méthodes à une classe
# puisque les méthodes sont aussi des objets !

def puissance_en_latex(self,right): # self n'est pas un mot réservé
    return LateX('{%s}^{%s}'%(self, right))
    
LateX.__pow__=puissance_en_latex
LateX.version=1.1

LateX('\\pi')*LateX('r')**2
Out[9]:
${\pi}{{r}^{2}}$
In [10]:
LateX().version
Out[10]:
1.1

Oui c'est TRES dangereux. Mais un principe de Python est

"We are all consenting adults here."


Iterateurs, générateurs, et programmation fonctionnelle

L'itérateur est un patron de conception qui permet de parcourir tous les éléments contenus dans un autre objet, le plus souvent un conteneur (liste, arbre, etc). Un synonyme d'itérateur est curseur, notamment dans le contexte des bases de données.

In [11]:
for i in range(10):
    print(fib(i), end=" ")
0 1 1 2 3 5 8 13 21 34 
In [12]:
r=range(10)
print(r,type(r))
range(0, 10) <class 'range'>
In [13]:
[fib(i) for i in r] # construction de liste par "compréhension"
Out[13]:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
In [14]:
res=map(fib,r)        # map applique une fonction à un itérable
print(res,type(res))  # le résultat est un itérable
<map object at 0x0000015E3813E6A0> <class 'map'>
In [15]:
functools.reduce(operator.add,res) # reduce applique répétitivement une fonction à 2 paramètres (opérateur) à un itérable
# sum(res) # aurait fait la même chose ...
Out[15]:
88
In [16]:
for obj in [1548, [1548], res, fib]:
    print(obj, itertools2.isiterable(obj))
1548 False
[1548] True
<map object at 0x0000015E3813E6A0> True
<function fib at 0x0000015E3812AEA0> False
In [17]:
def fibogen():
    logging.info('fibogen démarre...')
    n2,n1=0,1
    yield n2
    yield n1
    while True: # oui, une boucle infinie dans une fonction ...
        n1,n2=n1+n2,n1 # quand même pratique...
        yield n1
        
print(fibogen(), itertools2.isiterable(fibogen()))
<generator object fibogen at 0x0000015E38114F10> True
In [18]:
e=enumerate(fibogen())
print(e, type(e), itertools2.isiterable(e))
<enumerate object at 0x0000015E3813A4C8> <class 'enumerate'> True
In [19]:
for i,n in e:
    print(n, end=" ")
    if i>=9: break
    
INFO:root:fibogen démarre...
0 1 1 2 3 5 8 13 21 34 
In [20]:
res=itertools.islice(fibogen(),10)
print(res,type(res))  # le résultat est encore un itérable
<itertools.islice object at 0x0000015E3813CB38> <class 'itertools.islice'>
In [21]:
list(res)
INFO:root:fibogen démarre...
Out[21]:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
In [22]:
list(res) # mais attention ! un iterateur ne peut être "consommé" qu'une fois
Out[22]:
[]
In [23]:
list(itertools.islice(fibogen(),10,20))
INFO:root:fibogen démarre...
Out[23]:
[55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
In [24]:
class Fib:
    '''Fibonacci avec classe !'''
    def __iter__(self):
        logging.info('Fib.__iter__')
        self.n2, self.n1 = 0,1
        return self
    def __next__(self):
        logging.info('Fib.__next__')
        fib = self.n2
        self.n2, self.n1 = self.n1, self.n1 + self.n2
        return fib
f=Fib()    
print(f, itertools2.isiterable(f)) # une classe contenant __iter__ (et __next__) est itérable !
<__main__.Fib object at 0x0000015E3815E4A8> True
In [25]:
list(itertools.islice(f,10))
INFO:root:Fib.__iter__
INFO:root:Fib.__next__
INFO:root:Fib.__next__
INFO:root:Fib.__next__
INFO:root:Fib.__next__
INFO:root:Fib.__next__
INFO:root:Fib.__next__
INFO:root:Fib.__next__
INFO:root:Fib.__next__
INFO:root:Fib.__next__
INFO:root:Fib.__next__
Out[25]:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Introspection

Les champs+méthodes des objets peuvent être examinés. Et comme tout est objet ...

In [26]:
print(dir(LateX)) # tous les membres de la classe (beaucoup sont hérités de str)
['__add__', '__class__', '__contains__', '__delattr__', '__dict__', '__dir__', '__div__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__module__', '__mul__', '__ne__', '__new__', '__pow__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__weakref__', '_repr_latex_', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'version', 'zfill']
In [27]:
print(dir(None)) # membres de l'objet None ?
['__bool__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
In [28]:
print(dir(fib)) # membres de l'objet fonction
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
In [29]:
fib.__doc__ # pratique pour écrire des générateurs de doc ...
Out[29]:
'une très mauvaise implémentation de la suite de Fibonacci'
In [30]:
import inspect # https://docs.python.org/3/library/inspect.html
inspect.getsourcelines(fib)
Out[30]:
(['def fib(n):\n',
  '    """une très mauvaise implémentation de la suite de Fibonacci"""\n',
  '    if n < 1: return 0\n',
  '    if n < 2: return 1\n',
  '    return fib(n-1) + fib(n-2)\n'],
 1)
In [31]:
fib.__code__ # intéressant ... on y reviendra !
Out[31]:
<code object fib at 0x0000015E38123ED0, file "<ipython-input-7-7db8c3a11112>", line 1>
In [32]:
import math # un module est aussi un objet !

for name in math.__dict__: # traverse le dictionnaire de tout ce qui est défini dans le module
    f=math.__dict__[name]
    if callable(f):       # si l'objet a une méthode __call__, on peut l'appeler
        try:
            try:
                print(name+'()=',f())
                continue
            except TypeError:
                pass
            try:
                print(name+'(1)=',f(1))
                continue
            except TypeError:
                pass
            print(name+'(1,2)=',f(1,2))
        except:
            print(name+'(???)')
__loader__()= <_frozen_importlib.BuiltinImporter object at 0x0000015E3815E4A8>
acos(1)= 0.0
acosh(1)= 0.0
asin(1)= 1.5707963267948966
asinh(1)= 0.8813735870195429
atan(1)= 0.7853981633974483
atan2(1,2)= 0.4636476090008061
atanh(???)
ceil(1)= 1
copysign(1,2)= 1.0
cos(1)= 0.5403023058681398
cosh(1)= 1.5430806348152437
degrees(1)= 57.29577951308232
erf(1)= 0.842700792949715
erfc(1)= 0.157299207050285
exp(1)= 2.718281828459045
expm1(1)= 1.718281828459045
fabs(1)= 1.0
factorial(1)= 1
floor(1)= 1
fmod(1,2)= 1.0
frexp(1)= (0.5, 1)
fsum(???)
gamma(1)= 1.0
gcd(1,2)= 1
hypot(1,2)= 2.23606797749979
isclose(1,2)= False
isfinite(1)= True
isinf(1)= False
isnan(1)= False
ldexp(1,2)= 4.0
lgamma(1)= 0.0
log(1)= 0.0
log1p(1)= 0.6931471805599453
log10(1)= 0.0
log2(1)= 0.0
modf(1)= (0.0, 1.0)
pow(1,2)= 1.0
radians(1)= 0.017453292519943295
sin(1)= 0.8414709848078965
sinh(1)= 1.1752011936438014
sqrt(1)= 1.0
tan(1)= 1.5574077246549023
tanh(1)= 0.7615941559557649
trunc(1)= 1

Les Décorateurs

Un décorateur est une fonction qui modifie une fonction en l'enveloppant. C'est un patron de conception

"Gang of four" (GOF) Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides “Design Patterns - Catalogue de modèles de conceptions réutilisables” Vuibert, 1999, 490 p

Gestion du niveau de log pour debug

In [33]:
import logging # librairie standard pour loguer

logger = logging.getLogger()
logger.setLevel(logging.INFO)

logging.error("un message d'erreur s'affiche")
logging.warning("un message d'avertissement s'affiche")
logging.info("un message d'info s'affiche")
logging.debug("mais un message de debug est inférieur au level INFO")
ERROR:root:un message d'erreur s'affiche
WARNING:root:un message d'avertissement s'affiche
INFO:root:un message d'info s'affiche
In [34]:
def fonction():
    """cette fonction logue:
    * son propre nom en INFO
    * et sa doc en DEBUG
    """
    logging.info(fonction.__name__)
    def logdoc(doc):
        for s in doc.split('\n'):
            logging.debug(s)
    logdoc(fonction.__doc__)
       
fonction() # ne logue que le nom puisqu'on est au level INFO
INFO:root:fonction
In [35]:
@decorators.debug # passe en level DEBUG et ajoute des INFO à l'entrée et à la sortie
def fonction():
    """cette fonction logue:
    * son propre nom
    * et sa doc
    """
    logging.debug(fonction.__name__)
    def logdoc(doc):
        for s in doc.split('\n'):
            logging.debug(s)
    logdoc(fonction.__doc__)
    
fonction()
INFO:root:Entering fonction
DEBUG:root:fonction
DEBUG:root:cette fonction logue:
DEBUG:root:    * son propre nom
DEBUG:root:    * et sa doc
DEBUG:root:    
INFO:root:Exiting fonction
In [36]:
@decorators.debug # passe en level DEBUG et ajoute des INFO à l'entrée et à la sortie
def fonction():
    """cette fonction logue:
    * son propre nom
    * et sa doc
    """
    logging.debug(fonction.__name__)
    @decorators.nodebug # revenir en INFO pour réduire la taille du log
    def logdoc(doc):
        for s in doc.split('\n'):
            logging.debug(s)
    logdoc(fonction.__doc__)
    
fonction()
INFO:root:Entering fonction
DEBUG:root:fonction
INFO:root:Exiting fonction

Timeit

écrivons un décorateur pour chronométrer une fonction

In [37]:
import functools # librairie standard

def timeit(func):
    @functools.wraps(func) # un décorateur qui simplifie l'écriture de décorateurs...
    def wrapper(*args, **kwds):
        import time
        t=time.time()
        f_result = func(*args, **kwds)
        t=time.time()-t
        params=', '.join(map(repr,args))
        logger.info('%s(%s) took %f seconds'%(func.__name__,params,t)) 
        return f_result
    return wrapper
In [38]:
def fib(n):
    """une très mauvaise implémentation de la suite de Fibonacci"""
    if n < 2:
      return 1
    return fib(n-1) + fib(n-2)

@timeit
def tfib(n): return fib(n)

[tfib(i) for i in range(0,40,5)]
INFO:root:tfib(0) took 0.000000 seconds
INFO:root:tfib(5) took 0.000000 seconds
INFO:root:tfib(10) took 0.000000 seconds
INFO:root:tfib(15) took 0.001003 seconds
INFO:root:tfib(20) took 0.003009 seconds
INFO:root:tfib(25) took 0.036084 seconds
INFO:root:tfib(30) took 0.303837 seconds
INFO:root:tfib(35) took 3.365991 seconds
Out[38]:
[1, 8, 89, 987, 10946, 121393, 1346269, 14930352]

La Memoïsation

Patron de conception qui accélère les appels répétés à une fonction en mémorisant les résultats en fonction des paramètres

In [39]:
def memoize(obj): # disponible dans Goulib.decorators
    cache = obj.cache = {} # simple dict. il existe des implémentations à mémoire limitée
    @functools.wraps(obj)
    def memoizer(*args, **kwargs):
        key = str(args) + str(kwargs)
        if key not in cache:
            cache[key] = obj(*args, **kwargs)
        return cache[key]
    return memoizer
In [40]:
@memoize
def mfib(n):
    """la même très mauvaise implémentation de la suite de Fibonacci"""
    if n < 2:
      return 1
    return mfib(n-1) + mfib(n-2)

@timeit
def tfib(n): return mfib(n)

[tfib(i) for i in range(0,40,5)]
INFO:root:tfib(0) took 0.000000 seconds
INFO:root:tfib(5) took 0.000000 seconds
INFO:root:tfib(10) took 0.000000 seconds
INFO:root:tfib(15) took 0.000000 seconds
INFO:root:tfib(20) took 0.000000 seconds
INFO:root:tfib(25) took 0.000000 seconds
INFO:root:tfib(30) took 0.000000 seconds
INFO:root:tfib(35) took 0.000000 seconds
Out[40]:
[1, 8, 89, 987, 10946, 121393, 1346269, 14930352]
In [41]:
tfib(500)
INFO:root:tfib(500) took 0.003042 seconds
Out[41]:
225591516161936330872512695036072072046011324913758190588638866418474627738686883405015987052796968498626

Le Timeout

In [42]:
t=3
i,n = 0,0
@decorators.timeout(t) # implémentation interrompant la thread
def fibloop():
    global i,n
    while True: # boucle infinie sans le décorateur ...
        i=i+1
        n=fib(i)
        
try:
    fibloop()
except decorators.TimeoutError:
    print('en %d secondes, on peut calculer %d termes'%(t,i))
    print('le dernier est',n)
en 3 secondes, on peut calculer 33 termes
le dernier est 3524578
In [43]:
import itertools
#implémentation au niveau de l'itérateur de boucle
# dommage, pas de @itimeout for ... 
try:
    for i in decorators.itimeout(itertools.count(),t):
        n=mfib(i)
except decorators.TimeoutError:
    print('en %d secondes, on peut calculer %d termes'%(t,i))
    print('le dernier est',n)
en 3 secondes, on peut calculer 266774 termes
le dernier est 2129328592959303085943830833439223531952114640604893241598116687954524873436690351066861033808480670250428431498468229101754630206182777263662521788844078690918967937220233190583931976899071018700277741525105817755831702518441632740057377938535846432746978863675667001362039829165731498124578753841352955621309545536510831113846732982107632228332782615642112510770438516014202688292724003924428433006215872358729692384357680152914329881994846198992071295049036571916506795425482631492289715890831170999305084381240636689996304631317430706203325562657951816957945155385257182279677215300931245771341164341136890242292966031395018110307787497115698576475239905606728554420155549529962382904742041505609544931259460623342880623522214377629842824942470421390915822456543498916819596731501454685382731452113474939326291168233851818937715197091375939062189746665052992696653984729084584902546183384957996947221245942262626408039286586063430899920303653348938464086932808764511292451198684044483807276762582821691077849577876697872369243394626650969310245449017685277513775037118286884877264664397466176490417702949497535331396535738314983258307836485553908296300281636051340414377539165287133232956020520820535944116925647331595943116015529742623332839023108634129364561701279200717844590666806420347487246924260216359890761749877018589484900983673535472642530843633897550776249329614220778108062342408908513125553482158651766177229195411184931933371690866865943828912819937642660379576770568525132006837524074432102665661751850863073726579574693478745481779930204445658757356372547119980431214097993302158918791907867841952638072140475345411392312183220803267319531962576486451492373086803242789573284220734107508022149321727203910876313436466469555335790173585765334054673482740387237554883920665019053376880433344387307026895957802553721129954886038410901976349279459355746133504870915254025702101700841115570115854267417876066689742878627475316866765139562732301645634739633822324549072068424681035367677358679461415726767608898198037443853261115152745850904496686882034438184620161584324789633703495668750560215944554687531427330499652625459195435073821882330989533235337940324604516973456949024951069022161898491266286988269882412744681436538000169701805465856320355024014800021782200678145188948059843015832141576969677361582097982196857436334879362693875374684577766477609669941150420692035425633476100434727975627246390497238336654677701268547860604047789586277404288546187941722359939892623827872505789639166166489987192410788134686800583873750846996188943255399130446838295788095290823330410899629074541887023992296302419746998240667000956807057010353888348379174334717875536304662136732187323169711408535464354846350866792754663265188708337859946525862956627293260288327172297386282894510241873655278555195824207954372480690093834170986421282684902582615022967271017038194368078972917695752516764881008294095187615864219173980703791715787812097175623842369972815471018937602465279275482627583347803003707965435971955188190272633709106822604787821752357231563894943869004088883096324790991995183368372610423147883194494722213575277652070845938808347395334498331196956701036996881424503120567459538018184304241957881441029756063493152228190471684193011061088086620828861207756672419813648762642395433200515153004359243701127191323914477483964482219154748253313668922799633630738706489975442601527999700483695867396136255970695241386505280711674470427481362557488180661738315959355710205943015065633497845052904391941620503796556994085246402507308403488720826528704992667963342361441166647328898110951294848884782626642481508106376916550214183037938693566150122603365037165797877564796142020332899244582112405816297796382082234324141455758665737947126000412151274338157817237963641309622048817837447330580139576396722127150901653257636814913387312982899915780581242563632806772960419465480429019238706644352577816280984258688163933969738534506530976067736829029814822163462197143856275187764841626725877508267330218525367669291169432689433208963073638286111970331534894729657090905279166340121981115739007717438504463916907662382247520407725625430509563057835687036570867184187511180401851778676763434914020160722081179270130057601288446813818894525523835642507906203514680717888528701898885623515537196645834158025982741071511770634796582973628516973382150609940228198596657805646645934979168347147470924008222373643819895571793212981162562628914093427346130795634590034655328966101582755094147970725652326612074309584008584563269502039340850404761483766499284652652562152819559857861694199912268847767079370271963017789175042405109497448394144352599223266537496498529081996768523164400886001039639502239270503085313697920362489302541460097845510105670188143441037239191196538917375288643759280639565664140346640156865269886406032608942211902935373341430157615120803627282239923233008962017066237396532524606700888351765513039741158162568908150748962145872588049663120005138534629666395813929330596932624049770405302994725228046193953266558277960942462450049488084550504032513239147982560524110769019811527420536114603387839307642231663542879236799384000353252639622526620711350539950925368688022474080334865449341117447983380665490805954364655859683279345202377858243615623901846723501123352753302362791279220366195208280466448638528675535450615572314879097373609284667468895170578505718657203053642886533806201753930235310445743139363228081832786241328739194626215458734716312832340571924459017204816801055141908166086556428268576888425088779620222107422296112765531693707818100112992040927235960468494324880158562371812059564800048752699248968144572585273489360420221435315990329188130295791404151229544087685469692590947479342469315845600866207282989779630467915519728044694712710031253894686746983256662870379908994791988270007118937468602714950763111830295453084106889013296657028300191666225509467368156463694395575406136662607869705426670830800322410926221215669392113084750839667853335058719233233112775489791453325566902743952544098878603140236049627582027141161479288804477027522673315906572799185531839906268298149525907777740599186113407851544626828532329408440153801334741150216718843976020418960101023450608032047058678069682421972425096994631998775719721573238342568344699277804245291557138025748021627102392040970156264007398482016594794237162332668432393672260117790966528852496604831677243608558497501522904131974242334852192957797651951570088359552985397836603749763045501764658397592816921400996758960850988436749083090399150689613900039147514204463509779262724961794010796101244171518809540746479382507397418401883341098954963842951237299172208241683223063187906675875725188494104829070456444786636457862105580369823950199219658038829929807005934547997748269921337048617168527433644115222395076110410252217506858840358751893801847335816380530706159946830941119832303797449042791034918112719643773090498922812834804255645198539552849756067910238412992841160679136179682663256911213541490792912979846147816916204477298024753085126849898628549707552725815946088134519788497055964477483693386264726890047304853812011518596664191721175008955479654235135630172210927571813128260585625408673643894974084790490725805497309354065636642070930846904360760717850627060236796774541861526840809146284635083648640260424343302647726905449716621597309062100419463611789812351332021543811100851757038218083487754266171384104610396766106819285772239706840668104696923370220123145381658095548609702486550140751849048622053360955797637912312577544465445231822445578533516464435677360547176997471848322959161676938095028485380217009841086753769782689313549792049568988742118353626752599781553390460706334469693376460013317956550434428864243330506950002260242694559075779712448328240332519748729082105860118501633745793864598537874737550230085477907474985767212346764188212530415617426567223484567635485771437555196881592337820283580681323459442131339714685241800633370922123464826379875393167951508598789859144847174908846414547743928482676040086679325079289522696041376214939404531808705296112700206424432633927423372698048750118832230886887613459762424547749521002968881408542050492904069669628988012010495210292495062939728544422707674286756125620533765371803145479407262010168799527361796261600849552129387247633706066491082355925827480945423349485288941392402912597102631232146396893041262398428356634574934002601413507210968352973897513852278081930038800224240677089290207982068076265769891156743566752757227150127154909124005969679514236074931772190372849604428245643925092056965826801587116903872505079744859477743834614486004177232021398654619904486843542437745168928040575313678627011784882184994773325152904048400963687097483848097637324148656292870677863599745518393144472607218241455892805491500110796147324171637569871158554215249405231311257756701756946523151833497919164181622535040239131384347392698041344496022354381726464773665345987949005644928496832074443451952148853174901639237386538569080400987211833165170464077517746756533703059465652189697467342737160437941143182014434671662713231595241653396061152386690694984261649805973979950349545242827232711934524562725639321247927941315356953783171056277753307686600989557790029546598794539723799415786123375594084914428587406067854225998951363117485844643065478616464936174365533847563717168736180031523103426632406797160578707794947653804926805538003977265553278907468443264709137177939134301597636900905979201209154246568055832820800208443579721260486175131932906055807075317765193146467118244705958583987228577575636397906765342454220541861568332470813851200895453799368714543831466991393489901267872842231446512165034645944415529843012778047897529888452646678964573651376107494397715208332273683694274903297232167298122113704232094972907120467351460949890970493460089003108103628571793394092201419319299469181924546664629566896793703910403358121238447559102537673595681648432744347326713809027676882142818806244173049961196540481575400771215771071278511253569459389128983816851147709572976895155834750167294526187695665698226047977125336239331465213138685494918483395758825479320560708751060639799122360309493934614064067835542440852527151552430231910430650378720781221767990449711687011326420255712037811024249870875741373085191945601842125964741998811083918451051712337774771379769095299893333420695414139408232962038763863763151181450685609720132077739533993659875358655484565002901010438312345842540836256072709405969244856991727249425619073563635688624490207689587265326996424907501945460491747496707280754633711738317016404886281919673410673375369885962335911788720009308744688267468837714960106961709885137179925282655301097029700141164759176331118854732527902009384625717823396727062795964273526019658370272346013741031353169445390461862409281583109460508970149342578550320181260561141594438413838806478577542769680572322857367014480656008533477421755699454279195030157301609014841674409295646475593876200672386080638373277884216859145508005738921341026646885997484346720570188101082450798717345604679890854717596799988648905605763027191511720722423881541321023074632849517902218757955535705956461762237782040506191079985308201978559172337580099926845898224245377697151881828854475672687360334446971836809717575067520187530870961369925696306691931339670505324553681826914265195845741466607716972632734588651912004085760523539685303464317137966725219662536509839858175919666370073604774259479077620375319526117882853270570970271087301545390216724110089530656339394017161991385188971142414145210115060569603176645549793122855750566466657919234224171721108804773437660246501743505402400622530500805947356918288317202538296969465038564187736955067415977562000506919221191159086133564322019362316804259598551292181210166630564244115569843298893723533992163163999988221194358794090305032860487332244705594476880291767096518436409087554954113718571761872902038789179312978753456057712505586575671524740383394204981575584147875219868995556606937215243701602999264996527749135217019253884072559261670545104664277055585802666229999301158729832377326418955925293779655764822312397324760010953824353329612387735614265944669048355412213910949775537557886184137488105124787025016710896494886158666454395270021774576238309719814075436883748048839249878034885637283529585970816267023366515149586912258036447642541125713442889819653414281271341584665589646833901013266888535901531068357984075080013536421998462427699981366013004892513222117622252716632398685575694531203770299078046113248849592028099733069139004630719092909121559178698752943843172154683062375189195563234382416976808909458531571663581940269034265017913515737248819153263313195119280360951830693632384456775068412531797874057229616372543206015643230972913782525983346325707249905368213427086361366668370786295598429256981187663091519149588236888039076877747797648049914572978720514345835551766768529274403461042543049534617831620885047400966124161449148221623285236124693271381342922466151826792236271446501691108509548823279628971357253566922046742797103327039790554778411799889397650223680048608702211378128435266094388441668432866549634318025128396281632510862837689543234739114395915105135232474401847490536608790917703118207473914972350829159672359461447035495313324548973684000107683285055415168412769938694013146584521022720680315721140225495279874114747425129619300707933109921228956051860779811753595833238892911737294772102884516061538805880735436240710958706541189526504469387912226830560317799952551122238797100676343175945282499194917072186406921960672897609026756853504228432974547950389545244977436783007003871730538957977165405537366015406596628901351963398415691201247322963487427351872794441007041744643974596560608120348834281923472986620937808366831011754231094578612824401648353143200386142798430483759879881847875846830103644988564845227678388578155237906642699373456737192566315689797854809534481805289728441891139551853492862420390652172494522601900775532606170321613328442027016225074293322378608994489146108582241741523337837395928410279512396914369749100020543599966125710443512223972257797642545269209223310687685257703331504232494959918343444358414823805296250741744836849217769981771362180167047595424259542044975142638463979090161635554996893444222933979504395686842188416594775981916379528009148419160014066520772155135777251500336957367409945592608080803103579919540497395780314373698490698961772062162925481565978471073318237947952795369773335571469867937551739321093809526469241309443006815565030020129541799535072909240641399876422077087521312300831793418182688939719900840510105052306170921295582136966285360046891988020516401487927330084624147658871055286334360959054031035481972966206991821000887482005967709002059930836297412377779528857739955182236052021219760848695725311824333554641112388975550671607919557130265046010403780829365018364073713218985209991999591511730244841983565216434263805705613404314209089199475761298348934913956370314168532392538592513600212738872160960276845272149550851801161322541998854785195139715908399948456241348971031699594996022274369035050885494567107605876696135210134167187706876913876608573568182159836873354523546632877615107574866472614360857329490354964766129614489827748051046015071347722412788740207806214365949157606856693341153304104994527435647262370252048912260772086054992375152308389440636726090547565363305350853113075221080935603651632037793455647473164764774673302447093385756916233405806971060770537425623030702743750729780502287977054349090905698785859094533527820007197021090978674875196962138563239287984521539187615071167235462477771193206654053948342190690277002023580779394125382288286350606015155566250316438703711410841350455861805929664574406457846381738236276648724571052525823222482988054169303881821114435639285648653944676121912147674892055920953451390282079592380367403591693064273943202161810404559359677313447979185546188811066468937182242055825077141428834555216266431742243351905791233278547712305460605256544437896729374778408081406659105099716667728985705947733000858376265361091161342348699559135270785815567202464192572420391277906653872114426635358725249712673066826607501839811984343234303300649241007521052622771310782179557571013903456083622217558593431414193399361583608346165010286390118190746059955569111173747929476560790129641649115345642087170286327736500277295489288050463107968061191653279181104737567801436627545246547412290094395539171597918882796322921522227921961707898399894856061121105840276195301249496291733461566645235549333252844621725770554977544088674651387178700631650442186541530635520832420053627100307708623024454706580219419808026076576715291599878514204050207972419224437221424237293917577783128112379870407048315491797232655807905055040179019207433335031234448210542653054993219115894073226281368726344186954444029025175038488464511710782103279336490741021750980541754540605960012465433993988947442446189947357023968622055248765985631519420397198700208277482185082752390693981898410240411495080071339904053228199523983942010406649951655229273550894962221357148689624475748623730771136867391252122025742111810570436301337993497590137197432346689643453226209660370401445614516599169704303639613811350097431805238215087489805988833487286632863032459266571605713382069112193996309467822750068168339246409312006062869409702741605478293780328622553383868876239587476713057159867360263366169621108059687824813821840205632188654779596664468461884322967191227787593122343510014479180054685941211197815860853507385711788210552238867075014437004530273486285213661370987858803430458197468504056662449446684888929190801867176828612354816639338859842055472123041672497474066627272779198218824550641628449112272093178291767675556292680483290115858226253600578888028622607825665624719710693836928406879024072515226482283023165515074205839730181963443747711000670056468565314213239787183479537927726766966658221389263539463706507071596287724317029236558887869710898662661371022931667144944199087516587715110268310789348056376691467009033392645253609672807413163075892536243511243815775730468908886636891936104849985562311470758023204354998028206284218675018046442757724015117517000069126284909392388747595849879987597649735160227417207221644220914385816104713854027362799107520813284766414910303388052662447714692285827940555540312574538373163370739844231510823389178221196294886442402713642712139847010888061309349433277932902436458401335291410861306396582129779914173043123302653967109924102076161414958131011298135016460248959475381824202478628520583835028769101618674257816917464736081248543107011673597322098483095736730059056909996317142173566381855519251765380942666217731168361230878993398656067359612884631047869683895421453480798723364854677618193759840218785641886742315020855071550613065158555659721733392177268201824997419062438014063003092670724847139236002115122015605154460212882874944161731374417344420850161891821410285353856311141083618237705773911485998332082621984985216684613014878417136398175509800106152961690678205272113869378325337576118369698903227994695279178413235293519861736373710187267089443385386153615141808946241935218031094922963591196933524846140960360512411337219303643730570832745495101343384316259162903736197601646461920588486171918560251386333777773451792371248073018733435197760798837095274785624410293123230648126691496261921137346965304464062567518444341040691866367895620425948082176152408385254920593991326388332723074727739182367045267401419798020344721887319796617375029339400941366703213339056413181193596462627470279453249893564189062187259402073215787106733423156436813233654659243296528282179668531821385370230472558047681916922482857924593950459113100142496157822491647415511409688005039069022476460040433277372386033484165318497428018077858278831825617072271708258857577071918928186322811714275002823201628506621722573426612010713908130569091354409583136869271508927139577190229716369045316471473919595767444450981848856104832082965358964779307311965977221112770249100866687269631143351721377053315947816464615202063323373279517310464667813165882575222085713732956186944465109506402444039797782727354918969481752307598079878544400785438754002548635243857390420465852749591182126491197871165037646347795649812092510271151241281864836365029486536967988581388261756067634133617346441708787757657642584247130457639605742919564559331174256616590923455821722958875071081793958589178730041698144101042202604555114105978596082221913452075109048353806057263916729643388193117599343217923543981804719861194875325086018028244127004521376286311633087527178474355367176944414868086331087969851765874698241845580792876768431318423770039812554762338348713681587105535839036890206433413035553336919353664618127589574147165133089677595232700141293250732864897528910718347236262910975569978896051092073960198775812650184249921982975859949695988062841198404877095589796681356968236121442928168197387316899590634382431212671048682406292304995750804779535482978069482560277663323744521693547257242440006240133731174862984222677243315425681440706131402069581106260114682753069959246614627056081962083525667000171951816284213520277097209297855764273724448570293623305651614707679159088569587132976698099945138856322484168819980074823618672628646627916467575429690938278651177655873709924595525006433989729706059489312071098664689581217112567211569466038555619564669900008370472070260998451093257786588432675998076233900167621724366269512558174128375869440138306459764673835203069031368825106579802448302400809211165090522093953628003225227193687889834472085838562640903002848314870483373966104649834922354239800243739105975850483344504199696267477516830272343728864805035982129159996238921763485912082202794819662031045246371988557108594142263510522185349445051623797619122918677513154352787814480747708766937971805686080698863516426591477388843002485767948582635276644252366193988012633810213953138826309260669551380056091295600982995329399312065011507354010552614188197347147110402224380580033866637804924320595068264335425115183872601872654524345957944528310753469727700048603517645704631850565733550015686959264219039747172744491478542112308502151138953933826016520316606192844576466252983407442513260606192427750305338869563202376016083522237812594747072325770200619758624682384743752574228872193110094038350385987830867663606254452955541777101156360620637686532538105177647644384850953615338206035347467242866346953482855810186872437206066718344657320977056038038485779248655706128311672952749261933561754306807868587405112458612324351588992191981724503718944755355860592394070184795055898991635176409594185674819117315761187374481399760231707583088177334265838233763934276461499863600018508097424852678583109221019562368413374965102820156920606872354402068076706991939250316971791373217170668904937256090941988641219757442447456934452874349734391128514009770896413431195428455985910084952942982496513200810920266137123900305968243808117529384825105522082612634212957459412254678633652532652159399234279611604942369534542391904466362396175662437064393736260381518045106554153119285816881718707640461000860213352134372030809794147701909193958660032670065888432249656133246150202839771528246115791033410494796416439881210672978151013240916052949283309120691454459149796117305069053356745609218010908556276119720697669384205839448535820942845749633525715537399556847569681335123535060015810748717121945776654031294868422418905964778034820609405420745600156961364756505803947819991720894697547402311184542726808788551623260358923407316570834941456345344758121433788037096069023046887732455116127376487799342566726978109770524301614215778480260331007329937559622036671630766018783526930267817368252110416921630475386049564329320963816673149229749452571667891524805196426178070272472678200909628416019433244086326176346271617568864864880888106207001834298695409549722996554279119917861967017284350332715279018101345118862283521244925941359220199265146430635050726919724815424607840433517816343504224997157583156470222224201770589440370870205483606564647889894587814952161437532717405330965138921975095946335147996264064230827991299323461455067876393515215094640705183157476505523161832937489445473232094972991691402735954971711536305578413875988064857977314747415714657817772875745503767454557185930553356832846491775910869175374940836549786040696414557710630489083465213870437302485819717502468855788995181116171952769010376009091348696881453406585909815389854866287030714825644009626434848220556526543293133427688313974615656941308511634873160583645034000030376877600778809763527485813278704068342755428597308778317899286097649656933188026909879944064027368654687316502442712618124425347310925682777410013956518208770819647864163027427538915908155902206574887226230816815714788286108720115090982131023780225772546867320698705237368761116905280019439747649081672574998464494981022961486066181396783649770849223622666167197970466625016982164477382528449865978252758006267839418528133115328104833919154060571031809159782481062641486521675295305075981038995146335046127229909849140650102075160373992688516224329315060614586790229989993050231181743539309609751597751379338300467940607384446263448557136299227684725722546648667083111929811779553187563224684211727925821803573293263671480694793570692614642955544130882061959765781734228865568126405095333914701220077686176030055637847378911371990531282719831727917960556399227466576005005362121470092731806697148854251129747895501709655109671209210554828552786145042693189838080564529205445872363845016613363650440325079840768868733215971361020025374977863800111756939077371925566807862015241219861941892792624506787508099824352945200494895031348695042432778498969510568089349080006674626129117179075929793744894770257821166490250258945886439839644024630755706262800379557764036826802762341655306369694046554435359660313379417593093728551957474429890152018793703127620908933578641014256137655570793306308723447464691611587175792651639066838314434207154948069943767383045350134170214123418644038027872170936678270664888166816312691045893280107304929332180624574577447131501422495586244329055367955178939501531975804829007749646695669986939625504743598146329270102062411709074633569072382236559751970773621542201345089093852275000684398439767524620304502339137655169210630689440008103628027337654860805331307167958247723704579326634569751433319739654083300676786183991866264177126585898573985210406498953400517793584480537100370554714464169744140232658961574028594000713483505818562461939123179016859917245051732817952897817598918835242707386997985771375672300860459181902420917323144995910621904845837585061821653332847328020725301920913613669319537053631241827317178770873934563059924601923108860921164245172149814999037610269093657167750522522663812173717675545705635729912480357517578507008402729874820701326872988728517035215842853202607660704158658448251673191572505222167601395459166102683493088344687239955158562006536426575300198432983721673947713828214720711344627303259817835715740430229410916970349141863101218288224368147431241994141106309671052863271572858936472707283057915584669563272064669124820969453838035346301164010068051795145436835040996579741181114875432374845387061708643338728758191150229831258467593672884517226868350272556343058571616769777525787816804372650046487949147317361097571327568828308678666628490735587948897092296809391728696868226376139465865852221726349024339118778348949004930894693374778546538799299206636306030225143255733143198178775262631063162212736412521976977567393322116601557712743862195942070228296999584444372798966970086043956526161139015915434005460218044112560857065193131636853781686472968759176816731365172740607664398004603840525033726791582205980421510907949004050541899775782431356630448187727219719145294287226137416365989344806638739687182318136164578919468955851029327944084480853752265265867300502979760981375160726430406079323206665417180563226181339196554876032821567487830113183593071793134535383848720138840693781496816996350650510933788334855436069251998633909038633491814858622029086770618765769620410417752190137735517313985029964352446488380547653213579602626407376089096427711581007324127660325101114325354459258368095638628190094668770743537658732082318608711501578216960584034228461197853986672426674513641481032470692851510894189960696633005828034661311366582449482221546237604551427418113762745267844665969113856124637979121611631989226968874905293901442030463913396826544516288879739594241265015561467961505117594219210483880231280842273381897036666742728711299154621001705889211743874618789845679774256431917529177101850295770555069208416728696757264628685142487599177378157527449275382209124411083051618507734248700089796580240543389858308554456217425970107964047650351224347836147926762288242570713755070168305156337499225490819142095562494361511918791558599937314088142941496245884153759634452975914900632043774752936435345460270019698896511546749279744909498899966271505894811516785749122683243693541794436127607419793459131965711868742317951288054853523297441650933580273678400977251275050693145247491993592765735051789118012277425496238720882357551389342526373025039688593906004191223197173878229743389360692517347217441745308060439602838253148193974495914251023860307032508397035803798193583031158478962048847643056649380886910502571906147767068687608242273938424582602508910027754786028151885872266783246342431642659435610901743644158467096402267322327956540820503838176496407349239272594131767738195662459627044212508463203381969517559502191874352898299473564936938720129704180512859157001587358345902926482765377542445143399183626990260258191839356051877570258015995155858011411755532598028075406196554218108892015423005459148266306780952446116067894134068604908307065269904254859967207146384201546984982805229087556301287502436969613694491844820509985027196543469359844838348844184360860497444677834052428175646544011884656649391079166541690564221955820882901376982079874247193302968299418242816848212938190496694541129754741074247904698042692263608047387620025106959263309916822293854993074854141355787712531851047751505454863861973579259025118427412155908287402389456991127457916186435987718806408278648054783187391432244836886274351257932975708110167175965160100854354412868196283693316213604145053512626243156331474119791397577044444249241624043670543993583734334595918100946339348806634440979985951983731929465319910128323169649572249464245143577759204773916079565707811499853402409832149587371060403645316050607735818236311883804704228005871272058545607684284891415879519453787586596669566881784127334113016968016681842540476008805436974150749657172760590063567081190500559410878004685651233376870929099265654160414273949155102984084283244744475369985152056208659189526191820603506473570267837683408768318172042208238171894644142912890532684931573080292320917293811801080431804000143620860796937555711157088696635939666199611606738590398289079012148525654980380531977388285368410608978982452706749150976045221371653286017484275042357774105307206867316434884125467479279469194045751013999961727815922804126878274755195646334148895995462488340394750806827862050420514270264627235916402340423951117229586360940677091876629389669423612271448820943333700690416266524675686576300210048758362861479171799942849467747296978623398538946601700499095993090914140782716500117850511711471943784703745528980365931265190884675606857586775094386954655399458107840373863670817372737749985674003898637953963706693744449424311695570508670915916925878931007905029581928256669883106225273033346291695797908422211035033275527925403521434395507449402238829427192623339073501302271684896648423723314679986750180037750447016526566339862499072030594456737728197253849075029547702747010141004619148181376715460263786569165796730691181127636804829487433142680171008071825466588131255015389209584980596823750927625590436343490852662717736803847528385075141013264304556018737235440272595029472647370682042405794173368043777690124546366874502550021599521174186744186799369641600926768860917864033188451072366338220169715699536731478067629812073410514891989387345752372814207309191165030344372719058938543404913045692761022615062922747498161505349727044516748264185915551989993290909321032107278149461680006178170640145171982228311348108979764389080777704104895921599128489989784691305896872270336949230081750725521607641664237558670621032449396905282635726120381061246426909407814685520680793115154669661179621403691858942260741699944207157035159956892274403122563968174315649945055876540017292643723664346945663576141535189886046548482633431570091091675188707053100227675882203601689412975825707722239640378522475082749113935607418865426792429545148709116658712752584517063519241122486975103992175094736010763670254175466688650683846359875596667022988959681346232896625718543341351572580138076632124236913162734759096354905966533189862291645112423696065213270891582653918488210395140358643182475605290595798284165345703307392678824803104759358586027640721779310251915557987505582677963803132348156918355644508887633661455693944118908242381588621020217192287056019299228294838928140790314263308333604147947634742752149402690744091017076835744173611627892383764652560807333218056830852943759692665980457927496445836793796251902865824555896388226637505399922337849667468044860974557533975205099891057365432876941494920900007658172414182649848607517227961090268467672322047401617588058244574301371160846054158980096261128042657135994698299870123132877062553943984565135211928723914652834408261849019310878566843209068003994992480801462081699873450609031297494415095468861383803532258203295389422383926325333754027165295700502340262470917133464945882424717858730756912585324206091630048543803626728803757921438560713229131807181834169765972220617805145309993211478702731700600425547911155868700975708809748992825848051292052710641376002288947914092191885231137456226719171408796535255672189085095576425648245704511157268160262596495614046976054986445130945485496255103824594047129766851010753537109960027786251082926337429479541628355380455045151341115286470518854814666278954773440759505441294643237768637105014143172557119828945839056878797633283270767249669637780594930250762152698723764616087455173117114423996316782809141259577586712121460315566091159866859293532242709346397509771270020295085262234934220360176412503610519863672207899433280782803939099904226014615813220587036456194781111598259964267273355376142973755754632092251292428759991473300207426716889552875680841535356952547199156036807054292959239767539486857337152655068337598178355353054796790141073232677278056733083080750347611087617639279167307356524481330688598820854725209596949798663148391353677347811275281536999006000820826365839919464579431594259604038936353789011722445899610947794414495126008227925526799235106627305554341925187265682821955325482889722376908731646175333172709203640427345099490289615647543248200145950434932142472584949403775190774294082203291175650403006224090664611681714534970352244388413549651951043386935307293964588800085663209088283832055729975832715792041435597902153558524233348089262074960382196162073126355216192164745580819272350579780366534637334122768096787316946547464662270715713604995058983135891764383238794974069315114745404049210442427687502330334846736342180473723082770181764909606380486341901736287235491552259768951557668672489433244508665764530693888244944241122828059651860217996510391477529945436903895869835224287472043140447068928919993838923476082968013580839451302424407445067412839243509151422563741836681371904536259927849402803031452438195942332734897009258118452130833740864904075667380985035422098213914622652425353946890944296584744803093022109700194051085371092351568449925131533714630239600514752933768419878369948363178453161551759984880433429070614323704702428533245151748615484003022980899160914471989222663137231897440897874910894749804441499668748490099819349603185825542967330452053003732492152478348017346037046537559373692595508946902959052302288914331538906615997071326577082795962707018026028936734896057600984063482929051482325715907021410860403276189760477676782847148763827905261879680280223693654419735684379814882077209817727982898608287765102439911109767221591937899404452231804681062227322397985238024296805925565545520874815344308667480844587099840439233648682477405709043111848569866651663299856855215182062959770386830013125337002560158695515945046825736142698773624741569519789492025404935806163144036880125674850311510921729209328880923463132904641077151789877550369719767919940642470891791248127873000772882066171288744661594325149979951914185197501762403128152473133966413076247164165891681757462730074512426288316145975745516853908149952256838754784540182697501200926798089149764030994844256427200029055377803498114067382262509067969397631852579568483044191266435987125086556340485619852803217971115346707559089359922427654131693686414834160871867220934249067126999068821304324602638495124789210095040690455088599823050474312069735889408038274174744926284157134529763887656526632572644927873043276693399640475584741182228258258988520444766318907425495525855840944081702653079727921500608567649112158490895265337608293159549769984099627237465294815362347097917083757030480257291258061722760683258668497972602434025871065305739800993425461796994044047512112650220714173008090782539973056909833749475722558384326194689304461200949459831412140713119998233926773305822264217989377187032303235419358825562195850937858693502809043684528851491014395729030407348888616534553321036086748207310618591269895127463156006239020676422366121805153144935992418777968458334183884371431351072078074480020514502007903026866638850608539478394386616268076309309609173895282066441738441244969144361088572878981492491284166387945990859145144418387686940050100625094755705336829838033227023413053968906616737081814806197645334377038296351053202830082348934230336407209261952195899691911483679879048964251226407926050760034207832416872253370617087149304227330812410958312381421438734437359960248591344869662200338816458382013850659838109442015203497340029286437064512916300505212248378946325474548328583616324442851917708947416715377544183131320081964638436902945596017007299593823644812636848220614938891611758546961914919562628458265621491048853680111554012551526983238568730104224237745180999702639266357669505685434867134289242031315684450998106011643916652489698417649955663148284527318463972864130885289696501068337437653371840848478783850431136415740950515934732346094991757931627069317823458496998306077208017089830117698643104804046007831808323012822627739560391021589030178097412712289023080747465807256060754702892748646426856749247701650734514819423484261614726203488861454637606326426049823145550874568293898228616929242244760268529565667644611888262076623937441188326310311167641387753060981654204357263412624412519180923169842819619461622246935406160799768438678162527796931047375425941028413182155669171830165188666897769165563056055266805394876644439081419005448722501427784000586608929354917020301362671587690357683349739130437132448959461427802297930505169956310819999741081083605522675635483100819767943622306154083072390185167010142979681617421037556895578829256394910308115380617883461601834631922724345194867508880987885894499091039199664494409218201495973078282035699075024758714805088097792414880231405828145637581979297676959828835916128780354699091300940239003018489475673475984758027353665698792344991169219102528354884774387265554125299114021095710352601978732123966580603557843071506767849282395530626649733866556018868215629790519234301262161852255993950423075346109800297236105161559684176194547860759770863878513037506197521660407654443602834720981271981318000078739649709875462888209530669682376348058757652142298782407041295020723790537476288418080926481608290434666460541699664134496187561430507219119114179419318922570824493885241348254605468079295784507078754332590973314643913291256956852445802062279497191146762480873298686887727253948704467112529977521176717527226934058486402268004915959284505231391097411315006499922368697666862274042596726926552922966664176157068970137569500352669134363258697396008827729696526760997633743940446172664373567794187959595311427851964770279045582369201494335640305873505296341425119968238845370442174084840580165976875492314868421082561941892833620704259875298152788439626585512448267405932203690860584575228997414673371141516702537207735558926720239415024709288872609072418007382711921344434991550442370816311296392133910349853159056985681259556594412894795863008000819423743104603630611895290034369560452359395243167331920005097438066242972003668754753495223021357529734504188812959444376093630665408274420907910658368218503618851964011592573280509046624121927721150227711766908385186692551939629804254157992888000756174831518230646351290166766808215864931018264877824144559072379878391024488280585635516761998425252806793695799019799019965002943271163017609872103279933290970692547121822318925142380111201239212096988446996109255057539558256995299791564594780271182649112990633938584524268094961287383320240780236312212864517254441867807456243922273863285038172556974655996660848020741689046135142103328463874291054514767248788126112193701196403221406731617756153662729463284404610121168287721576026307216866550727011037134284997374312531174761945421207946482334675629872100249839837208503917563115861654485693838486209921784350330464851033315061366878892709532951272687786874116100533481605779369131861189296666500134654771140318534195764531672027297015254144416868337777165717357086756071864371264457694532326991640896517298771650045182129349908395931682418359070142768591218025874026812675063115356856268184744508072071854403673466588962758850847246872703301259992384157238972463442819554816626868191226109994350393081341681530365728910892175380171955658816105377636783170434950105124891067861307571819022675600102444053646424596814526409129587765000433402326901491623780736241289323112227938859506101479550906487264091431230131768683594948122283115147818034767320231196461591737848119916146639051776525378432347973291307440996424796008314458076240773397275386080183721623232272757838153337133207196190437607565930056699177581414940706468338491787725427654617937869469563411104281615068734350853454820990693786022019742929887865695527896444613174867234742174636209489726323218917114663988454312562021484768364608396968086925724724211273632567400486056656094000745004996217479398346865570721262737618463202117838292703954020049141339978680267211704125544308314591757537745486168988899891887366048523957732676663167644285358775626992212575901883019782205275001338687911616800080060587495476120854685046107913973978385034112052230217947945090023994576953203175907021638186203311464987755619957341146967238428382540468726112652846477191999322717747456517783518611211582058762242222203563080373507655950125905280671663987496691350625349777957571516831242618202795346509572542504658193189602272014070978395264386212614586959939839452321010288253148042530874512182581710756876292559493898636183203693008824632528514730354874772260224262685477457914147155598313922949612281463275825810222694927813601483012873190235032876431947041507694753135682718584803062573653068802672637080919025752720866191960061898110296398542872599818624819931506512426608620275507683405726046356455641779881908979313227995662278614297091288852424300678363402149982192575675229693157176977220947510256626950690972154208890062135749124749063457716245788872226643498301892481339562747765404138006249899757405453325604026971867325756002347610663488602148041268613017535801988086455247164870587943648650996363892650310972655693947889136878927024254183204117623286185068171679110368609733440501130202454614480921710224571571000147931118758215754999126186325983498807943415264685766950518259872464330801350983008382145604544861737876456870115806595098935920405082473980433187174199148526620080233989763811742096361732296201992133998844994094995879225361373889062533810195267444072236098545080054508354187104199286751295528258850900281449222331659062672300585333239438370527723938251567683124464896361356492651412688120846574294386430441892520600144139996992448730728598239008270559786913781446887807404143194014342674219445744831654344499243456376034078411420276480547212576708181216267678313509212146909940911304980194411210980015409193821111797774222928579131523669550141337405115935461917699184402574213685184515488840994881182346008342945496935817062396031226734344666418684681744442177610916418982133211623823487302672724616089407737370662231810436738387870739639540888707274708893824459342267981171447876032949924057913462307791090226158263255402228988610673355693130675042120276865305341087592518533569093754039330458184898015412910174828755603149959241283703310471348512422836941791495403941240005135160291660739563508382687324333610762297326966652878941864503910219460056145486808961319274015878102333214286536225019694012621306065423612123334273239281680881117589232959694792393676474407968495921583839497268958131260900728549436329396350406058798928335658146092677818958981916364544597445189246313807902600310998071574087078458441159533157756442774615959241725493298754413416869498897594576642936201627653101931429043225938458474688947153475663313045641864596335167214918338266102153407574387076737083533147135168640147417242587796256575313077775674306463248778301475094661820163771541321768840861816416176212398281238683673084771318681542068715703215501664631647118535296147631950812837990137892620171254247778702913688137056377682621169803283711673228284418572362249581345646127340437421947298791178769937889772361824685560611007955874355525705909950578650272199643603390442762572815415557143226886980118428516818089588877725261599909647513556627624819382976017911623299292112950077750255711988537690877979917966369156595996584835391919316660124045855281028028860163365242075891716984310459926200432472592225980779356831269383515302962541861507994085481074648867932286638645260312125414480349379965378209573549532837187395609135300023521574895735610429554561204285672339069190447983048604636275996886152684990261284000893350073520822332221971539348822547739018685517633942245626688840967426447124489504129830003287768641764720207980373889954018105537087522120414435581470390165975287356886494624243443167041900107261505952254181170872066662283065946537848788180375805541541911802125713609727203555990135545693690438601908219136418445869687275704041415737372813335646625659667050157128932061298289031715712852390018208936926849828886482877608038208096265229064054980402079604393186822597891682977162336413856311045344271643669955031006440874553359565400388322794477069431924272181749697114212078337327370127756316048354566494821609510662491900593090101896026066020849595606901912927345956616507966026206557825889574812806362792835718803736707434033381680927861031027320551394975814682728145486932514700576512564340033677170553561930302924113532696205364504953010615008171246518237980126365878234621474900563277304291877285827372541558520171247949766069170956895047842098052146583583056667946411579436013249127982736025459177074788396761805590696003989864249589969022378465400908220512758563784962087014220374273987398276778021042619900329342011600480641441989748194227513458150776827661135812272952970109118272066862733930147328166748755098460452467682438270169654112405541561908860889872218818460384582105913600758216358859199503089380403040666056358411173916521642246980751652948477264335665945258162327136041038938467614747469870567133908371742758173838118003625959723924867103145577146776871186481812104622871568458018240130509938585128032276678571458612245053090451800408014670142829902976865139646643470246509398018898720635633890612653589750649391701371101463553170190619835662570030638119491418764949954183803880369764116338318433850484603430418386177228601426102461874666863927817687324119241539482900524351245218647775136894178598186710494129499026530475869885425467636883363775475285220665733318650083362070237114432557549967721764892176719979226329103420132889483646816090467575011984755791009972600077339360459355779453601562292086711439031445444013716192759254327591874580505531891774386090078205011018434863508251201816622129076068139801133607452320531604501496139631426725881283941389547226227334006539461677233186085074785733593790849597663226202145262522791442092077750458561819468069569956390343118397431376467772187168648195347322594655531376209749138879722656195309734547358865262437604884393682523525297681339230385034577592362285413844090291324004188441761308946598113155622594470101813896717827793848959466897581352096411465349497482536667678806755963003594269964471645756032079320277704458853069418529971942575852094104790310066847069670325402373020833841876608040386282714261061594335369930639258387475450755168768340794098892705854617614243440707489160798676951449013008341993381732131984227333099392676925782457904480246684111901862252629606700297054325514002833036878077927320486093138287205556063008293376772433391714142630719204798033902765988430555164772582267966219041116996440539611674000601957205887125099421470042532656876785243560501045136171320218415143037548196562948415694940370010976819108894029684652176921453433190337467467439543014735696442815741548747702293908336908985277965476394250069229149180150682997008263874224970008677192011419847537688924343215111577053147822731803738472808685565730387296072637475856439347581597856449683577027257576415569686496716232166624488382627415690912163227932292317464331287402981216293429621218940245902331369206273758387594129522029813705571334915488514574423717032381934766275456215930679664254635000985990088857302736127787308242824260325470176425887795269807370383222625206712586758031401651612445507809930006945003100158708722576506337449252473023364306115312347771983684758483905499993546165300115824998346470933349306355992111511854360424339719752241094774221470024725008754260639339123535935395369604834231422742026526593608645437773732737340639414276366719135140139619264386085915702676818624745313860140935190183792177611068021569164499918574037150376482954594180535425247884719895545197806754060579022905823177907142912487939450490835317177502750318235743892921322738828536361107159384762191716829657741664961945528957725126050184313153569688248698712439231614999620828858947533263577771674833085946996572712193762889513560348639053641170588896653043908598903555365149561211191470230120731319008354242244302286812736403476357021604922802357384689171568314660315221930302536848081930622543291880613573247100469750473998324933106345714410176138736434547857673738984895674926675722726635872377765727031319309249702985669047074463586960806921003800374225019759282334308009367792331912865955086108861120741379037842912165510997478992006052676867774966799496752583581866257935485610692844574854628449194090808829084742021357462913639856068465787990532673010600205468426509964560553554935157586604132565199856157848210918982178980095756934507324717987022565055393387357632719824784593459764392772029174788244871203394912193045917777516833911695517756040814887416374656407835901621235075533435508686899159645856809023026620178447065983821919778128506207425520891952097070004849135013350297579692482273725032845494503105379989250316263400521395561956989656768507496725540542294995431881558926029531518968265087462417000823697746746776548232226800794800142751776501957376491014276981143934918369329932427888214868153578683648580785013860429323993824849223337605028255415063337065465216386571127301713738908601696807697895191386352130203238147150771101431768924282377768128234363953161212267726752248256619632318099994653730109821052864397198271841210345494903348900088625423276385831640814794822769926307235167930155467349891850521835125234414389422765750919904715878343527302768510636638650820425644388411572694009266853453546326636608262484968826961152888397079218381669647347437831598385028448986282822095841237959151680179414410531988958175111441916576314185007692323688002201487709687475218817315597583827349920185235890237646848875494010553416276352446323043360739529672222463604902641640778195698333214453999124774875813151340968915370601331455884133177085449452700302781315085796423576630906837490998849854579645012417417410725851316361694206620948098145976261864818914009232990957229611688393507636568492448654625946960048700159184093046376905918764142044531267520130925428785866522524222978722360350767192661891413674114543647698884570929652984997282849866692335796445426431456323511904478115398437648145621578154569702869291418433549303996524770365521806475706038919985144625039583556744927239519719881835231158970990928483074709113874828246793476868108725594313317866049379027518901105674744308567457083663203347523172401128073181551488238725236801591882207149390324975870354434475332533662150939244173226570770173467522557507190799848307594920175542038283288444097433304461901110683201102993266310889996878376451806143286661186989850922706531831219078871711488889436868901265444667763988782049150553926121305319777519528394987552990557198745658798896900176073513421115742229192485881880179410848271335587896532237685230467415081995450847304156262431282933134350441251001706307425823381687992828157611631217896188076308844428001218167474176295556385549631396590011591473348763241889869892519096275493973888500054279729367865760464710068697950339475397947976840987761144502463515670270449977105611334814516897014195566914505280486207388614874723906637808757256368027260928007962815476464271473201037546013670305371261420383979040881148983345289061533428107074749517324444888002725043537365442850393344401208730640814680650866001537375596885221586199601783136922857778666921449959525695968461700332814459217639360788498649848737801932534546760215770329120195070894817871266521847966599043802104558455558240113360894224791422561980310640389060477588394722625925125085079203433991939851511015274999701241052760405442004790692863321020835492346789888222654285828384235023157385203832979147730883227995198569086603327459196157150314868790874777563159832073479359819522113727604088122030492037664552314741599241392921687409562894990700601616401132151251627178280253297489928770932001714074161280774406349568829844155943099107835943925577362856982853585146926620644490114393381747180930068704643386289520003035224241592391931577561317503463974381387219145581941150075349739235445554989940756661596399324487402013716696284558958661746820865646755271781530030808173448727992057828893221802639627075430457992845294070536506800345606169755876601314634718722851054910242690662854231071258698020590273949972893094541692473118795578563209406719473770590210999950300771195604214561489009297994857358614229879695713401394152710274054683001113715957454311087562975402229317090908460094792184473317675037036366520999885667665334432897260976806985270392762765409842137267919929143522360061257649617508871196263155746846698493858718722112841312151696467164932107464418431526342839198321055733306995942238296375689219988441960825708272089931288526813797505009544779764605724814125441502100533504374308917078778328920080190088864969410895004951509472500449319368987554376787970387215182844531575746483984818555323033889008114729691735047629941579013391399522639148573310180804430222787587638916434251463477055585153797748572837293435406307929568135850557509135552751277039569344908232487298850

Hey mais alors ...

In [44]:
class Valeur:
    def __init__(self,v):
        self.v=v
        self.__name__=type(v).__name__
    @property
    def double(self):
        return self.v*2
    
    def type(self):
        return self.__name__
    
    @classmethod
    def classe(self): # self désigne ici la classe !
        return self.__name__
    
    @staticmethod
    def statique():
        return 'statique'
        
v=Valeur('A')
print(v.classe(), v.type(), v.v, ", double =",v.double, v.statique())
Valeur str A , double = AA statique

... Oui ! certains décorateurs sont prédéfinis et étendent le langage !

il n'y a pas (encore ?) de librairie standard de décorateurs, mais il y en a pas mal ici

Guido van Rossum a par exemple proposé les "multimethodes" :

In [45]:
from fractions import Fraction

def f(a, b):
    if isinstance(a, int) and isinstance(b, int):
        return Fraction(a,b) 
    elif isinstance(a, float) and isinstance(b, float):
        return Fraction(a/b)
    elif isinstance(a, str) and isinstance(b, str):
        return "%s / %s"%(a,b)
    else:
        raise TypeError("unsupported argument types (%s, %s)" % (type(a), type(b)))
        
print(f(2,3))
print(f(math.e,math.pi))
print(f('a','b'))
print(f('a',2))
2/3
7793533013102485/9007199254740992
a / b
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-45-8e7ed8cd920d> in <module>()
     14 print(f(math.e,math.pi))
     15 print(f('a','b'))
---> 16 print(f('a',2))

<ipython-input-45-8e7ed8cd920d> in f(a, b)
      9         return "%s / %s"%(a,b)
     10     else:
---> 11         raise TypeError("unsupported argument types (%s, %s)" % (type(a), type(b)))
     12 
     13 print(f(2,3))

TypeError: unsupported argument types (<class 'str'>, <class 'int'>)
In [46]:
from Goulib.decorators import multimethod

@multimethod(int, int)
def foo(a, b):
    return Fraction(a,b) 

@multimethod(float, float)
def foo(a, b):
    return Fraction(a/b)

@multimethod(str, str)
def foo(a, b):
    return "%s / %s"%(a,b)

print(f(2,3))
print(f(math.e,math.pi))
print(f('a','b'))
print(f('a',2))
2/3
7793533013102485/9007199254740992
a / b
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-46-95b92003cab4> in <module>()
     16 print(f(math.e,math.pi))
     17 print(f('a','b'))
---> 18 print(f('a',2))

<ipython-input-45-8e7ed8cd920d> in f(a, b)
      9         return "%s / %s"%(a,b)
     10     else:
---> 11         raise TypeError("unsupported argument types (%s, %s)" % (type(a), type(b)))
     12 
     13 print(f(2,3))

TypeError: unsupported argument types (<class 'str'>, <class 'int'>)