IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Annexe C. Trucs et astuces

Annexe C. Trucs et astuces

Chapitre 1. Installation de Python

    Chapitre 2. Votre premier programme Python

    • 2.1. Plonger
      ASTUCE
      Dans l'IDE ActivePython sous Windows, vous pouvez exécuter le programme Python que vous êtes en train d'éditer par File->Run... (Ctrl-R). La sortie est affichée dans la fenêtre interactive.
      ASTUCE
      Dans l'IDE Python sous Mac OS, vous pouvez exécuter un module avec Python->Run window... (Cmd-R) mais il y a une option importante que vous devez activer préalablement. Ouvrez le module dans l'IDE, ouvrez le menu des options des modules en cliquant le triangle noir dans le coin supérieur droit de la fenêtre et assurez-vous que «Run as __main__» est coché. Ce réglage est sauvegardé avec le module, vous n'avez donc à faire cette manipulation qu'une fois par module.
      ASTUCE
      Sur les systèmes compatibles UNIX (y compris Mac OS X), vous pouvez exécuter un programme Python depuis la ligne de commande : python odbchelper.py

    • 2.2. Déclaration de fonctions
      NOTE
      En Visual Basic, les fonctions (qui retournent une valeur) débutent avec function et les sous-routines (qui ne retourne aucune valeur) débutent avec sub. Il n'y a pas de sous-routines en Python. Tout est fonction, toute fonction retourne un valeur (même si c'est None) et toute fonction débute avec def.
      NOTE
      En Java, C++ et autres langage à typage statique, vous devez spécifier les types de données de la valeur de retour d'une fonction ainsi que de chaque paramètre. En Python, vous ne spécifiez jamais de manière explicite le type de quoi que ce soit. En se basant sur la valeur que vous lui assignez, Python gère les types de données en interne.

    • 2.3. Documentation des fonctions
      NOTE
      Les triples guillemets sont aussi un moyen simple de définir une chaîne contenant à la fois des guillemets simples et doubles, comme qq/.../ en Perl.
      NOTE
      Beaucoup d'IDE Python utilisent les doc string pour fournir une documentation contextuelle, ainsi lorsque vous tapez le nom d'une fonction, sa doc string apparaît dans une bulle d'aide. Cela peut être incroyablement utile, mais cette utilité est liée à la qualité de votre doc string.

    • 2.4. Tout est objet
      NOTE
      import en Python est similaire à require en Perl. Une fois que vous importez un module Python, vous accédez à ses fonctions avec module.function. Une fois que vous incluez un module Perl, vous accédez à ses fonctions avec module::function.

    • 2.5. Indentation du code
      NOTE
      Python utilise le retour chariot pour séparer les instructions, deux points et l'indentation pour séparer les blocs de code. C++ et Java utilisent des points-virgules pour séparer les instructions et des accolades pour séparer les blocs de code.

    • 2.6. Test des modules
      NOTE
      A l'instar de C, Python utilise == pour la comparaison et = pour l'assignement. Mais au contraire de C, Python ne permet pas les assignations dans le corps d'une instruction afin d'éviter qu'une valeur soit accidentellement assignée alors que vous pensiez effectuer une simple comparaison.
      ASTUCE
      Avec MacPython, il y a une étape supplémentaire pour que l'astuce if __name__ fonctionne. Ouvrez le menu des options des modules en cliquant le triangle noir dans le coin supérieur droit de la fenêtre et assurez-vous que Run as __main__ est coché.

    Chapitre 3. Types prédéfinis

    • 3.1. Présentation des dictionnaires
      NOTE
      En Python, un dictionnaire est comme une table de hachage en Perl. En Perl, les variables qui stockent des tables de hachage débutent toujours par le caractère %. En Python vous pouvez nommer votre variable comme bon vous semble et Python se chargera de la gestion du typage.
      NOTE
      Un dictionnaire Python est similaire à une instance de la classe Hashtable en Java.
      NOTE
      Un dictionnaire Python est similaire à une instance de l'objet Scripting.Dictionnary en Visual Basic.

    • 3.1.2. Modification des dictionnaires
      NOTE
      Les dictionnaires ne sont liés à aucun concept d'ordonnancement des éléments. Il est incorrect de dire que les élément sont «dans le désordre», il ne sont tout simplement pas ordonnés. C'est une distinction importante qui vous ennuiera lorsque vous souhaiterez accéder aux éléments d'un dictionnaire d'une façon spécifique et reproductible (par exemple par ordre alphabétique des clés). C'est possible, mais cette fonctionalite n'est pas integrée au dictionnaire.

    • 3.2. Présentation des listes
      NOTE
      Une liste en Python est comme un tableau Perl. En Perl, les variables qui stockent des tableaux débutent toujours par le caractère @, en Python vous pouvez nommer votre variable comme bon vous semble et Python se chargera de la gestion du typage.
      NOTE
      Une liste Python est bien plus qu'un tableau en Java (même s'il peut être utilisé comme tel si vous n'attendez vraiment rien de mieux de la vie). Une meilleure analogie serait la classe ArrayList, qui peut contenir n'importe quels objets et qui croît dynamiquement au fur et à mesure que de nouveaux éléments y sont ajoutés.

    • 3.2.3. Recherche dans une liste
      NOTE
      Avant la version 2.2.1, Python n'avait pas de type booléen. Pour compenser cela, Python acceptait pratiquement n'importe quoi dans un contexte requérant un booléen (comme une instruction if), en fonction des règles suivantes :
      • 0 est faux, tous les autres nombres sont vrai.
      • Une chaîne vide ("") est faux, toutes les autres chaînes sont vrai.
      • Une liste vide ([]) est faux, toutes les autres listes sont vrai.
      • Un tuple vide (()) est faux, tous les autres tuples sont vrai.
      • Un dictionnaire vide ({}) est faux, tous les autres dictionnaires sont vrai.
      Ces règles sont toujours valides en Python 2.3.3 et au-delà, mais vous pouvez maintenant utiliser un véritable booléen, qui a pour valeur True ou False. Notez la majuscule, ces valeurs comme tout le reste en Python, sont sensibles à la casse.

    • 3.3. Présentation des tuples
      NOTE
      Les tuples peuvent être convertis en listes et vice-versa. La fonction prédéfinie tuple prends une liste et retourne un tuple contenant les mêmes éléments et la fonction list prends un tuple et retourne une liste. En fait, tuple gèle une liste et list dégèle un tuple.

    • 3.4. Définitions de variables
      NOTE
      Lorsq'une commande est étalée sur plusieurs lignes avec le marqueur de continuation de ligne («\»), les lignes suivantes peuvent être indentées de n'importe qu'elle manière, les règles d'indentation strictes habituellement utilisées en Python ne s'appliquent pas. Si votre IDE Python indente automatiquement les lignes continuées, vous devriez accepter ses réglages par défauts sauf raison impérative.

    • 3.5. Formatage de chaînes
      NOTE
      Le formatage de chaînes en Python utilise la même syntaxe que la fonction C sprintf.

    • 3.7. Jointure de listes et découpage de chaînes
      Attention
      La méthode join ne fonctionne qu'avec des listes de chaînes; elle n'applique pas la conversion de types. La jointure d'une liste comprenant au moins un élément non-chaîne déclenchera une exception.
      ASTUCE
      une_chaîne.split(delimiteur, 1) est une technique utile pour chercher une sous-chaîne dans une chaîne et utiliser tout ce qui précède cette sous-chaîne (le premier élément de la liste retournée) et tout ce qui la suit (le second élément de la liste retournée).

    Chapitre 4. Le pouvoir de l’introspection

    • 4.2. Arguments optionnels et nommés
      NOTE
      La seule chose que vous avez à faire pour appeler une fonction est de spécifier une valeur (d’une manière ou d’une autre) pour chaque argument obligatoire, la manière et l’ordre dans lequel vous le faites ne dépendent que de vous.

    • 4.3.3. Fonctions prédéfinies
      NOTE
      Python est fourni avec d’excellent manuels de référence que vous devriez parcourir de manière exhaustive pour apprendre tous les modules que Python offre. Mais alors que dans la plupart des langages vous auriez à vous référer constamment aux manuels (ou aux pages man, ou pire, à MSDN) pour vous rappeler l’usage de ces modules, Python est en grande partie auto-documenté.

    • 4.7. Utiliser des fonctions lambda
      NOTE
      Les fonctions lambda sont une question de style. Les utiliser n’est jamais une nécessité, partout où vous pouvez les utiliser, vous pouvez utiliser une fonction ordinaire. Je les utilise là où je veux incorporer du code spécifique et non réutilisable sans encombrer mon code de multiples fonctions d’une seule ligne.

    • 4.8. Assembler les pièces
      NOTE
      En SQL, vous devez utiliser IS NULLmethod au lieu de = NULL pour la comparaison d’une valeur nulle. En Python, vous pouvez utiliser aussi bien == None que is None, mais is None est plus rapide.

    Chapitre 5. Les objets et l'orienté objet

    • 5.2. Importation de modules avec from module import
      NOTE
      from module import * en Python est comme use module in Perl. import module en Python est comme require module en Perl.
      NOTE
      from module import * en Python est comme import module.* en Java. import module en Python est comme import module en Java.
      Attention
      Utilisez from module import * avec modération, il rend plus difficile de déterminer l'origine d'une fonction ou d'un attribut, ce qui rend le débogage et la refactorisation plus difficiles.

    • 5.3. Définition de classes
      NOTE
      L'instruction pass de Python est comme une paire d'accolades vide ({}) en Java ou C.
      NOTE
      En Python, l'ancêtre d'une classe est simplement indiqué entre parenthèses immédiatement après le nom de la classe. Il n'y a pas de mot clé spécifique comme extends en Java.

    • 5.3.1. Initialisation et écriture de classes
      NOTE
      Par convention, le premier argument d'une méthode de classe (la référence à l'instance en cours) est appelé self. Cet argument remplit le rôle du mot réservé this en C++ ou Java, mais self n'est pas un mot réservé de Python, seulement une convention de nommage. Cependant, veuillez ne pas l'appeler autre chose que self, c'est une très forte convention.

    • 5.3.2. Quand utiliser self et __init__
      NOTE
      Les méthodes __init__ sont optionnelles, mais quand vous en définissez une, vous devez vous rappeler d'appeler explicitement la méthode __init__ de l'ancêtre de la classe. C'est une règle plus générale : quand un descendant veut étendre le comportement d'un ancêtre, la méthode du descendant doit appeler la méthode de l'ancêtre explicitement au moment approprié, avec les arguments appropriés.

    • 5.4. Instantiation de classes
      NOTE
      En Python, vous appelez simplement une classe comme si c'était une fonction pour créer une nouvelle instance de la classe. Il n'y a pas d'opérateur new explicite comme pour C++ ou Java.

    • 5.5. UserDict : une classe enveloppe
      ASTUCE
      Dans l'IDE ActivePython sous Windows, vous pouvez ouvrir rapidement n'importe quel module dans votre chemin de bibliothèques avec File->Locate... (Ctrl-L).
      NOTE
      Java et Powerbuilder supportent la surcharge de fonction par liste d'arguments : une classe peut avoir différentes méthodes avec le même nom mais avec un nombre différent d'arguments ou des arguments de type différent. D'autres langages (notamment PL/SQL) supportent même la surcharge de fonction par nom d'argument : une classe peut avoir différentes méthodes avec le même nom et le même nombre d'arguments du même type mais avec des noms d'arguments différents. Python ne supporte ni l'une ni l'autre, il n'a tout simplement aucune forme de surcharge de fonction. Les méthodes sont définies uniquement par leur nom et il ne peut y avoir qu'une méthode par classe avec le même nom. Donc si une classe descendante a une méthode __init__, elle redéfinit toujours la méthode __init__ de la classe ancêtre, même si la descendante la définit avec une liste d'arguments différente. Et la même règle s'applique pour toutes les autres méthodes.
      NOTE
      Guido, l'auteur originel de Python, explique la redéfinition de méthode de cette manière : «Les classes dérivées peuvent redéfinir les méthodes de leur classes de base. Puisque les méthodes n'ont pas de privilèges spéciaux lorsqu'elles appellent d'autres méthodes du même objet, une méthode d'une classe de base qui appelle une autre méthode définie dans cette même classe de base peut en fait se retrouver à appeler une méthode d'une classe dérivée qui la redéfini (pour les programmeurs C++ cela veut dire qu'en Python toutes les méthodes sont virtuelles).» Si cela n'a pas de sens pour vous (personellement, je m'y perd complètement) vous pouvez ignorer la question. Je me suis juste dit que je ferais circuler l'information.
      Attention
      Assignez toujours une valeur initiale à toutes les données attributs d'une instance dans la méthode __init__. Cela vous épargera des heures de débogage plus tard, à la poursuite d'exceptions AttributeError pour cause de référence à des attributs non-initialisés (et donc non-existants).
      NOTE
      Dans les versions de Python antérieures à la 2.2, vous ne pouviez pas directement dériver les types de données prédéfinis comme les chaînes, les listes et les dictionnaires. Pour compenser cela, Python est fourni avec des classes enveloppes qui reproduisent le comportement de ces types de données prédéfinis : UserString, UserList et UserDict. En utilisant un mélange de méthodes ordinaires et spéciales, la classe UserDict fait une excellente imitation d'un dictionnaire, mais c'est juste une classe comme les autres, vous pouvez donc la dériver pour créer des classes personalisées semblables à un dictionnaire comme FileInfo. En Python 2.2 et suivant, vous pourriez récrire l'exemple de ce chapitre de manière à ce que FileInfo hérite directement de dict au lieu de UserDict. Cependant, vous devriez quand même lire l'explication du fonctionnement de UserDict au cas où vous auriez besoin d'implémenter ce genre d'objet enveloppe ou au cas où vous auriez à travailler avec une version de Python antérieure à la 2.2.

    • 5.6.1. Lire et écrire des éléments
      NOTE
      Lorsque vous accédez à des données attributs dans une classe, vous devez qualifier le nom de l'attribut : self.attribute. Lorsque vous appelez d'autres méthodes dans une classe, vous devez qualifier le nom de la méthode : self.method.

    • 5.7. Méthodes spéciales avancées
      NOTE
      En Java, vous déterminez si deux variables de chaînes référencent la même zone mémoire à l'aide de str1 == str2. On appelle cela identité des objets et la syntaxe Python en est str1 is str2. Pour comparer des valeurs de chaînes en Java, vous utiliseriez str1.equals(str2), en Python, vous utiliseriez str1 == str2. Les programmeurs Java qui ont appris que le monde était rendu meilleur par le fait que == en Java fasse une comparaison par identité plutôt que par valeur peuvent avoir des difficultés à s'adapter au fait que Python est dépourvu d'un tel piège.
      NOTE
      Alors que les autres langages orientés objet ne vous laissent définir que le modèle physique d'un objet («cet objet a une méthode GetLength»), les méthodes spéciales de Python comme __len__ vous permettent de définir le modèle logique d'un objet («cet objet a une longueur»).

    • 5.8. Attributs de classe
      NOTE
      En Java, les variables statiques (appelées attributs de classe en Python) aussi bien que les variables d'instance (appelées données attributs en Python) sont définies immédiatement après la définition de la classe (avec le mot-clé static pour les premières). En Python, seuls les attributs de classe peuvent être définis à cet endroit, les données attributs sont définies dans la méthode __init__.
      NOTE
      Il n'y a pas de constantes en Python. Tout est modifiable en faisant un effort. C'est en accord avec un des principes essentiels de Python : un mauvais comportement doit être découragé mais pas interdit. Si vous voulez vraiment changer la valeur de None, vous pouvez le faire, mais ne venez pas vous plaindre que votre code est impossible à déboguer.

    • 5.9. Fonctions privées
      NOTE
      En Python, toutes les méthodes spéciales (comme __setitem__) et les attributs prédéfinis (comme __doc__) suivent une convention standard : il commencent et se terminent par deux caractères de soulignement. Ne nommez pas vos propres méthodes et attributs de cette manière, cela n'apporterait que de la confusion pour vous et les autres.

    Chapitre 6. Traitement des exceptions et utilisation de fichiers

    • 6.1. Traitement des exceptions
      NOTE
      Python utilise try...except pour gérer les exceptions et raise pour les générer. Java et C++ utilisent try...catch pour gérer les exceptions et throw pour les générer.

    • 6.5. Travailler avec des répertoires
      NOTE
      A chaque fois que c’est possible, vous devriez utiliser les fonction de os et os.path pour les manipulations de fichier, de répertoire et de chemin. Ces modules enveloppent des modules spécifiques aux plateformes, les fonctions comme os.path.split marchent donc sous UNIX, Windows, Mac OS et toute autre plateforme supportée par Python.

    Chapitre 7. Expressions régulières

    • 7.4. Utilisation de la syntaxe {n,m}
      NOTE
      Il n’y a aucun moyen de déterminer par un programme que deux expressions régulières sont équivalentes. Le mieux que vous puissiez faire est d’écrire de nombreux cas de test pour vérifier que leur comportements sont identiques pour les entrées pertinentes. Nous discuterons plus en détail l’écriture de cas de tests plus loin dans le livre.

    Chapitre 8. Traitement du HTML

    • 8.2. Présentation de sgmllib.py
      Important
      Python 2.0 avait un bogue qui empêchait SGMLParser de reconnaître les déclarations (handle_decl n’était jamais appelé), ce qui veut dire que les DOCTYPEs étaient ignorés silencieusement. Ce bogue est corrigé dans Python 2.1.
      ASTUCE
      Dans l’IDE ActivePython sous Windows, vous pouvez spécifier des arguments de ligne de commande dans la boîte de dialogue «Run script». Séparez les différents arguments par des espaces.

    • 8.4. Présentation de BaseHTMLProcessor.py
      Important
      La spécification HTML exige que tous les éléments non-HTML (comme le JavaScript côté client) soient compris dans des commentaires HTML, mais toutes les pages web ne le font pas (et les navigateurs web récents ne l’exigent pas). BaseHTMLProcessor, lui, l’exige, si le script n’est correctement encadré dans un commentaire, il sera analysé comme s’il était du code HTML. Par exemple, si le script contient des signes inférieurs à ou égal, SGMLParser peut considérer à tort qu’il a trouvé des balises et des attributs. SGMLParser convertit toujours les noms de balises et d’attributs en minuscules, ce qui peut empêcher la bonne exécution du script et BaseHTMLProcessor entoure toujours les valeurs d’attributs entre guillemets (même si le document HTML n’en utilisait pas ou utilisait des guillemets simples), ce qui empêchera certainement l’exécution du script. Protégez toujours vos script côté client par des commentaires HTML.

    • 8.5. locals et globals
      Important
      Python 2.2 a introduit une modification légère mais importante qui affecte l’ordre de recherche dans les espaces de noms : les portées imbriquées. Dans les versions précédentes de Python, lorsque vous référenciez une variable dans une fonction imbriquée ou une fonction lambda, Python recherchait la variable dans l’espace de noms de la fonction (imbriquée ou lambda) en cours, puis dans l’espace de noms du module. Python 2.2 recherche la variable dans l’espace de noms de la fonction (imbriquée ou lambda) en cours, puis dans l’espace de noms de la fonction parente, puis dans l’espace de noms du module. Python 2.1 peut adopter l'un ou l'autre de ces comportements, par défaut il fonctionne comme Python 2.0, mais vous pouvez ajouter la ligne de code suivante au début de vos modules pour les faire fonctionner comme avec Python 2.2 :
      
      from __future__ import nested_scopes
      NOTE
      A l’aide des fonctions locals et globals, vous pouvez obtenir la valeur d’une variable quelconque dynamiquement, en fournissant le nom de la variable sous forme de chaîne. C’est une fonctionnalité semblable à celle de la fonction getattr, qui vous permet d’accéder à une fonction quelconque dynamiquement en fournissant le nom de la fonction sous la forme d’une chaîne.

    • 8.6. Formatage de chaînes à l’aide d’un dictionnaire
      Important
      L’utilisation du formatage de chaîne à l’aide d’un dictionnaire avec locals est une manière pratique de rendre des expressions de formatage complexes plus lisibles, mais elle a un prix. Il y a une petite baisse de performance due à l’appel de locals, puisque locals effectue une copie de l’espace de noms local.

    Chapitre 9. Traitement de données XML

    • 9.2. Les paquetages
      NOTE
      Un paquetage est un répertoire pourvu du fichier __init__.py. Le fichier __init__.py définit les attributs et les méthodes du paquetage. Il n'est cependant pas tenu de définir quoi que ce soit; ce peut simplement être un fichier vide, mais il se doit d'être présent. Et si __init__.py n'existe pas, le répertoire reste un répertoire, pas un paquetage et ne peut ni être importé ni contenir de modules ou de paquetages imbriqués.

    • 9.6. Accéder aux attributs d'un élément
      NOTE
      Cette section peut paraître un peu confuse dans le mesure où des terminologies se recouvrent. Les éléments d'un document XML ont des attributs, mais les objets Python ont aussi des attributs. Lorsque vous analysez un document XML, vous obtenez un paquet d'objets Python qui représentent l'ensemble des parties du document XML et certains de ces objets Python représentent les attributs des éléments XML. Mais les objets (Python) qui représentent les attributs (XML) possèdent également des attributs (Python), qui sont utilisés pour accéder à diverses parties de l'attribut (XML) que l'objet représente. Je vous avais bien dit que tout cela prêtait à confusion. Je suis ouvert à toute suggestion qui permettrait de les distinguer plus clairement.
      NOTE
      A l'instar d'un dictionnaire, les attributs d'un élément XML ne sont pas ordonnés. Il se peut que les attributs apparaissent dans un certain ordre dans le document XML original et qu'ils apparaissent dans un certain ordre quand le document XML est analysé en objets Python, mais ces ordonnancements sont arbitraires et n'ont aucune signification particulière. Vous devriez toujours accéder aux attributs individuels par leur nom, comme les clés d'un dictionnaire.

    Chapitre 10. Des scripts et des flots de données (streams)

      Chapitre 11. Services Web HTTP

      • 11.6. Prise en charge de Last-Modified et ETag
        NOTE
        Dans ces exemples, le serveur HTTP supporte à la fois les en-têtes Last-Modified et ETag, mais ce n'est pas le cas de tous les serveurs. Pour vos clients de services Web, vous devez prévoir de supporter les deux et programmer de manière défensive au cas ou un serveur ne supporterais que l'un des deux, ou aucun.

      Chapitre 12. Services Web SOAP

        Chapitre 13. Tests unitaires

        Chapitre 14. Ecriture des tests en premier

        • 14.3. roman.py, étape 3
          NOTE
          La chose la plus importante que des tests unitaires complets vous disent est quand vous arrêter d’écrire du code. Quand tous les tests unitaires d’une fonction passent, arrêtez d’écrire le code de la fonction. Quand tous les tests d’un module passent, arrêtez d’écrire le code du module.

        • 14.5. roman.py, étape 5
          NOTE
          Quand tous vos tests passent, arrêtez d’écrire du code.

        Chapitre 15. Refactorisation

        • 15.3. Refactorisation
          NOTE
          A chaque fois que vous allez utiliser une expression régulière plus d’une fois, il vaut mieux la compiler pour obtenir un objet motif et appeler ses méthodes directement.

        Chapitre 16. Programmation fonctionnelle

        • 16.2. Trouver le chemin
          NOTE
          Les chemins et noms de fichier que vous passez à os.path.abspath n'ont pas besoin d'exister sur le disque.
          NOTE
          os.path.abspath ne construit pas seulement des chemins complets, il les normalise. Cela signifie que si vous êtes dans le répertoire /usr/, os.path.abspath('bin/../local/bin') retournera /usr/local/bin. Il normalise le chemin en le rendant aussi simple que possible. Si vous voulez normaliser un chemin de cette manière sans le transformer en chemin complet, utilisez os.path.normpath.
          NOTE
          Comme les autres fonctions des modules os et os.path, os.path.abspath est multiplate-forme. Les résultats que vous obtiendrez seront légèrement ifférents si vous utilisez Windows (qui utilise le le backslash comme séparateur de chemin) ou Mac OS (qui utilise les deux points), mais le script fonctionnera. C'est là le rôle du module os.

        Chapitre 17. Fonctions dynamiques

          Chapitre 18. Ajustements des performances

          • 18.2. Utilisation du module timeit
            ASTUCE
            Vous pouvez utiliser le module timeit en ligne de commande pour tester un programme Python existant sans en modifier le code. Voir http://docs.python.org/lib/node396.html pour la documentation des paramètres de ligne de commande.
            ASTUCE
            Le module timeit ne fonctionne que si vous savez déjà quelle partie de votre code optimiser. Si vous avez un programme Python plus grand et que vous ne savez pas où se trouve le problème de performances, allez voir le module hotshot.