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 :
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
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
import itertools
import functools
import operator
from Goulib import itertools2, decorators
Python utilise un typage:
a=256
print(a,type(a)) # a désigne un OBJET de type (classe...) int
256 <class 'int'>
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
langue_au_chat='! nohtyP ne sinifédérp stejbo sed tnos 652 à 5- ed sreitne sel'
''.join(reversed(langue_au_chat))
'les entiers de -5 à 256 sont des objets prédéfinis en Python !'
s="a = "+str(a) # le str est obligatoire : pas de conversion implicite
print(s,type(s))
a = 256 <class 'str'>
a=str(a) # a ne change pas de type, il désigne un nouvel objet (nuance...)
print(a,type(a))
256 <class 'str'>
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'>
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
# 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
LateX().version
1.1
Oui c'est TRES dangereux. Mais un principe de Python est
"We are all consenting adults here."
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.
for i in range(10):
print(fib(i), end=" ")
0 1 1 2 3 5 8 13 21 34
r=range(10)
print(r,type(r))
range(0, 10) <class 'range'>
[fib(i) for i in r] # construction de liste par "compréhension"
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
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'>
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 ...
88
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
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
e=enumerate(fibogen())
print(e, type(e), itertools2.isiterable(e))
<enumerate object at 0x0000015E3813A4C8> <class 'enumerate'> True
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
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'>
list(res)
INFO:root:fibogen démarre...
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
list(res) # mais attention ! un iterateur ne peut être "consommé" qu'une fois
[]
list(itertools.islice(fibogen(),10,20))
INFO:root:fibogen démarre...
[55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
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
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__
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
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']
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__']
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__']
fib.__doc__ # pratique pour écrire des générateurs de doc ...
'une très mauvaise implémentation de la suite de Fibonacci'
import inspect # https://docs.python.org/3/library/inspect.html
inspect.getsourcelines(fib)
(['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)
fib.__code__ # intéressant ... on y reviendra !
<code object fib at 0x0000015E38123ED0, file "<ipython-input-7-7db8c3a11112>", line 1>
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
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
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
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
@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
@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
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
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
[1, 8, 89, 987, 10946, 121393, 1346269, 14930352]
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
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
@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
[1, 8, 89, 987, 10946, 121393, 1346269, 14930352]
tfib(500)
INFO:root:tfib(500) took 0.003042 seconds
225591516161936330872512695036072072046011324913758190588638866418474627738686883405015987052796968498626
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
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
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" :
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'>)
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'>)