515 votes

Indentation correcte pour les chaînes de caractères multilignes ?

Quelle est l'indentation appropriée pour les chaînes de caractères multilignes de Python à l'intérieur d'une fonction ?

    def method():
        string = """line one
line two
line three"""

ou

    def method():
        string = """line one
        line two
        line three"""

ou autre chose ?

Dans le premier exemple, il est un peu bizarre que la chaîne de caractères soit suspendue en dehors de la fonction.

6 votes

Les chaînes de documents sont traitées spécialement Le texte de la première ligne est supprimé ; le plus petit retrait commun à toutes les autres lignes non vides est supprimé de toutes les lignes. À part cela, les chaînes littérales multilignes en Python sont malheureusement ce que vous voyez est ce que vous obtenez en termes d'espace blanc : tous les caractères entre les délimiteurs de la chaîne font partie de la chaîne, y compris l'indentation qui, avec les instincts de lecture de Python, semble devoir être mesurée à partir de l'indentation de la ligne où commence le littéral.

3 votes

@EvgeniSergeev L'outil de traitement effectue cette tâche (et cela dépend largement de votre choix d'outil de traitement). method.__doc__ n'est pas modifiée par Python lui-même, pas plus que n'importe quelle autre méthode. str littérale.

488voto

Mike Graham Points 22480

Vous voudrez probablement vous aligner sur le """

def foo():
    string = """line one
             line two
             line three"""

Comme les nouvelles lignes et les espaces sont inclus dans la chaîne elle-même, vous devrez la post-traiter. Si vous ne voulez pas le faire et que vous avez beaucoup de texte, vous pouvez le stocker séparément dans un fichier texte. Si un fichier texte ne convient pas à votre application et que vous ne voulez pas faire de post-traitement, j'opterais probablement pour

def foo():
    string = ("this is an "
              "implicitly joined "
              "string")

Si vous souhaitez post-traiter une chaîne multiligne pour en éliminer les parties inutiles, vous pouvez utiliser l'option textwrap ou la technique de post-traitement des docstrings présentée dans le module PEP 257 :

def trim(docstring):
    if not docstring:
        return ''
    # Convert tabs to spaces (following the normal Python rules)
    # and split into a list of lines:
    lines = docstring.expandtabs().splitlines()
    # Determine minimum indentation (first line doesn't count):
    indent = sys.maxint
    for line in lines[1:]:
        stripped = line.lstrip()
        if stripped:
            indent = min(indent, len(line) - len(stripped))
    # Remove indentation (first line is special):
    trimmed = [lines[0].strip()]
    if indent < sys.maxint:
        for line in lines[1:]:
            trimmed.append(line[indent:].rstrip())
    # Strip off trailing and leading blank lines:
    while trimmed and not trimmed[-1]:
        trimmed.pop()
    while trimmed and not trimmed[0]:
        trimmed.pop(0)
    # Return a single string:
    return '\n'.join(trimmed)

1 votes

Il est bon d'avoir le même niveau d'indentation pour chaque ligne de texte dans la chaîne. Mais cela signifie que les lignes de texte doivent avoir un seul niveau d'indentation (4 colonnes), et ne pas commencer à une position arbitraire de plusieurs colonnes à partir de la ligne précédente.

0 votes

@bignose, je ne vois pas en quoi cette exigence contribue à rendre le code plus propre ou plus lisible ou présente un avantage particulier.

13 votes

Il s'agit du style d'indentation suspendue pour le suivi des lignes. Il est prescrit dans le PEP8 pour les définitions de fonctions et les longues instructions if, bien qu'il ne soit pas mentionné pour les chaînes de caractères multilignes. Personnellement, c'est l'un des points sur lesquels je refuse de suivre le PEP8 (et j'utilise à la place un retrait de 4 espaces), car je n'aime pas du tout les retraits suspendus qui, pour moi, obscurcissent la structure correcte du programme.

308voto

bignose Points 6573

Les textwrap.dedent permet de commencer par indentation correcte dans la source Le texte est ensuite dépouillé avant d'être utilisé.

La contrepartie, comme l'ont fait remarquer d'autres personnes, est qu'il s'agit d'un appel de fonction supplémentaire sur le littéral ; tenez-en compte lorsque vous décidez de l'endroit où placer ces littéraux dans votre code.

import textwrap

def frobnicate(param):
    """ Frobnicate the scrognate param.

        The Weebly-Ruckford algorithm is employed to frobnicate
        the scrognate to within an inch of its life.

        """
    prepare_the_comfy_chair(param)
    log_message = textwrap.dedent("""\
            Prepare to frobnicate:
            Here it comes...
                Any moment now.
            And: Frobnicate!""")
    weebly(param, log_message)
    ruckford(param)

La fin de l'article \ dans le littéral du message de journal est de s'assurer que le saut de ligne n'est pas dans le littéral ; ainsi, le littéral ne commence pas par une ligne vierge, mais par la ligne complète suivante.

La valeur de retour de textwrap.dedent est la chaîne d'entrée avec toutes les indentations courantes des espaces blancs de tête sont supprimées sur chaque ligne de la chaîne. Ainsi, l'exemple ci-dessus log_message sera :

Prepare to frobnicate:
Here it comes...
    Any moment now.
And: Frobnicate!

2 votes

Bien qu'il s'agisse d'une solution raisonnable et qu'il soit bon de la connaître, faire quelque chose comme cela à l'intérieur d'une fonction fréquemment appelée pourrait s'avérer désastreux.

0 votes

@haridsv Pourquoi cela serait-il un désastre ?

10 votes

@jtmoulia : Une meilleure description que le désastre serait "inefficace" parce que le résultat de l'analyse des données de la base de données est le même que celui de la base de données de la base de données de la base de données. textwrap.dedent() est une valeur constante, tout comme son argument d'entrée.

19voto

Joop Points 1108

S

from matplotlib.cbook import dedent

I

"""
line 1 of string
line 2 of string
"""

"""\
line 1 of string
line 2 of string
"""

"""line 1 of string
line 2 of string
"""

U

O

S

W

def example():
    long_string = '''\
Lorem ipsum dolor sit amet, consectetur adipisicing
elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip.\
'''
    return long_string

print example()

1voto

James Gowdy Points 19

Je suis venu ici à la recherche d'un simple 1-liner pour supprimer ou corriger l'identation niveau de la docstring pour l'impression, sans en faire désordre, par exemple en le rendant accrocher à l'extérieur de la fonction" dans le script.

Voici ce que j'ai fait:

import string
def myfunction():

    """
    line 1 of docstring
    line 2 of docstring
    line 3 of docstring"""

print str(string.replace(myfunction.__doc__,'\n\t','\n'))[1:] 

Évidemment, si vous êtes à la mise en retrait avec des espaces (par exemple, 4) plutôt que la touche de tabulation utiliser quelque chose comme ceci à la place:

print str(string.replace(myfunction.__doc__,'\n    ','\n'))[1:]

Et vous n'avez pas besoin de supprimer le premier personnage si vous le souhaitez votre docstrings ressembler à ceci à la place:

    """line 1 of docstring
    line 2 of docstring
    line 3 of docstring"""

print string.replace(myfunction.__doc__,'\n\t','\n') 

0 votes

Cela ne fonctionne pas avec les méthodes de classe et les classes imbriquées.

-1voto

Cela dépend de la manière dont vous souhaitez que le texte s'affiche. Si vous voulez qu'il soit aligné à gauche, vous pouvez soit le formater comme dans le premier extrait, soit itérer à travers les lignes en coupant tout l'espace à gauche.

5 votes

La façon dont les outils de traitement des docstring fonctionnent consiste à supprimer non pas les éléments suivants tous l'espace à gauche, mais autant comme première ligne indentée. Cette stratégie est un peu plus sophistiquée et vous permet d'indenter et de faire respecter cette indentation dans la chaîne de caractères post-traitée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X