{"id":714,"date":"2010-08-11T11:54:50","date_gmt":"2010-08-11T09:54:50","guid":{"rendered":"http:\/\/j-mad.com\/blog\/?p=714"},"modified":"2010-08-13T12:50:20","modified_gmt":"2010-08-13T10:50:20","slug":"petit-tour-du-cote-des-itertools-billet-sans-nucleaire-dedans-promis","status":"publish","type":"post","link":"https:\/\/j-mad.com\/blog\/2010\/08\/11\/petit-tour-du-cote-des-itertools-billet-sans-nucleaire-dedans-promis\/","title":{"rendered":"Petit tour du cot\u00e9 des itertools, billet sans nucl\u00e9aire dedans, promis"},"content":{"rendered":"<p>Le module <a href=\"http:\/\/docs.python.org\/library\/itertools.html\">itertools<\/a> est un module bien pratique auquel on ne pense pas assez souvent. En tout cas auquel, moi, je ne pense pas assez souvent. Et pourtant, il peut grandement simplifier pas mal de ligne de code, dans un bon nombre de situation. Il faut juste savoir que les fonctions qu&#8217;il propose existe.<\/p>\n<p>Ce billet a donc 2 objectifs, vous faire d\u00e9couvrir les itertools (je ne vais pas lister toutes les fonctions juste celles dont je devrais me servir plus souvent et que j&#8217;oublie) et me permettre de ne pas oublier que je pourrais les utiliser.<\/p>\n<p>Point important\u00a0: Un certain nombre des itertools permettent de g\u00e9rer les iterateur infinis, ce que ne permettent pas les fonctions &#8216;normales&#8217; comme map par exemple (qui renvoie une sortie compl\u00e9tement calcul\u00e9e, ce qui est par d\u00e9finition impossible avec un iterateur infini).<\/p>\n<p>Pr\u00e9cision\u00a0: les exemples de code sont ceux fournis par la doc officielle des itertools<\/p>\n<h2>itertools.chain (*iterables)<\/h2>\n<p>permet d&#8217;avoir un iterateur qui retourne tout les \u00e9l\u00e9ments du premier iterable pass\u00e9 en param\u00e8tre, puis du second, puis du troisi\u00e8me, etc etc&#8230; Bien pratique pour a\u00e9rer son code.<\/p>\n<div class=\"codecolorer-container python default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"python codecolorer\"><span class=\"kw1\">def<\/span> chain<span class=\"br0\">&#40;<\/span>*iterables<span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"co1\"># chain('ABC', 'DEF') --&gt; A B C D E F<\/span><br \/>\n<span class=\"kw1\">for<\/span> it <span class=\"kw1\">in<\/span> iterables:<br \/>\n<span class=\"kw1\">for<\/span> element <span class=\"kw1\">in<\/span> it:<br \/>\n<span class=\"kw1\">yield<\/span> element<\/div><\/div>\n<p>Depuis python 2.6, il existe une classmethod de chain, from_iterable(iterable) qui ne prend qu&#8217;un argument, un iterable contenant tout les iterables.<\/p>\n<div class=\"codecolorer-container python default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"python codecolorer\"><span class=\"sy0\">@<\/span><span class=\"kw2\">classmethod<\/span><br \/>\n<span class=\"kw1\">def<\/span> from_iterable<span class=\"br0\">&#40;<\/span>iterables<span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"co1\"># chain.from_iterable(['ABC', 'DEF']) --&gt; A B C D E F<\/span><br \/>\n<span class=\"kw1\">for<\/span> it <span class=\"kw1\">in<\/span> iterables:<br \/>\n<span class=\"kw1\">for<\/span> element <span class=\"kw1\">in<\/span> it:<br \/>\n<span class=\"kw1\">yield<\/span> element<\/div><\/div>\n<h2>itertools.compress(data, selectors)<\/h2>\n<p>compress n&#8217;est disponible qu&#8217;en python 2.7. Cette fonction retourne un iterateur contenant que uniquement les valeurs de data auxquelles correspondent un \u00e9l\u00e9ment \u00e9valu\u00e9 \u00e0 True dans le selectors. Compress s&#8217;arr\u00eate d\u00e8s que data ou selectors est vide.<\/p>\n<div class=\"codecolorer-container python default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"python codecolorer\"><span class=\"kw1\">def<\/span> compress<span class=\"br0\">&#40;<\/span>data<span class=\"sy0\">,<\/span> selectors<span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"co1\"># compress('ABCDEF', [1,0,1,0,1,1]) --&gt; A C E F<\/span><br \/>\n<span class=\"kw1\">return<\/span> <span class=\"br0\">&#40;<\/span>d <span class=\"kw1\">for<\/span> d<span class=\"sy0\">,<\/span> s <span class=\"kw1\">in<\/span> izip<span class=\"br0\">&#40;<\/span>data<span class=\"sy0\">,<\/span> selectors<span class=\"br0\">&#41;<\/span> <span class=\"kw1\">if<\/span> s<span class=\"br0\">&#41;<\/span><\/div><\/div>\n<h2>itertools.count(start=0, step=1)<\/h2>\n<p>Cette fonction bien que pr\u00e9sente depuis longtemps a droit \u00e0 quelques modifications dans python 2.7. Count gagne en effet l&#8217;argument step et la possibilit\u00e9 d&#8217;it\u00e9rer sur des arguments non integer.<\/p>\n<div class=\"codecolorer-container python default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"python codecolorer\"><span class=\"kw1\">def<\/span> count<span class=\"br0\">&#40;<\/span>start<span class=\"sy0\">=<\/span><span class=\"nu0\">0<\/span><span class=\"sy0\">,<\/span> step<span class=\"sy0\">=<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"co1\"># count(10) --&gt; 10 11 12 13 14 ...<\/span><br \/>\n<span class=\"co1\"># count(2.5, 0.5) -&gt; 3.5 3.0 4.5 ...<\/span><br \/>\nn <span class=\"sy0\">=<\/span> start<br \/>\n<span class=\"kw1\">while<\/span> <span class=\"kw2\">True<\/span>:<br \/>\n<span class=\"kw1\">yield<\/span> n<br \/>\nn +<span class=\"sy0\">=<\/span> step<\/div><\/div>\n<h2>itertools.dropwhile(predicate, iterable)<\/h2>\n<p>Construit un iterateur qui ne renvoie aucun \u00e9l\u00e9ment de l&#8217;iterable tant que le pr\u00e9dicat est vrai, ensuite, tout les \u00e9l\u00e9ments de l&#8217;iterable sont renvoy\u00e9s<\/p>\n<div class=\"codecolorer-container python default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"python codecolorer\"><span class=\"kw1\">def<\/span> dropwhile<span class=\"br0\">&#40;<\/span>predicate<span class=\"sy0\">,<\/span> iterable<span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"co1\"># dropwhile(lambda x: x&lt;5, [1,4,6,4,1]) --&gt; 6 4 1<\/span><br \/>\niterable <span class=\"sy0\">=<\/span> <span class=\"kw2\">iter<\/span><span class=\"br0\">&#40;<\/span>iterable<span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"kw1\">for<\/span> x <span class=\"kw1\">in<\/span> iterable:<br \/>\n<span class=\"kw1\">if<\/span> <span class=\"kw1\">not<\/span> predicate<span class=\"br0\">&#40;<\/span>x<span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"kw1\">yield<\/span> x<br \/>\n<span class=\"kw1\">break<\/span><br \/>\n<span class=\"kw1\">for<\/span> x <span class=\"kw1\">in<\/span> iterable:<br \/>\n<span class=\"kw1\">yield<\/span> x<\/div><\/div>\n<h2>itertools.takewhile(predicate, iterable)<\/h2>\n<p>Construit un iterateur qui, tant que le pr\u00e9dicat est vrai, renvoie les \u00e9l\u00e9ments de l&#8217;iterable.<\/p>\n<div class=\"codecolorer-container python default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"python codecolorer\"><span class=\"kw1\">def<\/span> takewhile<span class=\"br0\">&#40;<\/span>predicate<span class=\"sy0\">,<\/span> iterable<span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"co1\"># takewhile(lambda x: x&lt;5, [1,4,6,4,1]) --&gt; 1 4<\/span><br \/>\n<span class=\"kw1\">for<\/span> x <span class=\"kw1\">in<\/span> iterable:<br \/>\n<span class=\"kw1\">if<\/span> predicate<span class=\"br0\">&#40;<\/span>x<span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"kw1\">yield<\/span> x<br \/>\n<span class=\"kw1\">else<\/span>:<br \/>\n<span class=\"kw1\">break<\/span><\/div><\/div>\n<h2>itertools.ifilter(predicate, iterable) et itertools.ifilterfalse(predicate, iterable)<\/h2>\n<p>Construit un iterateur qui ne renvoie que les \u00e9l\u00e9ments pour lesquels le pr\u00e9dicat est respectivement True ou False. Si predicate est \u00e0 None, l&#8217;iterateur renvoie les \u00e9l\u00e9ments respectivement True ou False.<\/p>\n<div class=\"codecolorer-container python default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"python codecolorer\"><span class=\"kw1\">def<\/span> ifilter<span class=\"br0\">&#40;<\/span>predicate<span class=\"sy0\">,<\/span> iterable<span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"co1\"># ifilter(lambda x: x%2, range(10)) --&gt; 1 3 5 7 9<\/span><br \/>\n<span class=\"kw1\">if<\/span> predicate <span class=\"kw1\">is<\/span> <span class=\"kw2\">None<\/span>:<br \/>\npredicate <span class=\"sy0\">=<\/span> <span class=\"kw2\">bool<\/span><br \/>\n<span class=\"kw1\">for<\/span> x <span class=\"kw1\">in<\/span> iterable:<br \/>\n<span class=\"kw1\">if<\/span> predicate<span class=\"br0\">&#40;<\/span>x<span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"kw1\">yield<\/span> x<\/div><\/div>\n<h2>itertools.imap(function, *iterables)<\/h2>\n<p>Renvoie un iterateur qui applique function en utilisant les iterables comme argument. Si function est None, les arguments sont retourn\u00e9s sous la forme d&#8217;un tuple. Imap s&#8217;arr\u00eate lorsqu&#8217;elle atteint la fin du plus petit des iterables. Imap est utile lorsque l&#8217;on utilise des iterateur infinie qui provoque une erreur avec map.<\/p>\n<div class=\"codecolorer-container python default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"python codecolorer\"><span class=\"kw1\">def<\/span> imap<span class=\"br0\">&#40;<\/span>function<span class=\"sy0\">,<\/span> *iterables<span class=\"br0\">&#41;<\/span>:<br \/>\n<span class=\"co1\"># imap(pow, (2,3,10), (5,2,3)) --&gt; 32 9 1000<\/span><br \/>\niterables <span class=\"sy0\">=<\/span> <span class=\"kw2\">map<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw2\">iter<\/span><span class=\"sy0\">,<\/span> iterables<span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"kw1\">while<\/span> <span class=\"kw2\">True<\/span>:<br \/>\nargs <span class=\"sy0\">=<\/span> <span class=\"br0\">&#91;<\/span>next<span class=\"br0\">&#40;<\/span>it<span class=\"br0\">&#41;<\/span> <span class=\"kw1\">for<\/span> it <span class=\"kw1\">in<\/span> iterables<span class=\"br0\">&#93;<\/span><br \/>\n<span class=\"kw1\">if<\/span> function <span class=\"kw1\">is<\/span> <span class=\"kw2\">None<\/span>:<br \/>\n<span class=\"kw1\">yield<\/span> <span class=\"kw2\">tuple<\/span><span class=\"br0\">&#40;<\/span>args<span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"kw1\">else<\/span>:<br \/>\n<span class=\"kw1\">yield<\/span> function<span class=\"br0\">&#40;<\/span>*args<span class=\"br0\">&#41;<\/span><\/div><\/div>\n<h2>les autres i-versions des fonctions classiques.<\/h2>\n<p>Comme l&#8217;on trouve imap, il existe aussi izip, izip_longest et islice,<\/p>\n<p>Parmi les autres fonctions il y a des fonctions de combinaisons, de calcul, de cycle, de groupby, mais celles l\u00e0, vous les trouverez sur la <a title=\"documentation itertools\" href=\"http:\/\/docs.python.org\/library\/itertools.html\">doc officielle<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Le module itertools est un module bien pratique auquel on ne pense pas assez souvent. En tout cas auquel, moi, je ne pense pas assez souvent. Et pourtant, il peut grandement simplifier pas mal de ligne de code, dans un bon nombre de situation. Il faut juste savoir que les fonctions qu&#8217;il propose existe. Ce &hellip; <a href=\"https:\/\/j-mad.com\/blog\/2010\/08\/11\/petit-tour-du-cote-des-itertools-billet-sans-nucleaire-dedans-promis\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Petit tour du cot\u00e9 des itertools, billet sans nucl\u00e9aire dedans, promis<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[5],"tags":[98],"class_list":["post-714","post","type-post","status-publish","format-standard","hentry","category-python","tag-python"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p12cdp-bw","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/posts\/714","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/comments?post=714"}],"version-history":[{"count":7,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/posts\/714\/revisions"}],"predecessor-version":[{"id":718,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/posts\/714\/revisions\/718"}],"wp:attachment":[{"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/media?parent=714"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/categories?post=714"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/j-mad.com\/blog\/wp-json\/wp\/v2\/tags?post=714"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}