Le module operator en Python 9


Le module operator contient des fonctions qui font ce que font les opérateurs. Exemple :

>>> from operator import add, gt
>>> add(1, 1) # fait en fonction ce que ferait 1 + 1
>>> gt(1, 2) # fait en fonction ce que ferait 1 > 2

On a donc dans le module operator de quoi remplacer les opérateurs +, <, not, etc. par des fonctions.

Les opérateurs or et and n'ont pas de fonctions équivalentes car ils short circuitent, ce que ne peut pas faire une fonction. operator.and_ et operator.or_ sont des fonctions pour & et |, par pour or et and.

Il y a des opérateurs qu'on oublie souvent, comme l'opérateur []. Le module operator contient des fonctions pour lui également.

>>> from operator import getitem, getslice
>>> lst = [1, 2, 3]
>>> lst[0]
1
>>> getitem(lst, 0)
1
>>> lst[:2]
[1, 2]
>>> getslice(lst, 0, 2)
[1, 2]

On oublie parfois l'opérateur ".". Il y a une fonction builtin pour ça:

>>> class Classe(object):
...     def __init__(self, type):
...         self.type = type
...         
>>> c = Classe('cm2')
>>> c.type
'cm2'
>>> getattr(c, 'type')
'cm2'

Mais le plus étonnant dans le module operator, c'est qu'il a des fonctions qui retournent... des fonctions.

>>> from operator import itemgetter
>>> getfirst = itemgetter(0)
>>> getfirst([1, 2, 3])
1
>>> getfirst('abc')
'a'
>>> getsecond = itemgetter(1)
>>> getsecond([1, 2, 3])
2
>>> getsecond("abc")
'b'
>>> getlast = itemgetter(-1)
>>> getlast(range(100))
99

Ici on créer des fonctions qui ont pour seul triste but dans la vie de retourner l'élément à l'index donné. getfirst retournera l'élément 0. getsecond retournera l'élément à l'index 1. getlast retournera l'élément à l'index -1. itemgetter() est un créateur de fonction qui ne font que ça: retourner un seul élément.

On pourrait aussi le faire avec une lambda:

>>> getfirst = lambda x: x[0]
>>> getfirst([1, 2, 3])
1

On a le même chose de chose pour les attributs. attrgetter est une fonction qui crée une fonction. La fonction créée retourne toujour la valeur du même attribut.

>>> from operator import attrgetter
>>> gettype = attrgetter('type') # crée une fonction qui ...
>>> gettype(Classe('cm2')) # ... retourne la valeur de l'attribut 'type'
'cm2'
>>> gettype(Classe('6eme'))
'6eme'

On pourrait aussi le faire avec une lambda:

>>> gettype = lambda x: x.type
>>> gettype(Classe('6eme'))
'6eme'

Ces fonctions n'ont pas l'air utile comme ça, mais en Python les fonctions peuvent être passées en paramètres. Cela permet donc de faire des choses intéressante comme de l'injection de dépendance. C'est notamment ainsi que fonctionne key dans sorted().

Bref, jetez un coup d'oeil à operator, il est plein comme un oeuf:

>>> from operator import <tab>
abs               delitem           getslice          ilshift           ior               isSequenceType    le                neg               sequenceIncludes
add               delslice          gt                imod              ipow              is_               lshift            not_              setitem
and_              div               iadd              imul              irepeat           is_not            lt                or_               setslice
attrgetter        eq                iand              index             irshift           isub              methodcaller      pos               sub
concat            floordiv          iconcat           indexOf           isCallable        itemgetter        mod               pow               truediv
contains          ge                idiv              inv               isMappingType     itruediv          mul               repeat            truth
countOf           getitem           ifloordiv         invert            isNumberType      ixor              ne                rshift            xor

9 thoughts on “Le module operator en Python

  • JeromeJ

    J’ai récemment trouvé quelque chose du même goût (je trouve).

    Ça fait partie du module functools (qui a plusieurs truc chouettes dont les lru_wrapper à partir de 3.2, etc), il s’agit de functools.partial.

    Si vous avez une fonction qui prend plusieurs paramètres mais que vous voulez faire en sorte qu’un des paramètre aient une (autre) valeur par défaut, vous pouvez faire.

    base2 = functools.partial(int, base=2)
    base2(10)

    http://docs.python.org/3/library/functools.html

  • Pocreau thomas

    Pour répondre à Zariko.

    Je préfère le terme “évaluation paresseuse” à “short-circuite”.

  • Sam Post author

    Les deux notions ne sont pas égales. Un short-circuit et une évaluation paresseuse avec un retour le plus tôt possible, alors qu’on peut appliquer l’évaluation paresseuses à des choses très différences comme les générateurs. C’est une notion plus large que le short-circuit.

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.