Skip to content

Instantly share code, notes, and snippets.

@goulu
Created June 23, 2018 08:53
Show Gist options
  • Save goulu/e0a39091eaed677aa9c9a75669750a11 to your computer and use it in GitHub Desktop.
Save goulu/e0a39091eaed677aa9c9a75669750a11 to your computer and use it in GitHub Desktop.
Finesses de python
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Les Finesses de Python\n",
"\n",
"## Microclub 1er juin 2018\n",
"\n",
"\n",
"\n",
"\n",
"## Philippe Guglielmetti\n",
"\n",
"\n",
"\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Encore Python ???\n",
"\n",
"> Il ne vaut pas la peine de connaître un langage qui ne modifie pas votre façon de penser la programmation.\n",
"> ([Alan Perlis](https://www.drgoulu.com/2008/01/21/perlisismes-les-dictons-informatiques-dalan-perlis/))\n",
"\n",
"* #4 au [TIOBE](https://www.tiobe.com/tiobe-index/) (nombre de développeurs)\n",
"* #2 au [Madnight] (https://madnight.github.io/githut/#/issues/2018/1) (activité sur GitHub)\n",
"* #1 au [PYPL](http://pypl.github.io/PYPL.html) PopularitY of Programming Language (nombre de tutoriels suivis)\n",
"\n",
"\n",
"\n",
">Python est un langage de programmation objet, multi-paradigme ([wikipedia](https://fr.wikipedia.org/wiki/Python_(langage)))\n",
"\n",
"= on peut programmer :\n",
"1. [comme une patate](http://entrian.com/goto/)\n",
"2. comme on en a l’habitude (classes, objets, ...)\n",
"3. comme on en a pas l’habitude\n",
"4. comme ~~un dieu~~ [Guido van Rossum](https://fr.wikipedia.org/wiki/Guido_van_Rossum)\n",
"\n",
"Notamment, Python intègre ou facilite certains [patron de conception](https://fr.wikipedia.org/wiki/Patron_de_conception)\n",
"\n",
"\"Gang of four\" (GOF) Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides \n",
"“Design Patterns - Catalogue de modèles de conceptions réutilisables” \n",
"Vuibert, 1999, 490 p \n",
"\n",
"----"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Au menu ce soir :\n",
"* [Objets et Types (Classes)¶](#objs)\n",
"* [Iterateurs](#iter)\n",
"* [Introspection](#intro)\n",
"* [Les Décorateurs](#deco)\n",
" * [La Memoïsation](#memo)\n",
" * [Timeout](#stop)\n",
"* [Intermède OEIS](#OEIS)\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"----\n",
"mais commençons par importer quelques [librairies standard](https://docs.python.org/3/library/) et [\"maison\"](https://github.com/goulu/Goulib) utilisées dans la suite"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import logging\n",
"logger = logging.getLogger()\n",
"logger.setLevel(logging.INFO)\n",
"import itertools\n",
"import functools\n",
"import operator\n",
"\n",
"from Goulib import itertools2, decorators"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a id=\"objs\"></a>\n",
"## Types et Objets (Classes) \n",
"\n",
"Python utilise un typage:\n",
"* FORT : chaque variable désigne un objet dont le type est connu\n",
"* DYNAMIQUE : mais une variable peut changer pour désigner un autre objet d'un autre type\n",
"* PAS vérifié à la compilation (à moins que...)\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"256 <class 'int'>\n"
]
}
],
"source": [
"a=256\n",
"print(a,type(a)) # a désigne un OBJET de type (classe...) int"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True True\n",
"True False\n"
]
}
],
"source": [
"print(255+1 == a, 255+1 is a) # == compare les valeurs, is compare les objets\n",
"print(a+1 == 257, a+1 is 257) # une idée de ce qui se passe ???"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'les entiers de -5 à 256 sont des objets prédéfinis en Python !'"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"langue_au_chat='! nohtyP ne sinifédérp stejbo sed tnos 652 à 5- ed sreitne sel'\n",
"''.join(reversed(langue_au_chat))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"a = 256 <class 'str'>\n"
]
}
],
"source": [
"s=\"a = \"+str(a) # le str est obligatoire : pas de conversion implicite\n",
"print(s,type(s))"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"256 <class 'str'>\n"
]
}
],
"source": [
"a=str(a) # a ne change pas de type, il désigne un nouvel objet (nuance...)\n",
"print(a,type(a))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<function fib at 0x0000015E3812AEA0> <class 'function'>\n"
]
}
],
"source": [
"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",
"\n",
"print(fib,type(fib)) # les fonctions sont des objets aussi"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\frac{{{2}{x}}+{1}}{2}$"
],
"text/plain": [
"'\\\\frac{{{2}{x}}+{1}}{2}'"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"class LateX (str): # on peut dériver une classe de n'importe quel type\n",
" \n",
" def __init__(self, s=''): # constructeur\n",
" self = str(s) # utilise la méthode d'assignation de la classe str\n",
" \n",
" def _repr_latex_(self): # affichage dans Jupyter Notebook\n",
" return r'$%s$'%self\n",
" \n",
" # une méthode est juste un champ de type fonction \n",
" # les \"magic methods\" permettent de redéfinir les opérateurs\n",
" __add__=lambda self,right:LateX('{%s}+{%s}'%(self, right)) \n",
" __sub__=lambda self,right:LateX('{%s}-{%s}'%(self, right)) \n",
" __mul__=lambda self,right:LateX('{%s}{%s}'%(self, right))\n",
" __div__=lambda self,right:LateX('\\\\frac{%s}{%s}'%(self, right)) \n",
" __truediv__= __div__ # nécessaire pour / au lieu de //\n",
" \n",
"(LateX(2)*'x'+1)/2"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"${\\pi}{{r}^{2}}$"
],
"text/plain": [
"'{\\\\pi}{{r}^{2}}'"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# on peut ajouter/modifier dynamiquement des méthodes à une classe\n",
"# puisque les méthodes sont aussi des objets !\n",
"\n",
"def puissance_en_latex(self,right): # self n'est pas un mot réservé\n",
" return LateX('{%s}^{%s}'%(self, right))\n",
" \n",
"LateX.__pow__=puissance_en_latex\n",
"LateX.version=1.1\n",
"\n",
"LateX('\\\\pi')*LateX('r')**2"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.1"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"LateX().version"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Oui c'est TRES dangereux. Mais un principe de Python est \n",
">\"We are all consenting adults here.\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"----\n",
"<a id=\"iter\"></a>\n",
"## Iterateurs, générateurs, et programmation fonctionnelle\n",
"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."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 1 1 2 3 5 8 13 21 34 "
]
}
],
"source": [
"for i in range(10):\n",
" print(fib(i), end=\" \")"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"range(0, 10) <class 'range'>\n"
]
}
],
"source": [
"r=range(10)\n",
"print(r,type(r))"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"[fib(i) for i in r] # construction de liste par \"compréhension\""
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<map object at 0x0000015E3813E6A0> <class 'map'>\n"
]
}
],
"source": [
"res=map(fib,r) # map applique une fonction à un itérable\n",
"print(res,type(res)) # le résultat est un itérable"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"88"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"functools.reduce(operator.add,res) # reduce applique répétitivement une fonction à 2 paramètres (opérateur) à un itérable\n",
"# sum(res) # aurait fait la même chose ..."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1548 False\n",
"[1548] True\n",
"<map object at 0x0000015E3813E6A0> True\n",
"<function fib at 0x0000015E3812AEA0> False\n"
]
}
],
"source": [
"for obj in [1548, [1548], res, fib]:\n",
" print(obj, itertools2.isiterable(obj))"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<generator object fibogen at 0x0000015E38114F10> True\n"
]
}
],
"source": [
"def fibogen():\n",
" logging.info('fibogen démarre...')\n",
" n2,n1=0,1\n",
" yield n2\n",
" yield n1\n",
" while True: # oui, une boucle infinie dans une fonction ...\n",
" n1,n2=n1+n2,n1 # quand même pratique...\n",
" yield n1\n",
" \n",
"print(fibogen(), itertools2.isiterable(fibogen()))"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<enumerate object at 0x0000015E3813A4C8> <class 'enumerate'> True\n"
]
}
],
"source": [
"e=enumerate(fibogen())\n",
"print(e, type(e), itertools2.isiterable(e))"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:root:fibogen démarre...\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 1 1 2 3 5 8 13 21 34 "
]
}
],
"source": [
"for i,n in e:\n",
" print(n, end=\" \")\n",
" if i>=9: break\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<itertools.islice object at 0x0000015E3813CB38> <class 'itertools.islice'>\n"
]
}
],
"source": [
"res=itertools.islice(fibogen(),10)\n",
"print(res,type(res)) # le résultat est encore un itérable"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:root:fibogen démarre...\n"
]
},
{
"data": {
"text/plain": [
"[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(res)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[]"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(res) # mais attention ! un iterateur ne peut être \"consommé\" qu'une fois"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:root:fibogen démarre...\n"
]
},
{
"data": {
"text/plain": [
"[55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(itertools.islice(fibogen(),10,20))"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<__main__.Fib object at 0x0000015E3815E4A8> True\n"
]
}
],
"source": [
"class Fib:\n",
" '''Fibonacci avec classe !'''\n",
" def __iter__(self):\n",
" logging.info('Fib.__iter__')\n",
" self.n2, self.n1 = 0,1\n",
" return self\n",
" def __next__(self):\n",
" logging.info('Fib.__next__')\n",
" fib = self.n2\n",
" self.n2, self.n1 = self.n1, self.n1 + self.n2\n",
" return fib\n",
"f=Fib() \n",
"print(f, itertools2.isiterable(f)) # une classe contenant __iter__ (et __next__) est itérable !"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:root:Fib.__iter__\n",
"INFO:root:Fib.__next__\n",
"INFO:root:Fib.__next__\n",
"INFO:root:Fib.__next__\n",
"INFO:root:Fib.__next__\n",
"INFO:root:Fib.__next__\n",
"INFO:root:Fib.__next__\n",
"INFO:root:Fib.__next__\n",
"INFO:root:Fib.__next__\n",
"INFO:root:Fib.__next__\n",
"INFO:root:Fib.__next__\n"
]
},
{
"data": {
"text/plain": [
"[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(itertools.islice(f,10))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"----\n",
"<a id=\"intro\"></a>\n",
"## Introspection\n",
"Les champs+méthodes des objets peuvent être examinés.\n",
"Et comme tout est objet ..."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['__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']\n"
]
}
],
"source": [
"print(dir(LateX)) # tous les membres de la classe (beaucoup sont hérités de str)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['__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__']\n"
]
}
],
"source": [
"print(dir(None)) # membres de l'objet None ?"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['__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__']\n"
]
}
],
"source": [
"print(dir(fib)) # membres de l'objet fonction"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'une très mauvaise implémentation de la suite de Fibonacci'"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fib.__doc__ # pratique pour écrire des générateurs de doc ..."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(['def fib(n):\\n',\n",
" ' \"\"\"une très mauvaise implémentation de la suite de Fibonacci\"\"\"\\n',\n",
" ' if n < 1: return 0\\n',\n",
" ' if n < 2: return 1\\n',\n",
" ' return fib(n-1) + fib(n-2)\\n'],\n",
" 1)"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import inspect # https://docs.python.org/3/library/inspect.html\n",
"inspect.getsourcelines(fib)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<code object fib at 0x0000015E38123ED0, file \"<ipython-input-7-7db8c3a11112>\", line 1>"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fib.__code__ # intéressant ... on y reviendra !"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"__loader__()= <_frozen_importlib.BuiltinImporter object at 0x0000015E3815E4A8>\n",
"acos(1)= 0.0\n",
"acosh(1)= 0.0\n",
"asin(1)= 1.5707963267948966\n",
"asinh(1)= 0.8813735870195429\n",
"atan(1)= 0.7853981633974483\n",
"atan2(1,2)= 0.4636476090008061\n",
"atanh(???)\n",
"ceil(1)= 1\n",
"copysign(1,2)= 1.0\n",
"cos(1)= 0.5403023058681398\n",
"cosh(1)= 1.5430806348152437\n",
"degrees(1)= 57.29577951308232\n",
"erf(1)= 0.842700792949715\n",
"erfc(1)= 0.157299207050285\n",
"exp(1)= 2.718281828459045\n",
"expm1(1)= 1.718281828459045\n",
"fabs(1)= 1.0\n",
"factorial(1)= 1\n",
"floor(1)= 1\n",
"fmod(1,2)= 1.0\n",
"frexp(1)= (0.5, 1)\n",
"fsum(???)\n",
"gamma(1)= 1.0\n",
"gcd(1,2)= 1\n",
"hypot(1,2)= 2.23606797749979\n",
"isclose(1,2)= False\n",
"isfinite(1)= True\n",
"isinf(1)= False\n",
"isnan(1)= False\n",
"ldexp(1,2)= 4.0\n",
"lgamma(1)= 0.0\n",
"log(1)= 0.0\n",
"log1p(1)= 0.6931471805599453\n",
"log10(1)= 0.0\n",
"log2(1)= 0.0\n",
"modf(1)= (0.0, 1.0)\n",
"pow(1,2)= 1.0\n",
"radians(1)= 0.017453292519943295\n",
"sin(1)= 0.8414709848078965\n",
"sinh(1)= 1.1752011936438014\n",
"sqrt(1)= 1.0\n",
"tan(1)= 1.5574077246549023\n",
"tanh(1)= 0.7615941559557649\n",
"trunc(1)= 1\n"
]
}
],
"source": [
"import math # un module est aussi un objet !\n",
"\n",
"for name in math.__dict__: # traverse le dictionnaire de tout ce qui est défini dans le module\n",
" f=math.__dict__[name]\n",
" if callable(f): # si l'objet a une méthode __call__, on peut l'appeler\n",
" try:\n",
" try:\n",
" print(name+'()=',f())\n",
" continue\n",
" except TypeError:\n",
" pass\n",
" try:\n",
" print(name+'(1)=',f(1))\n",
" continue\n",
" except TypeError:\n",
" pass\n",
" print(name+'(1,2)=',f(1,2))\n",
" except:\n",
" print(name+'(???)')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a id=\"deco\"></a>\n",
"## Les Décorateurs\n",
"\n",
"\n",
"Un décorateur est une fonction qui modifie une fonction en l'enveloppant.\n",
"C'est un [patron de conception](https://fr.wikipedia.org/wiki/Patron_de_conception)\n",
"\n",
"\"Gang of four\" (GOF) Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides \n",
"“Design Patterns - Catalogue de modèles de conceptions réutilisables” \n",
"Vuibert, 1999, 490 p "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a id=\"debug\"></a>\n",
"### Gestion du niveau de log pour debug"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"ERROR:root:un message d'erreur s'affiche\n",
"WARNING:root:un message d'avertissement s'affiche\n",
"INFO:root:un message d'info s'affiche\n"
]
}
],
"source": [
"import logging # librairie standard pour loguer\n",
"\n",
"logger = logging.getLogger()\n",
"logger.setLevel(logging.INFO)\n",
"\n",
"logging.error(\"un message d'erreur s'affiche\")\n",
"logging.warning(\"un message d'avertissement s'affiche\")\n",
"logging.info(\"un message d'info s'affiche\")\n",
"logging.debug(\"mais un message de debug est inférieur au level INFO\")"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:root:fonction\n"
]
}
],
"source": [
"def fonction():\n",
" \"\"\"cette fonction logue:\n",
" * son propre nom en INFO\n",
" * et sa doc en DEBUG\n",
" \"\"\"\n",
" logging.info(fonction.__name__)\n",
" def logdoc(doc):\n",
" for s in doc.split('\\n'):\n",
" logging.debug(s)\n",
" logdoc(fonction.__doc__)\n",
" \n",
"fonction() # ne logue que le nom puisqu'on est au level INFO"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:root:Entering fonction\n",
"DEBUG:root:fonction\n",
"DEBUG:root:cette fonction logue:\n",
"DEBUG:root: * son propre nom\n",
"DEBUG:root: * et sa doc\n",
"DEBUG:root: \n",
"INFO:root:Exiting fonction\n"
]
}
],
"source": [
"@decorators.debug # passe en level DEBUG et ajoute des INFO à l'entrée et à la sortie\n",
"def fonction():\n",
" \"\"\"cette fonction logue:\n",
" * son propre nom\n",
" * et sa doc\n",
" \"\"\"\n",
" logging.debug(fonction.__name__)\n",
" def logdoc(doc):\n",
" for s in doc.split('\\n'):\n",
" logging.debug(s)\n",
" logdoc(fonction.__doc__)\n",
" \n",
"fonction()"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:root:Entering fonction\n",
"DEBUG:root:fonction\n",
"INFO:root:Exiting fonction\n"
]
}
],
"source": [
"@decorators.debug # passe en level DEBUG et ajoute des INFO à l'entrée et à la sortie\n",
"def fonction():\n",
" \"\"\"cette fonction logue:\n",
" * son propre nom\n",
" * et sa doc\n",
" \"\"\"\n",
" logging.debug(fonction.__name__)\n",
" @decorators.nodebug # revenir en INFO pour réduire la taille du log\n",
" def logdoc(doc):\n",
" for s in doc.split('\\n'):\n",
" logging.debug(s)\n",
" logdoc(fonction.__doc__)\n",
" \n",
"fonction()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a id=\"timeit\"></a>\n",
"### Timeit\n",
"\n",
"écrivons un décorateur pour chronométrer une fonction"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [],
"source": [
"import functools # librairie standard\n",
"\n",
"def timeit(func):\n",
" @functools.wraps(func) # un décorateur qui simplifie l'écriture de décorateurs...\n",
" def wrapper(*args, **kwds):\n",
" import time\n",
" t=time.time()\n",
" f_result = func(*args, **kwds)\n",
" t=time.time()-t\n",
" params=', '.join(map(repr,args))\n",
" logger.info('%s(%s) took %f seconds'%(func.__name__,params,t)) \n",
" return f_result\n",
" return wrapper"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:root:tfib(0) took 0.000000 seconds\n",
"INFO:root:tfib(5) took 0.000000 seconds\n",
"INFO:root:tfib(10) took 0.000000 seconds\n",
"INFO:root:tfib(15) took 0.001003 seconds\n",
"INFO:root:tfib(20) took 0.003009 seconds\n",
"INFO:root:tfib(25) took 0.036084 seconds\n",
"INFO:root:tfib(30) took 0.303837 seconds\n",
"INFO:root:tfib(35) took 3.365991 seconds\n"
]
},
{
"data": {
"text/plain": [
"[1, 8, 89, 987, 10946, 121393, 1346269, 14930352]"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def fib(n):\n",
" \"\"\"une très mauvaise implémentation de la suite de Fibonacci\"\"\"\n",
" if n < 2:\n",
" return 1\n",
" return fib(n-1) + fib(n-2)\n",
"\n",
"@timeit\n",
"def tfib(n): return fib(n)\n",
"\n",
"[tfib(i) for i in range(0,40,5)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a id=\"memo\"></a>\n",
"### La [Memoïsation](https://fr.wikipedia.org/wiki/M%C3%A9mo%C3%AFsation)\n",
"\n",
"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"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [],
"source": [
"def memoize(obj): # disponible dans Goulib.decorators\n",
" cache = obj.cache = {} # simple dict. il existe des implémentations à mémoire limitée\n",
" @functools.wraps(obj)\n",
" def memoizer(*args, **kwargs):\n",
" key = str(args) + str(kwargs)\n",
" if key not in cache:\n",
" cache[key] = obj(*args, **kwargs)\n",
" return cache[key]\n",
" return memoizer"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:root:tfib(0) took 0.000000 seconds\n",
"INFO:root:tfib(5) took 0.000000 seconds\n",
"INFO:root:tfib(10) took 0.000000 seconds\n",
"INFO:root:tfib(15) took 0.000000 seconds\n",
"INFO:root:tfib(20) took 0.000000 seconds\n",
"INFO:root:tfib(25) took 0.000000 seconds\n",
"INFO:root:tfib(30) took 0.000000 seconds\n",
"INFO:root:tfib(35) took 0.000000 seconds\n"
]
},
{
"data": {
"text/plain": [
"[1, 8, 89, 987, 10946, 121393, 1346269, 14930352]"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@memoize\n",
"def mfib(n):\n",
" \"\"\"la même très mauvaise implémentation de la suite de Fibonacci\"\"\"\n",
" if n < 2:\n",
" return 1\n",
" return mfib(n-1) + mfib(n-2)\n",
"\n",
"@timeit\n",
"def tfib(n): return mfib(n)\n",
"\n",
"[tfib(i) for i in range(0,40,5)]"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO:root:tfib(500) took 0.003042 seconds\n"
]
},
{
"data": {
"text/plain": [
"225591516161936330872512695036072072046011324913758190588638866418474627738686883405015987052796968498626"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tfib(500)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a id=\"stop\"></a>\n",
"### Le Timeout"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"en 3 secondes, on peut calculer 33 termes\n",
"le dernier est 3524578\n"
]
}
],
"source": [
"t=3\n",
"i,n = 0,0\n",
"@decorators.timeout(t) # implémentation interrompant la thread\n",
"def fibloop():\n",
" global i,n\n",
" while True: # boucle infinie sans le décorateur ...\n",
" i=i+1\n",
" n=fib(i)\n",
" \n",
"try:\n",
" fibloop()\n",
"except decorators.TimeoutError:\n",
" print('en %d secondes, on peut calculer %d termes'%(t,i))\n",
" print('le dernier est',n)"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"en 3 secondes, on peut calculer 266774 termes\n",
"le dernier est 2129328592959303085943830833439223531952114640604893241598116687954524873436690351066861033808480670250428431498468229101754630206182777263662521788844078690918967937220233190583931976899071018700277741525105817755831702518441632740057377938535846432746978863675667001362039829165731498124578753841352955621309545536510831113846732982107632228332782615642112510770438516014202688292724003924428433006215872358729692384357680152914329881994846198992071295049036571916506795425482631492289715890831170999305084381240636689996304631317430706203325562657951816957945155385257182279677215300931245771341164341136890242292966031395018110307787497115698576475239905606728554420155549529962382904742041505609544931259460623342880623522214377629842824942470421390915822456543498916819596731501454685382731452113474939326291168233851818937715197091375939062189746665052992696653984729084584902546183384957996947221245942262626408039286586063430899920303653348938464086932808764511292451198684044483807276762582821691077849577876697872369243394626650969310245449017685277513775037118286884877264664397466176490417702949497535331396535738314983258307836485553908296300281636051340414377539165287133232956020520820535944116925647331595943116015529742623332839023108634129364561701279200717844590666806420347487246924260216359890761749877018589484900983673535472642530843633897550776249329614220778108062342408908513125553482158651766177229195411184931933371690866865943828912819937642660379576770568525132006837524074432102665661751850863073726579574693478745481779930204445658757356372547119980431214097993302158918791907867841952638072140475345411392312183220803267319531962576486451492373086803242789573284220734107508022149321727203910876313436466469555335790173585765334054673482740387237554883920665019053376880433344387307026895957802553721129954886038410901976349279459355746133504870915254025702101700841115570115854267417876066689742878627475316866765139562732301645634739633822324549072068424681035367677358679461415726767608898198037443853261115152745850904496686882034438184620161584324789633703495668750560215944554687531427330499652625459195435073821882330989533235337940324604516973456949024951069022161898491266286988269882412744681436538000169701805465856320355024014800021782200678145188948059843015832141576969677361582097982196857436334879362693875374684577766477609669941150420692035425633476100434727975627246390497238336654677701268547860604047789586277404288546187941722359939892623827872505789639166166489987192410788134686800583873750846996188943255399130446838295788095290823330410899629074541887023992296302419746998240667000956807057010353888348379174334717875536304662136732187323169711408535464354846350866792754663265188708337859946525862956627293260288327172297386282894510241873655278555195824207954372480690093834170986421282684902582615022967271017038194368078972917695752516764881008294095187615864219173980703791715787812097175623842369972815471018937602465279275482627583347803003707965435971955188190272633709106822604787821752357231563894943869004088883096324790991995183368372610423147883194494722213575277652070845938808347395334498331196956701036996881424503120567459538018184304241957881441029756063493152228190471684193011061088086620828861207756672419813648762642395433200515153004359243701127191323914477483964482219154748253313668922799633630738706489975442601527999700483695867396136255970695241386505280711674470427481362557488180661738315959355710205943015065633497845052904391941620503796556994085246402507308403488720826528704992667963342361441166647328898110951294848884782626642481508106376916550214183037938693566150122603365037165797877564796142020332899244582112405816297796382082234324141455758665737947126000412151274338157817237963641309622048817837447330580139576396722127150901653257636814913387312982899915780581242563632806772960419465480429019238706644352577816280984258688163933969738534506530976067736829029814822163462197143856275187764841626725877508267330218525367669291169432689433208963073638286111970331534894729657090905279166340121981115739007717438504463916907662382247520407725625430509563057835687036570867184187511180401851778676763434914020160722081179270130057601288446813818894525523835642507906203514680717888528701898885623515537196645834158025982741071511770634796582973628516973382150609940228198596657805646645934979168347147470924008222373643819895571793212981162562628914093427346130795634590034655328966101582755094147970725652326612074309584008584563269502039340850404761483766499284652652562152819559857861694199912268847767079370271963017789175042405109497448394144352599223266537496498529081996768523164400886001039639502239270503085313697920362489302541460097845510105670188143441037239191196538917375288643759280639565664140346640156865269886406032608942211902935373341430157615120803627282239923233008962017066237396532524606700888351765513039741158162568908150748962145872588049663120005138534629666395813929330596932624049770405302994725228046193953266558277960942462450049488084550504032513239147982560524110769019811527420536114603387839307642231663542879236799384000353252639622526620711350539950925368688022474080334865449341117447983380665490805954364655859683279345202377858243615623901846723501123352753302362791279220366195208280466448638528675535450615572314879097373609284667468895170578505718657203053642886533806201753930235310445743139363228081832786241328739194626215458734716312832340571924459017204816801055141908166086556428268576888425088779620222107422296112765531693707818100112992040927235960468494324880158562371812059564800048752699248968144572585273489360420221435315990329188130295791404151229544087685469692590947479342469315845600866207282989779630467915519728044694712710031253894686746983256662870379908994791988270007118937468602714950763111830295453084106889013296657028300191666225509467368156463694395575406136662607869705426670830800322410926221215669392113084750839667853335058719233233112775489791453325566902743952544098878603140236049627582027141161479288804477027522673315906572799185531839906268298149525907777740599186113407851544626828532329408440153801334741150216718843976020418960101023450608032047058678069682421972425096994631998775719721573238342568344699277804245291557138025748021627102392040970156264007398482016594794237162332668432393672260117790966528852496604831677243608558497501522904131974242334852192957797651951570088359552985397836603749763045501764658397592816921400996758960850988436749083090399150689613900039147514204463509779262724961794010796101244171518809540746479382507397418401883341098954963842951237299172208241683223063187906675875725188494104829070456444786636457862105580369823950199219658038829929807005934547997748269921337048617168527433644115222395076110410252217506858840358751893801847335816380530706159946830941119832303797449042791034918112719643773090498922812834804255645198539552849756067910238412992841160679136179682663256911213541490792912979846147816916204477298024753085126849898628549707552725815946088134519788497055964477483693386264726890047304853812011518596664191721175008955479654235135630172210927571813128260585625408673643894974084790490725805497309354065636642070930846904360760717850627060236796774541861526840809146284635083648640260424343302647726905449716621597309062100419463611789812351332021543811100851757038218083487754266171384104610396766106819285772239706840668104696923370220123145381658095548609702486550140751849048622053360955797637912312577544465445231822445578533516464435677360547176997471848322959161676938095028485380217009841086753769782689313549792049568988742118353626752599781553390460706334469693376460013317956550434428864243330506950002260242694559075779712448328240332519748729082105860118501633745793864598537874737550230085477907474985767212346764188212530415617426567223484567635485771437555196881592337820283580681323459442131339714685241800633370922123464826379875393167951508598789859144847174908846414547743928482676040086679325079289522696041376214939404531808705296112700206424432633927423372698048750118832230886887613459762424547749521002968881408542050492904069669628988012010495210292495062939728544422707674286756125620533765371803145479407262010168799527361796261600849552129387247633706066491082355925827480945423349485288941392402912597102631232146396893041262398428356634574934002601413507210968352973897513852278081930038800224240677089290207982068076265769891156743566752757227150127154909124005969679514236074931772190372849604428245643925092056965826801587116903872505079744859477743834614486004177232021398654619904486843542437745168928040575313678627011784882184994773325152904048400963687097483848097637324148656292870677863599745518393144472607218241455892805491500110796147324171637569871158554215249405231311257756701756946523151833497919164181622535040239131384347392698041344496022354381726464773665345987949005644928496832074443451952148853174901639237386538569080400987211833165170464077517746756533703059465652189697467342737160437941143182014434671662713231595241653396061152386690694984261649805973979950349545242827232711934524562725639321247927941315356953783171056277753307686600989557790029546598794539723799415786123375594084914428587406067854225998951363117485844643065478616464936174365533847563717168736180031523103426632406797160578707794947653804926805538003977265553278907468443264709137177939134301597636900905979201209154246568055832820800208443579721260486175131932906055807075317765193146467118244705958583987228577575636397906765342454220541861568332470813851200895453799368714543831466991393489901267872842231446512165034645944415529843012778047897529888452646678964573651376107494397715208332273683694274903297232167298122113704232094972907120467351460949890970493460089003108103628571793394092201419319299469181924546664629566896793703910403358121238447559102537673595681648432744347326713809027676882142818806244173049961196540481575400771215771071278511253569459389128983816851147709572976895155834750167294526187695665698226047977125336239331465213138685494918483395758825479320560708751060639799122360309493934614064067835542440852527151552430231910430650378720781221767990449711687011326420255712037811024249870875741373085191945601842125964741998811083918451051712337774771379769095299893333420695414139408232962038763863763151181450685609720132077739533993659875358655484565002901010438312345842540836256072709405969244856991727249425619073563635688624490207689587265326996424907501945460491747496707280754633711738317016404886281919673410673375369885962335911788720009308744688267468837714960106961709885137179925282655301097029700141164759176331118854732527902009384625717823396727062795964273526019658370272346013741031353169445390461862409281583109460508970149342578550320181260561141594438413838806478577542769680572322857367014480656008533477421755699454279195030157301609014841674409295646475593876200672386080638373277884216859145508005738921341026646885997484346720570188101082450798717345604679890854717596799988648905605763027191511720722423881541321023074632849517902218757955535705956461762237782040506191079985308201978559172337580099926845898224245377697151881828854475672687360334446971836809717575067520187530870961369925696306691931339670505324553681826914265195845741466607716972632734588651912004085760523539685303464317137966725219662536509839858175919666370073604774259479077620375319526117882853270570970271087301545390216724110089530656339394017161991385188971142414145210115060569603176645549793122855750566466657919234224171721108804773437660246501743505402400622530500805947356918288317202538296969465038564187736955067415977562000506919221191159086133564322019362316804259598551292181210166630564244115569843298893723533992163163999988221194358794090305032860487332244705594476880291767096518436409087554954113718571761872902038789179312978753456057712505586575671524740383394204981575584147875219868995556606937215243701602999264996527749135217019253884072559261670545104664277055585802666229999301158729832377326418955925293779655764822312397324760010953824353329612387735614265944669048355412213910949775537557886184137488105124787025016710896494886158666454395270021774576238309719814075436883748048839249878034885637283529585970816267023366515149586912258036447642541125713442889819653414281271341584665589646833901013266888535901531068357984075080013536421998462427699981366013004892513222117622252716632398685575694531203770299078046113248849592028099733069139004630719092909121559178698752943843172154683062375189195563234382416976808909458531571663581940269034265017913515737248819153263313195119280360951830693632384456775068412531797874057229616372543206015643230972913782525983346325707249905368213427086361366668370786295598429256981187663091519149588236888039076877747797648049914572978720514345835551766768529274403461042543049534617831620885047400966124161449148221623285236124693271381342922466151826792236271446501691108509548823279628971357253566922046742797103327039790554778411799889397650223680048608702211378128435266094388441668432866549634318025128396281632510862837689543234739114395915105135232474401847490536608790917703118207473914972350829159672359461447035495313324548973684000107683285055415168412769938694013146584521022720680315721140225495279874114747425129619300707933109921228956051860779811753595833238892911737294772102884516061538805880735436240710958706541189526504469387912226830560317799952551122238797100676343175945282499194917072186406921960672897609026756853504228432974547950389545244977436783007003871730538957977165405537366015406596628901351963398415691201247322963487427351872794441007041744643974596560608120348834281923472986620937808366831011754231094578612824401648353143200386142798430483759879881847875846830103644988564845227678388578155237906642699373456737192566315689797854809534481805289728441891139551853492862420390652172494522601900775532606170321613328442027016225074293322378608994489146108582241741523337837395928410279512396914369749100020543599966125710443512223972257797642545269209223310687685257703331504232494959918343444358414823805296250741744836849217769981771362180167047595424259542044975142638463979090161635554996893444222933979504395686842188416594775981916379528009148419160014066520772155135777251500336957367409945592608080803103579919540497395780314373698490698961772062162925481565978471073318237947952795369773335571469867937551739321093809526469241309443006815565030020129541799535072909240641399876422077087521312300831793418182688939719900840510105052306170921295582136966285360046891988020516401487927330084624147658871055286334360959054031035481972966206991821000887482005967709002059930836297412377779528857739955182236052021219760848695725311824333554641112388975550671607919557130265046010403780829365018364073713218985209991999591511730244841983565216434263805705613404314209089199475761298348934913956370314168532392538592513600212738872160960276845272149550851801161322541998854785195139715908399948456241348971031699594996022274369035050885494567107605876696135210134167187706876913876608573568182159836873354523546632877615107574866472614360857329490354964766129614489827748051046015071347722412788740207806214365949157606856693341153304104994527435647262370252048912260772086054992375152308389440636726090547565363305350853113075221080935603651632037793455647473164764774673302447093385756916233405806971060770537425623030702743750729780502287977054349090905698785859094533527820007197021090978674875196962138563239287984521539187615071167235462477771193206654053948342190690277002023580779394125382288286350606015155566250316438703711410841350455861805929664574406457846381738236276648724571052525823222482988054169303881821114435639285648653944676121912147674892055920953451390282079592380367403591693064273943202161810404559359677313447979185546188811066468937182242055825077141428834555216266431742243351905791233278547712305460605256544437896729374778408081406659105099716667728985705947733000858376265361091161342348699559135270785815567202464192572420391277906653872114426635358725249712673066826607501839811984343234303300649241007521052622771310782179557571013903456083622217558593431414193399361583608346165010286390118190746059955569111173747929476560790129641649115345642087170286327736500277295489288050463107968061191653279181104737567801436627545246547412290094395539171597918882796322921522227921961707898399894856061121105840276195301249496291733461566645235549333252844621725770554977544088674651387178700631650442186541530635520832420053627100307708623024454706580219419808026076576715291599878514204050207972419224437221424237293917577783128112379870407048315491797232655807905055040179019207433335031234448210542653054993219115894073226281368726344186954444029025175038488464511710782103279336490741021750980541754540605960012465433993988947442446189947357023968622055248765985631519420397198700208277482185082752390693981898410240411495080071339904053228199523983942010406649951655229273550894962221357148689624475748623730771136867391252122025742111810570436301337993497590137197432346689643453226209660370401445614516599169704303639613811350097431805238215087489805988833487286632863032459266571605713382069112193996309467822750068168339246409312006062869409702741605478293780328622553383868876239587476713057159867360263366169621108059687824813821840205632188654779596664468461884322967191227787593122343510014479180054685941211197815860853507385711788210552238867075014437004530273486285213661370987858803430458197468504056662449446684888929190801867176828612354816639338859842055472123041672497474066627272779198218824550641628449112272093178291767675556292680483290115858226253600578888028622607825665624719710693836928406879024072515226482283023165515074205839730181963443747711000670056468565314213239787183479537927726766966658221389263539463706507071596287724317029236558887869710898662661371022931667144944199087516587715110268310789348056376691467009033392645253609672807413163075892536243511243815775730468908886636891936104849985562311470758023204354998028206284218675018046442757724015117517000069126284909392388747595849879987597649735160227417207221644220914385816104713854027362799107520813284766414910303388052662447714692285827940555540312574538373163370739844231510823389178221196294886442402713642712139847010888061309349433277932902436458401335291410861306396582129779914173043123302653967109924102076161414958131011298135016460248959475381824202478628520583835028769101618674257816917464736081248543107011673597322098483095736730059056909996317142173566381855519251765380942666217731168361230878993398656067359612884631047869683895421453480798723364854677618193759840218785641886742315020855071550613065158555659721733392177268201824997419062438014063003092670724847139236002115122015605154460212882874944161731374417344420850161891821410285353856311141083618237705773911485998332082621984985216684613014878417136398175509800106152961690678205272113869378325337576118369698903227994695279178413235293519861736373710187267089443385386153615141808946241935218031094922963591196933524846140960360512411337219303643730570832745495101343384316259162903736197601646461920588486171918560251386333777773451792371248073018733435197760798837095274785624410293123230648126691496261921137346965304464062567518444341040691866367895620425948082176152408385254920593991326388332723074727739182367045267401419798020344721887319796617375029339400941366703213339056413181193596462627470279453249893564189062187259402073215787106733423156436813233654659243296528282179668531821385370230472558047681916922482857924593950459113100142496157822491647415511409688005039069022476460040433277372386033484165318497428018077858278831825617072271708258857577071918928186322811714275002823201628506621722573426612010713908130569091354409583136869271508927139577190229716369045316471473919595767444450981848856104832082965358964779307311965977221112770249100866687269631143351721377053315947816464615202063323373279517310464667813165882575222085713732956186944465109506402444039797782727354918969481752307598079878544400785438754002548635243857390420465852749591182126491197871165037646347795649812092510271151241281864836365029486536967988581388261756067634133617346441708787757657642584247130457639605742919564559331174256616590923455821722958875071081793958589178730041698144101042202604555114105978596082221913452075109048353806057263916729643388193117599343217923543981804719861194875325086018028244127004521376286311633087527178474355367176944414868086331087969851765874698241845580792876768431318423770039812554762338348713681587105535839036890206433413035553336919353664618127589574147165133089677595232700141293250732864897528910718347236262910975569978896051092073960198775812650184249921982975859949695988062841198404877095589796681356968236121442928168197387316899590634382431212671048682406292304995750804779535482978069482560277663323744521693547257242440006240133731174862984222677243315425681440706131402069581106260114682753069959246614627056081962083525667000171951816284213520277097209297855764273724448570293623305651614707679159088569587132976698099945138856322484168819980074823618672628646627916467575429690938278651177655873709924595525006433989729706059489312071098664689581217112567211569466038555619564669900008370472070260998451093257786588432675998076233900167621724366269512558174128375869440138306459764673835203069031368825106579802448302400809211165090522093953628003225227193687889834472085838562640903002848314870483373966104649834922354239800243739105975850483344504199696267477516830272343728864805035982129159996238921763485912082202794819662031045246371988557108594142263510522185349445051623797619122918677513154352787814480747708766937971805686080698863516426591477388843002485767948582635276644252366193988012633810213953138826309260669551380056091295600982995329399312065011507354010552614188197347147110402224380580033866637804924320595068264335425115183872601872654524345957944528310753469727700048603517645704631850565733550015686959264219039747172744491478542112308502151138953933826016520316606192844576466252983407442513260606192427750305338869563202376016083522237812594747072325770200619758624682384743752574228872193110094038350385987830867663606254452955541777101156360620637686532538105177647644384850953615338206035347467242866346953482855810186872437206066718344657320977056038038485779248655706128311672952749261933561754306807868587405112458612324351588992191981724503718944755355860592394070184795055898991635176409594185674819117315761187374481399760231707583088177334265838233763934276461499863600018508097424852678583109221019562368413374965102820156920606872354402068076706991939250316971791373217170668904937256090941988641219757442447456934452874349734391128514009770896413431195428455985910084952942982496513200810920266137123900305968243808117529384825105522082612634212957459412254678633652532652159399234279611604942369534542391904466362396175662437064393736260381518045106554153119285816881718707640461000860213352134372030809794147701909193958660032670065888432249656133246150202839771528246115791033410494796416439881210672978151013240916052949283309120691454459149796117305069053356745609218010908556276119720697669384205839448535820942845749633525715537399556847569681335123535060015810748717121945776654031294868422418905964778034820609405420745600156961364756505803947819991720894697547402311184542726808788551623260358923407316570834941456345344758121433788037096069023046887732455116127376487799342566726978109770524301614215778480260331007329937559622036671630766018783526930267817368252110416921630475386049564329320963816673149229749452571667891524805196426178070272472678200909628416019433244086326176346271617568864864880888106207001834298695409549722996554279119917861967017284350332715279018101345118862283521244925941359220199265146430635050726919724815424607840433517816343504224997157583156470222224201770589440370870205483606564647889894587814952161437532717405330965138921975095946335147996264064230827991299323461455067876393515215094640705183157476505523161832937489445473232094972991691402735954971711536305578413875988064857977314747415714657817772875745503767454557185930553356832846491775910869175374940836549786040696414557710630489083465213870437302485819717502468855788995181116171952769010376009091348696881453406585909815389854866287030714825644009626434848220556526543293133427688313974615656941308511634873160583645034000030376877600778809763527485813278704068342755428597308778317899286097649656933188026909879944064027368654687316502442712618124425347310925682777410013956518208770819647864163027427538915908155902206574887226230816815714788286108720115090982131023780225772546867320698705237368761116905280019439747649081672574998464494981022961486066181396783649770849223622666167197970466625016982164477382528449865978252758006267839418528133115328104833919154060571031809159782481062641486521675295305075981038995146335046127229909849140650102075160373992688516224329315060614586790229989993050231181743539309609751597751379338300467940607384446263448557136299227684725722546648667083111929811779553187563224684211727925821803573293263671480694793570692614642955544130882061959765781734228865568126405095333914701220077686176030055637847378911371990531282719831727917960556399227466576005005362121470092731806697148854251129747895501709655109671209210554828552786145042693189838080564529205445872363845016613363650440325079840768868733215971361020025374977863800111756939077371925566807862015241219861941892792624506787508099824352945200494895031348695042432778498969510568089349080006674626129117179075929793744894770257821166490250258945886439839644024630755706262800379557764036826802762341655306369694046554435359660313379417593093728551957474429890152018793703127620908933578641014256137655570793306308723447464691611587175792651639066838314434207154948069943767383045350134170214123418644038027872170936678270664888166816312691045893280107304929332180624574577447131501422495586244329055367955178939501531975804829007749646695669986939625504743598146329270102062411709074633569072382236559751970773621542201345089093852275000684398439767524620304502339137655169210630689440008103628027337654860805331307167958247723704579326634569751433319739654083300676786183991866264177126585898573985210406498953400517793584480537100370554714464169744140232658961574028594000713483505818562461939123179016859917245051732817952897817598918835242707386997985771375672300860459181902420917323144995910621904845837585061821653332847328020725301920913613669319537053631241827317178770873934563059924601923108860921164245172149814999037610269093657167750522522663812173717675545705635729912480357517578507008402729874820701326872988728517035215842853202607660704158658448251673191572505222167601395459166102683493088344687239955158562006536426575300198432983721673947713828214720711344627303259817835715740430229410916970349141863101218288224368147431241994141106309671052863271572858936472707283057915584669563272064669124820969453838035346301164010068051795145436835040996579741181114875432374845387061708643338728758191150229831258467593672884517226868350272556343058571616769777525787816804372650046487949147317361097571327568828308678666628490735587948897092296809391728696868226376139465865852221726349024339118778348949004930894693374778546538799299206636306030225143255733143198178775262631063162212736412521976977567393322116601557712743862195942070228296999584444372798966970086043956526161139015915434005460218044112560857065193131636853781686472968759176816731365172740607664398004603840525033726791582205980421510907949004050541899775782431356630448187727219719145294287226137416365989344806638739687182318136164578919468955851029327944084480853752265265867300502979760981375160726430406079323206665417180563226181339196554876032821567487830113183593071793134535383848720138840693781496816996350650510933788334855436069251998633909038633491814858622029086770618765769620410417752190137735517313985029964352446488380547653213579602626407376089096427711581007324127660325101114325354459258368095638628190094668770743537658732082318608711501578216960584034228461197853986672426674513641481032470692851510894189960696633005828034661311366582449482221546237604551427418113762745267844665969113856124637979121611631989226968874905293901442030463913396826544516288879739594241265015561467961505117594219210483880231280842273381897036666742728711299154621001705889211743874618789845679774256431917529177101850295770555069208416728696757264628685142487599177378157527449275382209124411083051618507734248700089796580240543389858308554456217425970107964047650351224347836147926762288242570713755070168305156337499225490819142095562494361511918791558599937314088142941496245884153759634452975914900632043774752936435345460270019698896511546749279744909498899966271505894811516785749122683243693541794436127607419793459131965711868742317951288054853523297441650933580273678400977251275050693145247491993592765735051789118012277425496238720882357551389342526373025039688593906004191223197173878229743389360692517347217441745308060439602838253148193974495914251023860307032508397035803798193583031158478962048847643056649380886910502571906147767068687608242273938424582602508910027754786028151885872266783246342431642659435610901743644158467096402267322327956540820503838176496407349239272594131767738195662459627044212508463203381969517559502191874352898299473564936938720129704180512859157001587358345902926482765377542445143399183626990260258191839356051877570258015995155858011411755532598028075406196554218108892015423005459148266306780952446116067894134068604908307065269904254859967207146384201546984982805229087556301287502436969613694491844820509985027196543469359844838348844184360860497444677834052428175646544011884656649391079166541690564221955820882901376982079874247193302968299418242816848212938190496694541129754741074247904698042692263608047387620025106959263309916822293854993074854141355787712531851047751505454863861973579259025118427412155908287402389456991127457916186435987718806408278648054783187391432244836886274351257932975708110167175965160100854354412868196283693316213604145053512626243156331474119791397577044444249241624043670543993583734334595918100946339348806634440979985951983731929465319910128323169649572249464245143577759204773916079565707811499853402409832149587371060403645316050607735818236311883804704228005871272058545607684284891415879519453787586596669566881784127334113016968016681842540476008805436974150749657172760590063567081190500559410878004685651233376870929099265654160414273949155102984084283244744475369985152056208659189526191820603506473570267837683408768318172042208238171894644142912890532684931573080292320917293811801080431804000143620860796937555711157088696635939666199611606738590398289079012148525654980380531977388285368410608978982452706749150976045221371653286017484275042357774105307206867316434884125467479279469194045751013999961727815922804126878274755195646334148895995462488340394750806827862050420514270264627235916402340423951117229586360940677091876629389669423612271448820943333700690416266524675686576300210048758362861479171799942849467747296978623398538946601700499095993090914140782716500117850511711471943784703745528980365931265190884675606857586775094386954655399458107840373863670817372737749985674003898637953963706693744449424311695570508670915916925878931007905029581928256669883106225273033346291695797908422211035033275527925403521434395507449402238829427192623339073501302271684896648423723314679986750180037750447016526566339862499072030594456737728197253849075029547702747010141004619148181376715460263786569165796730691181127636804829487433142680171008071825466588131255015389209584980596823750927625590436343490852662717736803847528385075141013264304556018737235440272595029472647370682042405794173368043777690124546366874502550021599521174186744186799369641600926768860917864033188451072366338220169715699536731478067629812073410514891989387345752372814207309191165030344372719058938543404913045692761022615062922747498161505349727044516748264185915551989993290909321032107278149461680006178170640145171982228311348108979764389080777704104895921599128489989784691305896872270336949230081750725521607641664237558670621032449396905282635726120381061246426909407814685520680793115154669661179621403691858942260741699944207157035159956892274403122563968174315649945055876540017292643723664346945663576141535189886046548482633431570091091675188707053100227675882203601689412975825707722239640378522475082749113935607418865426792429545148709116658712752584517063519241122486975103992175094736010763670254175466688650683846359875596667022988959681346232896625718543341351572580138076632124236913162734759096354905966533189862291645112423696065213270891582653918488210395140358643182475605290595798284165345703307392678824803104759358586027640721779310251915557987505582677963803132348156918355644508887633661455693944118908242381588621020217192287056019299228294838928140790314263308333604147947634742752149402690744091017076835744173611627892383764652560807333218056830852943759692665980457927496445836793796251902865824555896388226637505399922337849667468044860974557533975205099891057365432876941494920900007658172414182649848607517227961090268467672322047401617588058244574301371160846054158980096261128042657135994698299870123132877062553943984565135211928723914652834408261849019310878566843209068003994992480801462081699873450609031297494415095468861383803532258203295389422383926325333754027165295700502340262470917133464945882424717858730756912585324206091630048543803626728803757921438560713229131807181834169765972220617805145309993211478702731700600425547911155868700975708809748992825848051292052710641376002288947914092191885231137456226719171408796535255672189085095576425648245704511157268160262596495614046976054986445130945485496255103824594047129766851010753537109960027786251082926337429479541628355380455045151341115286470518854814666278954773440759505441294643237768637105014143172557119828945839056878797633283270767249669637780594930250762152698723764616087455173117114423996316782809141259577586712121460315566091159866859293532242709346397509771270020295085262234934220360176412503610519863672207899433280782803939099904226014615813220587036456194781111598259964267273355376142973755754632092251292428759991473300207426716889552875680841535356952547199156036807054292959239767539486857337152655068337598178355353054796790141073232677278056733083080750347611087617639279167307356524481330688598820854725209596949798663148391353677347811275281536999006000820826365839919464579431594259604038936353789011722445899610947794414495126008227925526799235106627305554341925187265682821955325482889722376908731646175333172709203640427345099490289615647543248200145950434932142472584949403775190774294082203291175650403006224090664611681714534970352244388413549651951043386935307293964588800085663209088283832055729975832715792041435597902153558524233348089262074960382196162073126355216192164745580819272350579780366534637334122768096787316946547464662270715713604995058983135891764383238794974069315114745404049210442427687502330334846736342180473723082770181764909606380486341901736287235491552259768951557668672489433244508665764530693888244944241122828059651860217996510391477529945436903895869835224287472043140447068928919993838923476082968013580839451302424407445067412839243509151422563741836681371904536259927849402803031452438195942332734897009258118452130833740864904075667380985035422098213914622652425353946890944296584744803093022109700194051085371092351568449925131533714630239600514752933768419878369948363178453161551759984880433429070614323704702428533245151748615484003022980899160914471989222663137231897440897874910894749804441499668748490099819349603185825542967330452053003732492152478348017346037046537559373692595508946902959052302288914331538906615997071326577082795962707018026028936734896057600984063482929051482325715907021410860403276189760477676782847148763827905261879680280223693654419735684379814882077209817727982898608287765102439911109767221591937899404452231804681062227322397985238024296805925565545520874815344308667480844587099840439233648682477405709043111848569866651663299856855215182062959770386830013125337002560158695515945046825736142698773624741569519789492025404935806163144036880125674850311510921729209328880923463132904641077151789877550369719767919940642470891791248127873000772882066171288744661594325149979951914185197501762403128152473133966413076247164165891681757462730074512426288316145975745516853908149952256838754784540182697501200926798089149764030994844256427200029055377803498114067382262509067969397631852579568483044191266435987125086556340485619852803217971115346707559089359922427654131693686414834160871867220934249067126999068821304324602638495124789210095040690455088599823050474312069735889408038274174744926284157134529763887656526632572644927873043276693399640475584741182228258258988520444766318907425495525855840944081702653079727921500608567649112158490895265337608293159549769984099627237465294815362347097917083757030480257291258061722760683258668497972602434025871065305739800993425461796994044047512112650220714173008090782539973056909833749475722558384326194689304461200949459831412140713119998233926773305822264217989377187032303235419358825562195850937858693502809043684528851491014395729030407348888616534553321036086748207310618591269895127463156006239020676422366121805153144935992418777968458334183884371431351072078074480020514502007903026866638850608539478394386616268076309309609173895282066441738441244969144361088572878981492491284166387945990859145144418387686940050100625094755705336829838033227023413053968906616737081814806197645334377038296351053202830082348934230336407209261952195899691911483679879048964251226407926050760034207832416872253370617087149304227330812410958312381421438734437359960248591344869662200338816458382013850659838109442015203497340029286437064512916300505212248378946325474548328583616324442851917708947416715377544183131320081964638436902945596017007299593823644812636848220614938891611758546961914919562628458265621491048853680111554012551526983238568730104224237745180999702639266357669505685434867134289242031315684450998106011643916652489698417649955663148284527318463972864130885289696501068337437653371840848478783850431136415740950515934732346094991757931627069317823458496998306077208017089830117698643104804046007831808323012822627739560391021589030178097412712289023080747465807256060754702892748646426856749247701650734514819423484261614726203488861454637606326426049823145550874568293898228616929242244760268529565667644611888262076623937441188326310311167641387753060981654204357263412624412519180923169842819619461622246935406160799768438678162527796931047375425941028413182155669171830165188666897769165563056055266805394876644439081419005448722501427784000586608929354917020301362671587690357683349739130437132448959461427802297930505169956310819999741081083605522675635483100819767943622306154083072390185167010142979681617421037556895578829256394910308115380617883461601834631922724345194867508880987885894499091039199664494409218201495973078282035699075024758714805088097792414880231405828145637581979297676959828835916128780354699091300940239003018489475673475984758027353665698792344991169219102528354884774387265554125299114021095710352601978732123966580603557843071506767849282395530626649733866556018868215629790519234301262161852255993950423075346109800297236105161559684176194547860759770863878513037506197521660407654443602834720981271981318000078739649709875462888209530669682376348058757652142298782407041295020723790537476288418080926481608290434666460541699664134496187561430507219119114179419318922570824493885241348254605468079295784507078754332590973314643913291256956852445802062279497191146762480873298686887727253948704467112529977521176717527226934058486402268004915959284505231391097411315006499922368697666862274042596726926552922966664176157068970137569500352669134363258697396008827729696526760997633743940446172664373567794187959595311427851964770279045582369201494335640305873505296341425119968238845370442174084840580165976875492314868421082561941892833620704259875298152788439626585512448267405932203690860584575228997414673371141516702537207735558926720239415024709288872609072418007382711921344434991550442370816311296392133910349853159056985681259556594412894795863008000819423743104603630611895290034369560452359395243167331920005097438066242972003668754753495223021357529734504188812959444376093630665408274420907910658368218503618851964011592573280509046624121927721150227711766908385186692551939629804254157992888000756174831518230646351290166766808215864931018264877824144559072379878391024488280585635516761998425252806793695799019799019965002943271163017609872103279933290970692547121822318925142380111201239212096988446996109255057539558256995299791564594780271182649112990633938584524268094961287383320240780236312212864517254441867807456243922273863285038172556974655996660848020741689046135142103328463874291054514767248788126112193701196403221406731617756153662729463284404610121168287721576026307216866550727011037134284997374312531174761945421207946482334675629872100249839837208503917563115861654485693838486209921784350330464851033315061366878892709532951272687786874116100533481605779369131861189296666500134654771140318534195764531672027297015254144416868337777165717357086756071864371264457694532326991640896517298771650045182129349908395931682418359070142768591218025874026812675063115356856268184744508072071854403673466588962758850847246872703301259992384157238972463442819554816626868191226109994350393081341681530365728910892175380171955658816105377636783170434950105124891067861307571819022675600102444053646424596814526409129587765000433402326901491623780736241289323112227938859506101479550906487264091431230131768683594948122283115147818034767320231196461591737848119916146639051776525378432347973291307440996424796008314458076240773397275386080183721623232272757838153337133207196190437607565930056699177581414940706468338491787725427654617937869469563411104281615068734350853454820990693786022019742929887865695527896444613174867234742174636209489726323218917114663988454312562021484768364608396968086925724724211273632567400486056656094000745004996217479398346865570721262737618463202117838292703954020049141339978680267211704125544308314591757537745486168988899891887366048523957732676663167644285358775626992212575901883019782205275001338687911616800080060587495476120854685046107913973978385034112052230217947945090023994576953203175907021638186203311464987755619957341146967238428382540468726112652846477191999322717747456517783518611211582058762242222203563080373507655950125905280671663987496691350625349777957571516831242618202795346509572542504658193189602272014070978395264386212614586959939839452321010288253148042530874512182581710756876292559493898636183203693008824632528514730354874772260224262685477457914147155598313922949612281463275825810222694927813601483012873190235032876431947041507694753135682718584803062573653068802672637080919025752720866191960061898110296398542872599818624819931506512426608620275507683405726046356455641779881908979313227995662278614297091288852424300678363402149982192575675229693157176977220947510256626950690972154208890062135749124749063457716245788872226643498301892481339562747765404138006249899757405453325604026971867325756002347610663488602148041268613017535801988086455247164870587943648650996363892650310972655693947889136878927024254183204117623286185068171679110368609733440501130202454614480921710224571571000147931118758215754999126186325983498807943415264685766950518259872464330801350983008382145604544861737876456870115806595098935920405082473980433187174199148526620080233989763811742096361732296201992133998844994094995879225361373889062533810195267444072236098545080054508354187104199286751295528258850900281449222331659062672300585333239438370527723938251567683124464896361356492651412688120846574294386430441892520600144139996992448730728598239008270559786913781446887807404143194014342674219445744831654344499243456376034078411420276480547212576708181216267678313509212146909940911304980194411210980015409193821111797774222928579131523669550141337405115935461917699184402574213685184515488840994881182346008342945496935817062396031226734344666418684681744442177610916418982133211623823487302672724616089407737370662231810436738387870739639540888707274708893824459342267981171447876032949924057913462307791090226158263255402228988610673355693130675042120276865305341087592518533569093754039330458184898015412910174828755603149959241283703310471348512422836941791495403941240005135160291660739563508382687324333610762297326966652878941864503910219460056145486808961319274015878102333214286536225019694012621306065423612123334273239281680881117589232959694792393676474407968495921583839497268958131260900728549436329396350406058798928335658146092677818958981916364544597445189246313807902600310998071574087078458441159533157756442774615959241725493298754413416869498897594576642936201627653101931429043225938458474688947153475663313045641864596335167214918338266102153407574387076737083533147135168640147417242587796256575313077775674306463248778301475094661820163771541321768840861816416176212398281238683673084771318681542068715703215501664631647118535296147631950812837990137892620171254247778702913688137056377682621169803283711673228284418572362249581345646127340437421947298791178769937889772361824685560611007955874355525705909950578650272199643603390442762572815415557143226886980118428516818089588877725261599909647513556627624819382976017911623299292112950077750255711988537690877979917966369156595996584835391919316660124045855281028028860163365242075891716984310459926200432472592225980779356831269383515302962541861507994085481074648867932286638645260312125414480349379965378209573549532837187395609135300023521574895735610429554561204285672339069190447983048604636275996886152684990261284000893350073520822332221971539348822547739018685517633942245626688840967426447124489504129830003287768641764720207980373889954018105537087522120414435581470390165975287356886494624243443167041900107261505952254181170872066662283065946537848788180375805541541911802125713609727203555990135545693690438601908219136418445869687275704041415737372813335646625659667050157128932061298289031715712852390018208936926849828886482877608038208096265229064054980402079604393186822597891682977162336413856311045344271643669955031006440874553359565400388322794477069431924272181749697114212078337327370127756316048354566494821609510662491900593090101896026066020849595606901912927345956616507966026206557825889574812806362792835718803736707434033381680927861031027320551394975814682728145486932514700576512564340033677170553561930302924113532696205364504953010615008171246518237980126365878234621474900563277304291877285827372541558520171247949766069170956895047842098052146583583056667946411579436013249127982736025459177074788396761805590696003989864249589969022378465400908220512758563784962087014220374273987398276778021042619900329342011600480641441989748194227513458150776827661135812272952970109118272066862733930147328166748755098460452467682438270169654112405541561908860889872218818460384582105913600758216358859199503089380403040666056358411173916521642246980751652948477264335665945258162327136041038938467614747469870567133908371742758173838118003625959723924867103145577146776871186481812104622871568458018240130509938585128032276678571458612245053090451800408014670142829902976865139646643470246509398018898720635633890612653589750649391701371101463553170190619835662570030638119491418764949954183803880369764116338318433850484603430418386177228601426102461874666863927817687324119241539482900524351245218647775136894178598186710494129499026530475869885425467636883363775475285220665733318650083362070237114432557549967721764892176719979226329103420132889483646816090467575011984755791009972600077339360459355779453601562292086711439031445444013716192759254327591874580505531891774386090078205011018434863508251201816622129076068139801133607452320531604501496139631426725881283941389547226227334006539461677233186085074785733593790849597663226202145262522791442092077750458561819468069569956390343118397431376467772187168648195347322594655531376209749138879722656195309734547358865262437604884393682523525297681339230385034577592362285413844090291324004188441761308946598113155622594470101813896717827793848959466897581352096411465349497482536667678806755963003594269964471645756032079320277704458853069418529971942575852094104790310066847069670325402373020833841876608040386282714261061594335369930639258387475450755168768340794098892705854617614243440707489160798676951449013008341993381732131984227333099392676925782457904480246684111901862252629606700297054325514002833036878077927320486093138287205556063008293376772433391714142630719204798033902765988430555164772582267966219041116996440539611674000601957205887125099421470042532656876785243560501045136171320218415143037548196562948415694940370010976819108894029684652176921453433190337467467439543014735696442815741548747702293908336908985277965476394250069229149180150682997008263874224970008677192011419847537688924343215111577053147822731803738472808685565730387296072637475856439347581597856449683577027257576415569686496716232166624488382627415690912163227932292317464331287402981216293429621218940245902331369206273758387594129522029813705571334915488514574423717032381934766275456215930679664254635000985990088857302736127787308242824260325470176425887795269807370383222625206712586758031401651612445507809930006945003100158708722576506337449252473023364306115312347771983684758483905499993546165300115824998346470933349306355992111511854360424339719752241094774221470024725008754260639339123535935395369604834231422742026526593608645437773732737340639414276366719135140139619264386085915702676818624745313860140935190183792177611068021569164499918574037150376482954594180535425247884719895545197806754060579022905823177907142912487939450490835317177502750318235743892921322738828536361107159384762191716829657741664961945528957725126050184313153569688248698712439231614999620828858947533263577771674833085946996572712193762889513560348639053641170588896653043908598903555365149561211191470230120731319008354242244302286812736403476357021604922802357384689171568314660315221930302536848081930622543291880613573247100469750473998324933106345714410176138736434547857673738984895674926675722726635872377765727031319309249702985669047074463586960806921003800374225019759282334308009367792331912865955086108861120741379037842912165510997478992006052676867774966799496752583581866257935485610692844574854628449194090808829084742021357462913639856068465787990532673010600205468426509964560553554935157586604132565199856157848210918982178980095756934507324717987022565055393387357632719824784593459764392772029174788244871203394912193045917777516833911695517756040814887416374656407835901621235075533435508686899159645856809023026620178447065983821919778128506207425520891952097070004849135013350297579692482273725032845494503105379989250316263400521395561956989656768507496725540542294995431881558926029531518968265087462417000823697746746776548232226800794800142751776501957376491014276981143934918369329932427888214868153578683648580785013860429323993824849223337605028255415063337065465216386571127301713738908601696807697895191386352130203238147150771101431768924282377768128234363953161212267726752248256619632318099994653730109821052864397198271841210345494903348900088625423276385831640814794822769926307235167930155467349891850521835125234414389422765750919904715878343527302768510636638650820425644388411572694009266853453546326636608262484968826961152888397079218381669647347437831598385028448986282822095841237959151680179414410531988958175111441916576314185007692323688002201487709687475218817315597583827349920185235890237646848875494010553416276352446323043360739529672222463604902641640778195698333214453999124774875813151340968915370601331455884133177085449452700302781315085796423576630906837490998849854579645012417417410725851316361694206620948098145976261864818914009232990957229611688393507636568492448654625946960048700159184093046376905918764142044531267520130925428785866522524222978722360350767192661891413674114543647698884570929652984997282849866692335796445426431456323511904478115398437648145621578154569702869291418433549303996524770365521806475706038919985144625039583556744927239519719881835231158970990928483074709113874828246793476868108725594313317866049379027518901105674744308567457083663203347523172401128073181551488238725236801591882207149390324975870354434475332533662150939244173226570770173467522557507190799848307594920175542038283288444097433304461901110683201102993266310889996878376451806143286661186989850922706531831219078871711488889436868901265444667763988782049150553926121305319777519528394987552990557198745658798896900176073513421115742229192485881880179410848271335587896532237685230467415081995450847304156262431282933134350441251001706307425823381687992828157611631217896188076308844428001218167474176295556385549631396590011591473348763241889869892519096275493973888500054279729367865760464710068697950339475397947976840987761144502463515670270449977105611334814516897014195566914505280486207388614874723906637808757256368027260928007962815476464271473201037546013670305371261420383979040881148983345289061533428107074749517324444888002725043537365442850393344401208730640814680650866001537375596885221586199601783136922857778666921449959525695968461700332814459217639360788498649848737801932534546760215770329120195070894817871266521847966599043802104558455558240113360894224791422561980310640389060477588394722625925125085079203433991939851511015274999701241052760405442004790692863321020835492346789888222654285828384235023157385203832979147730883227995198569086603327459196157150314868790874777563159832073479359819522113727604088122030492037664552314741599241392921687409562894990700601616401132151251627178280253297489928770932001714074161280774406349568829844155943099107835943925577362856982853585146926620644490114393381747180930068704643386289520003035224241592391931577561317503463974381387219145581941150075349739235445554989940756661596399324487402013716696284558958661746820865646755271781530030808173448727992057828893221802639627075430457992845294070536506800345606169755876601314634718722851054910242690662854231071258698020590273949972893094541692473118795578563209406719473770590210999950300771195604214561489009297994857358614229879695713401394152710274054683001113715957454311087562975402229317090908460094792184473317675037036366520999885667665334432897260976806985270392762765409842137267919929143522360061257649617508871196263155746846698493858718722112841312151696467164932107464418431526342839198321055733306995942238296375689219988441960825708272089931288526813797505009544779764605724814125441502100533504374308917078778328920080190088864969410895004951509472500449319368987554376787970387215182844531575746483984818555323033889008114729691735047629941579013391399522639148573310180804430222787587638916434251463477055585153797748572837293435406307929568135850557509135552751277039569344908232487298850\n"
]
}
],
"source": [
"import itertools\n",
"#implémentation au niveau de l'itérateur de boucle\n",
"# dommage, pas de @itimeout for ... \n",
"try:\n",
" for i in decorators.itimeout(itertools.count(),t):\n",
" n=mfib(i)\n",
"except decorators.TimeoutError:\n",
" print('en %d secondes, on peut calculer %d termes'%(t,i))\n",
" print('le dernier est',n)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a id=\"deco2\"></a>\n",
"### Hey mais alors ..."
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Valeur str A , double = AA statique\n"
]
}
],
"source": [
"class Valeur:\n",
" def __init__(self,v):\n",
" self.v=v\n",
" self.__name__=type(v).__name__\n",
" @property\n",
" def double(self):\n",
" return self.v*2\n",
" \n",
" def type(self):\n",
" return self.__name__\n",
" \n",
" @classmethod\n",
" def classe(self): # self désigne ici la classe !\n",
" return self.__name__\n",
" \n",
" @staticmethod\n",
" def statique():\n",
" return 'statique'\n",
" \n",
"v=Valeur('A')\n",
"print(v.classe(), v.type(), v.v, \", double =\",v.double, v.statique())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"... Oui ! certains décorateurs sont prédéfinis et étendent le langage !\n",
"\n",
"il n'y a pas (encore ?) de librairie standard de décorateurs, mais il y en a [pas mal ici](https://wiki.python.org/moin/PythonDecoratorLibrary)\n",
"\n",
"Guido van Rossum a par exemple proposé les \"[multimethodes](https://www.artima.com/weblogs/viewpost.jsp?thread=101605)\" :"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2/3\n",
"7793533013102485/9007199254740992\n",
"a / b\n"
]
},
{
"ename": "TypeError",
"evalue": "unsupported argument types (<class 'str'>, <class 'int'>)",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-45-8e7ed8cd920d>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m 14\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmath\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0me\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mmath\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpi\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 15\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m'b'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 16\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m<ipython-input-45-8e7ed8cd920d>\u001b[0m in \u001b[0;36mf\u001b[1;34m(a, b)\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[1;34m\"%s / %s\"\u001b[0m\u001b[1;33m%\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 11\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"unsupported argument types (%s, %s)\"\u001b[0m \u001b[1;33m%\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 12\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mTypeError\u001b[0m: unsupported argument types (<class 'str'>, <class 'int'>)"
]
}
],
"source": [
"from fractions import Fraction\n",
"\n",
"def f(a, b):\n",
" if isinstance(a, int) and isinstance(b, int):\n",
" return Fraction(a,b) \n",
" elif isinstance(a, float) and isinstance(b, float):\n",
" return Fraction(a/b)\n",
" elif isinstance(a, str) and isinstance(b, str):\n",
" return \"%s / %s\"%(a,b)\n",
" else:\n",
" raise TypeError(\"unsupported argument types (%s, %s)\" % (type(a), type(b)))\n",
" \n",
"print(f(2,3))\n",
"print(f(math.e,math.pi))\n",
"print(f('a','b'))\n",
"print(f('a',2))"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2/3\n",
"7793533013102485/9007199254740992\n",
"a / b\n"
]
},
{
"ename": "TypeError",
"evalue": "unsupported argument types (<class 'str'>, <class 'int'>)",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-46-95b92003cab4>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m 16\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmath\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0me\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mmath\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpi\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 17\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m'b'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 18\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'a'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m<ipython-input-45-8e7ed8cd920d>\u001b[0m in \u001b[0;36mf\u001b[1;34m(a, b)\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[1;34m\"%s / %s\"\u001b[0m\u001b[1;33m%\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 11\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"unsupported argument types (%s, %s)\"\u001b[0m \u001b[1;33m%\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtype\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 12\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mTypeError\u001b[0m: unsupported argument types (<class 'str'>, <class 'int'>)"
]
}
],
"source": [
"from Goulib.decorators import multimethod\n",
"\n",
"@multimethod(int, int)\n",
"def foo(a, b):\n",
" return Fraction(a,b) \n",
"\n",
"@multimethod(float, float)\n",
"def foo(a, b):\n",
" return Fraction(a/b)\n",
"\n",
"@multimethod(str, str)\n",
"def foo(a, b):\n",
" return \"%s / %s\"%(a,b)\n",
"\n",
"print(f(2,3))\n",
"print(f(math.e,math.pi))\n",
"print(f('a','b'))\n",
"print(f('a',2))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}