web-dev-qa-db-fra.com

L'interprétation par Python des tabulations et des espaces à mettre en retrait

J'ai décidé que j'apprends un peu de Python. La première introduction indique qu'il utilise l'indentation pour regrouper les instructions. Alors que la meilleure habitude est clairement d'utiliser un seul de ces éléments, que se passe-t-il si je les échange? Combien d'espaces seront considérés comme égaux à un onglet? Ou ne fonctionnera-t-il pas du tout si les tabulations et les espaces sont mélangés?

32
Lukas

Les espaces ne sont pas traités comme équivalents à tab. Une ligne en retrait avec une tabulation est à une indentation différente d'une ligne en retrait avec 1, 2, 4 ou 8 les espaces.

Preuve par contre-exemple ( erronée, ou, au mieux, limitée - tab! = 4 espaces ):

x = 1
if x == 1:
^Iprint "fff\n"
    print "yyy\n"

Le '^I' Affiche un TAB. Lorsque je passe par Python 2.5, j'obtiens l'erreur:

  File "xx.py", line 4
    print "yyy\n"
                ^
IndentationError: unindent does not match any outer indentation level

Montrant ainsi que dans Python 2.5, les tabulations ne sont pas égales aux espaces (et notamment pas égales à 4 espaces).


Oups - embarrassant; ma preuve par contre-exemple montre que les tabulations ne sont pas équivalentes à 4 espaces. Comme Alex Martelli le souligne dans un comment , dans Python 2, les tabulations sont équivalentes à 8 espaces, et l'adaptation de l'exemple avec une tabulation et 8 espaces montre que C'est en effet le cas.

x = 1
if x != 1:
^Iprint "x is not 1\n"
        print "y is unset\n"

Dans Python 2, ce code fonctionne, n'imprimant rien.


Dans Python 3, les règles sont légèrement différentes (comme noté par Antti Haapala ). Comparer:

Python 2 dit:

Tout d'abord, les tabulations sont remplacées (de gauche à droite) par un à huit espaces de sorte que le nombre total de caractères jusqu'au remplacement inclus est un multiple de huit (il s'agit de la même règle que celle utilisée par Unix). Le nombre total d'espaces précédant le premier caractère non vide détermine ensuite le retrait de la ligne. L'indentation ne peut pas être fractionnée sur plusieurs lignes physiques à l'aide de barres obliques inverses; l'espace jusqu'à la première barre oblique inverse détermine l'indentation.

Python 3 dit:

Les tabulations sont remplacées (de gauche à droite) par un à huit espaces de sorte que le nombre total de caractères jusqu'au remplacement inclus est un multiple de huit (il s'agit de la même règle que celle utilisée par Unix). Le nombre total d'espaces précédant le premier caractère non vide détermine ensuite le retrait de la ligne. L'indentation ne peut pas être fractionnée sur plusieurs lignes physiques à l'aide de barres obliques inverses; l'espace jusqu'à la première barre oblique inverse détermine l'indentation.

(Mis à part le mot d'ouverture "First", ceux-ci sont identiques.)

Python 3 ajoute un paragraphe supplémentaire:

L'indentation est rejetée comme incohérente si un fichier source mélange les tabulations et les espaces d'une manière qui rend la signification dépendante de la valeur d'une tabulation dans les espaces; une TabError est déclenchée dans ce cas.

Cela signifie que le TAB vs un exemple de 8 espaces qui fonctionnait dans Python 2 générerait une TabError dans Python 3. Il est préférable - nécessaire dans Python 3 - de s'assurer que la séquence de caractères constituant l'indentation sur chaque ligne d'un bloc est identique. PEP8 dit 'utilisez 4 espaces par niveau d'indentation'. (Les normes de codage de Google disent "utilisez 2 espaces".)

35
Jonathan Leffler

Suivez PEP 8 pour Python. PEP 8 dit: Indentation

Utilisez 4 espaces par niveau d'indentation.

Pour un code très ancien que vous ne voulez pas gâcher, vous pouvez continuer à utiliser des onglets à 8 espaces.

Onglets ou espaces?

Ne mélangez jamais les tabulations et les espaces.

Le moyen le plus populaire de mettre en retrait Python est uniquement avec des espaces. Le deuxième moyen le plus populaire est avec des tabulations uniquement. Le code en retrait avec un mélange de tabulations et d'espaces doit être converti en utilisant exclusivement des espaces. en invoquant l'interpréteur de ligne de commande Python avec l'option -t, il émet des avertissements sur le code qui mélange illégalement les tabulations et les espaces. Lorsque vous utilisez -tt, ces avertissements deviennent des erreurs. Ces options sont fortement recommandées!

18
Eli Bendersky

Dans Python 2, l'interprétation de TAB c'est comme s'il était converti en espaces à l'aide de taquets de tabulation à 8 espaces (comme déjà fourni par les réponses précédentes); c'est que chaque TAB prolonge l'indentation de 1 à 8 espaces afin que l'indentation résultante soit divisible par 8.

Cependant, cela ne s'applique pas à Python 3 plus - dans le mélange Python 3 d'espaces et de tabulations est toujours une erreur - les tabulations ne correspondent qu'aux tabulations et les espaces ne correspondent qu'aux autres espaces dans indentation; c'est une ligne en retrait avec TABSPACESPACE peut également contenir des lignes en retrait SPACESPACETAB; et peut contenir un bloc en retrait avec un retrait TABSPACESPACETAB, mais si le bloc indenté contenait TABTAB, il serait considéré comme une erreur d'indentation, même si le bloc s'étendrait apparemment plus loin:

L'indentation est rejetée comme incohérente si un fichier source mélange les tabulations et les espaces d'une manière qui rend la signification dépendante de la valeur d'une tabulation dans les espaces; une TabError est déclenchée dans ce cas.

C'est à dire. L'algorithme fonctionne comme suit:

  • si le nombre d'onglets et le nombre d'espaces correspond à la ligne précédente (peu importe l'ordre), alors cette ligne appartient au même bloc que la ligne précédente

  • si le nombre de l'un (tabulations, espaces) est supérieur à celui de la ligne précédente et le nombre de l'autre est au moins égal à ceux de la ligne précédente, il s'agit d'un bloc en retrait

  • le Tuple (tabs, spaces) correspond à un retrait d'un bloc précédent - cela se déduit à ce bloc

  • sinon un IndentationError ou un TabError est levé.

C'est pourquoi mélanger des tabulations et des espaces, ou même utiliser des tabulations pour l'indentation serait considéré comme une très mauvaise pratique en Python.

8
Antti Haapala

Ne les échangez pas :)
Réglez votre IDE/éditeur pour saisir 4 espaces en appuyant sur "tab" et vous êtes prêt à partir.

5
shylent

Je vous recommande de passer par PEP 8 qui est le guide officiel de style Python pour Python. Il couvre ( entre autres choses) l'utilisation des tabulations/espaces.

5
Noufal Ibrahim

Quatre espaces sont un onglet (dans ma configuration), mais pour autant que je sache, ils ne sont pas échangés. Vous pouvez utiliser des espaces ou des tabulations, pas les deux.

2
Amirshk

Je crois que le caractère de tabulation ne devrait tout simplement jamais apparaître dans le code source en aucune circonstance. Il n'y a aucun avantage et c'est une source infinie de petites erreurs. - utilisez une chaîne de caractères avec\t si vous avez besoin d'un onglet, il a l'avantage d'être auto-documenté.

Ici est l'article classique sur les tabulations vs les espaces - J'utilise une variante de elisp de jwz dans mon propre fichier .emacs.

(J'avoue avoir rompu personnellement avec PEP 8 en n'utilisant que l'indentation de 2 caractères - 4 caractères, c'est beaucoup quand vos lignes ne font que 80 caractères ...)

0
Tom Swirly