Sam & Max » for http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Une boucle while de moins 5 http://sametmax.com/une-boucle-while-de-moins/ http://sametmax.com/une-boucle-while-de-moins/#comments Tue, 23 Jun 2015 10:04:55 +0000 http://sametmax.com/?p=16427 Si vous devez retenir un truc de la partie Python de ce blog, c’est qu’en Python, l’itération est tout.

Du coup, on utilise pas beaucoup while, à part dans quelques cas particuliers.

Le cas d’école, c’est la lecture d’un fichier octet par octet.

Imaginez, vous créez un petit array de float écrits en 64 bits :

>>> import numpy as np
>>> a = np.sin(np.linspace(2.0, 3.0, num=100))
>>> a.dtype
dtype('float64')

Vous sauvegardez tout ça dans un fichier :

>>> a.tofile('/tmp/data')

Si vous voulez lire le fichier hors de numpy, il faut le charger float par float, donc le lire 64 bits par 64 bits soit par groupes de 8 octets.

La méthode canonique :

with open('/tmp/data', 'rb') as f:
    while True:
        nombre = f.read(8)
        if not nombre:
            break
        # faire un truc avec le nombre

Mais il existe une autre manière de faire cela, moins connue : utiliser iter().

with open('/tmp/data', 'rb') as f:
    for nombre in iter(lambda: f.read(8), b''):
        # faire un truc avec nombre

Cela marche car iter(), parmi ses nombreuses fonctionnalités, accepte un callable en paramètre (ici notre lambda), et va l’appeler jusqu’à ce que celui-ci retourne une valeur dite “sentinelle” (ici notre second paramètre).

]]>
http://sametmax.com/une-boucle-while-de-moins/feed/ 5
Sortir de plusieurs boucles for imbriquées en Python 9 http://sametmax.com/sortir-de-plusieurs-boucles-for-imbriquees-en-python/ http://sametmax.com/sortir-de-plusieurs-boucles-for-imbriquees-en-python/#comments Tue, 01 Jan 2013 19:27:41 +0000 http://sametmax.com/?p=3962 break permet de sortir d'une boucle for abruptement. Mais une seule. Parfois on a 3, 4 boucles imbriquées, et on aimerait tellement sortir de toutes d'un coup. Ce que je vais vous montrer est mal. Mais c'est tellement bon.]]> Le mot clé break permet de sortir d’une boucle for abruptement. Mais une seule. Parfois on a 3, 4 boucles imbriquées, et on aimerait tellement sortir de toutes d’un coup.

Ce que je vais vous montrer est mal. Mais c’est tellement bon.

# on fait une exception qui hérite de StopIteration car c'est ce qui est utilisé
# de toute façon pour arrêter une boucle
class MultiStopIteration(StopIteration):
    # la classe est capable de se lever elle même comme exception
    def throw(self):
        raise self
 
 
@contextmanager
def multibreak():
    # le seul boulot de notre context manager c'est de donne le moyen de lever
    # l'exception tout en l'attrapant
    try:
        yield MultiStopIteration().throw
    except MultiStopIteration:
        pass

En gros on se créé un petit context manager, dont le seul but est de créer une exception qui va remonter en pêtant toutes les boucles. Je vous avais dit que c’était mal

Ca s’utilise comme ça:

>>> with multibreak() as stop:
...     for x in range(1, 4):
...         for z in range(1, 4):
...             for w in range(1, 4):
...                 print w
...                 if x * z * w == 2 * 2 * 2:
...                     print 'stop'
...                     stop() # appel MultiStopIteration().throw()
...
1
2
3
1
2
3
1
2
3
1
2
3
1
2
stop

Je vous avais dit que ça serait bon.

A part le fait que ce n’est pas très rapide au moment du bubbling de l’exception sur 3 blocks, il n’y a aucun danger ou side-effect. On triche en fait à peine, car le mécanisme interne des boucles en Python utilise de toute façon déjà une exception (StopIteration) pour dire à une boucle quand s’arrêter.

Bref, encore une victoire de connard.

]]>
http://sametmax.com/sortir-de-plusieurs-boucles-for-imbriquees-en-python/feed/ 9
Dis papa, dis papa, dis-moi, dis-moi. Comment c’est fait dans une boucle for ? 14 http://sametmax.com/dis-papa-dis-papa-dis-moi-dis-moi-comment-cest-fait-dans-une-boucle-for/ http://sametmax.com/dis-papa-dis-papa-dis-moi-dis-moi-comment-cest-fait-dans-une-boucle-for/#comments Mon, 31 Dec 2012 16:10:08 +0000 http://sametmax.com/?p=3953 Dis papa, dis papa, dis-moi, dis-moi. Comment c’est fait dans une boucle for ?

C’est pas compliquéééééééééééé, j’vais tout t’expliquuuuuerrrrrrrrrr.

C´est le p´tit zinzin qui passe par ici:

>>> class MonIterable(object): # faisons notre propre itérable
...
...     def __init__(self):
...         self.values = [1, 2]
...
...     def __iter__(self): # ('for' appelle __iter__ automatiquement)
...         return self # __iter__ doit renvoyer un iterateur, ici nous-même
...
...     def next(self): # chaque tour de boucle, for appelle next()
...         if self.values: # qui retourne une des valeus de self.values
...             return self.values.pop() # en l'enlevant de la liste initiale
...         raise StopIteration() # si il y en a plus, il dit stop !
...

Et qui va toucher le p´tit machinnnnnnnnnnnnnnnnnnnnnnnnn !

>>> for x in MonIterable(): # ceci appelle next() jusqu'à StopIteration
...    print x
2
1

Et le p´tit machin qui repasse par là:

>>> iterateur = iter(MonIterable()) # Voilà ce que ça donne à la main
>>> iterateur.next()
2
>>> iterateur.next()
1
>>> iterateur.next() # l'exception: mécanisme naturel de Python pour stopper une boucle !
Traceback (most recent call last):
  File "<pyshell#9>", line 19, in <module>
    iterateur.next()
  File "<pyshell#9>", line 14, in next
    raise StopIteration()
StopIteration

Et qui fait marcher ce p´tit zinzinnnnnnnnnnnnn !

>>> iterateur = iter(range(3)) # c'est pareil pour tous les iterables
>>> iterateur.next() # un iterateur est juste un truc avec une méthode next()
0
>>> iterateur.next() # next() doit retourner la prochain valeur de l'iterable
1
>>> iterateur.next() # un itérateur itère donc sur un iterable
2
>>> iterateur.next() # jusqu'à la fin, où il lève StopIteratino
Traceback (most recent call last):
  File "<ipython-input-19-6c9f9efdd35c>", line 1, in <module>
    iterateur.next()
StopIteration

Ah bon ?

]]>
http://sametmax.com/dis-papa-dis-papa-dis-moi-dis-moi-comment-cest-fait-dans-une-boucle-for/feed/ 14