Views VS generators


Avec Python 2.7, un outil appelé les “views” (les “vues”) est apparu. Une vue est juste un enrobage qui permet de voir un objet d’une certaine façon, et de le manipuler d’une certaine façon (avec une autre API), sans changer cet objet.

Les vues ont surtout été notables pour leur apparition dans les dictionnaires avec Python 2.7:

    >>> scores = {"sam": 1, "max": 0}
    >>> scores.items() # retourne une lsite
    [('max', 0), ('sam', 1)]
    >>> scores.iteritems() # retourne un générateur
    <dictionary-itemiterator object at 0x7f8782a26628>
    >>> list(scores.iteritems()) # sans views
    [('max', 0), ('sam', 1)]
    >>> scores.viewsitems() # avec views
    Traceback (most recent call last):
      File "<ipython-input-12-dc0b08011047>", line 1, in <module>
        scores.viewsitems() # avec views
    AttributeError: 'dict' object has no attribute 'viewsitems'
 
    >>> scores.viewitems() # retourne une vue
    dict_items([('max', 0), ('sam', 1)])

Néanmoins personne ne les a vraiment utilisé, et c’est un tort. Elles sont en effet très performantes, et pour cette raison sont retournées par défaut avec items() en Python 3.

En effet, les vues ne sont qu’un enrobage : elles ne contiennent rien, et donc ne prennent pas beaucoup mémoire, tout comme les générateurs.

Mais contrairement aux générateurs, les vues ne se vident pas et peuvent exposer une API plus complète que les générateurs, comme par exemple déclarer une taille :

>>> items = scores.iteritems()
>>> list(items)
[('max', 0), ('sam', 1)]
>>> list(items) # woops
[]
>>> items = scores.viewitems()
>>> list(items)
[('max', 0), ('sam', 1)]
>>> list(items)
[('max', 0), ('sam', 1)]
>>> len(scores.iteritems()) # nope
Traceback (most recent call last):
  File "<ipython-input-21-9c7f250da51d>", line 1, in <module>
    len(scores.iteritems())
TypeError: object of type 'dictionary-itemiterator' has no len()
 
>>> len(scores.viewitems())
2

Alors certes, on ne peut pas mettre des vues partout, et les générateurs restent utiles. Mais quand il est possible de les utiliser, et à moins d’avoir besoin d’une liste afin de modifier les valeurs in place, il n’y pas de raison de ne pas le faire : c’est le meilleur des deux mondes.

6 thoughts on “Views VS generators

  • jpcw

    Un autre avantage très pratique des vues est qu’elles restent à jour en gardant une référence sur le dict

    >>> scores = {"sam": 1, "max": 0}
    >>> keys = scores.keys()
    >>> keys
    ['max', 'sam']
    >>> v_keys = scores.viewkeys()
    >>> v_keys
    dict_keys(['max', 'sam'])
    >>> scores['xoxo'] = 2
    >>> 'xoxo' in v_keys
    True
  • Ryzz

    Bon ok, on a des views dans les dicos. La question que je me pose, c’est: «est-ce qu’on peut implémenter une view sur un objet quelconque ?».

  • Sam Post author

    En fait c’est juste un pattern “façade”, donc techniquement tu code ta fascade, tu l’appele “vue” et pouf :)

  • kontre

    Pour info, numpy utilise beaucoup les vues pour ses tableaux, ce qui rend certaines opérations ultra-rapides (une transposition, par exemple).

  • ZZelle

    donc iterXXX renvoie un iterator et viewXXX renvoie un iterable qui implémente len ?

  • Sam Post author

    @ZZelle: c’est l’idée, mais l’itérable implémente plus que \_\len\_\_ : il est par exemple comparable avec == avec un objet du même type.

Comments are closed.

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