web-dev-qa-db-fra.com

Style correct pour les sauts de ligne lors du chaînage des méthodes dans Python

J'ai un code comme celui-ci. La pause doit-elle survenir avant les règles ou après?

# before
my_var = somethinglikethis.where(we=do_things).where(we=domore).where(we=everdomore)

# this way
my_var = somethinglikethis.where(we=do_things) \
                          .where(we=domore) \
                          .where(we=everdomore)

# or this way
my_var = somethinglikethis.where(we=do_things). \
                           where(we=domore). \
                           where(we=everdomore)
42
JiminyCricket

PEP 8 recommande d'utiliser des parenthèses pour ne pas avoir besoin de \, et suggère doucement de casser avant les opérateurs binaires au lieu de les suivre. Ainsi, la façon préférée de formater votre code est la suivante:

my_var = (somethinglikethis
          .where(we=do_things)
          .where(we=domore)
          .where(we=everdomore))

Les deux passages pertinents sont ceux de la section Longueur de ligne maximale :

Le moyen préféré pour encapsuler les longues lignes est d'utiliser la continuation de ligne implicite de Python entre parenthèses, crochets et accolades. Les longues lignes peuvent être coupées sur plusieurs lignes en enveloppant les expressions entre parenthèses. Ceux-ci doivent être utilisés de préférence à l'utilisation d'une barre oblique inverse pour la poursuite de la ligne.

... et l'intégralité ne ligne doit-elle être interrompue avant ou après un opérateur binaire? section:

Une ligne doit-elle être interrompue avant ou après un opérateur binaire?

Pendant des décennies, le style recommandé était de casser après les opérateurs binaires. Mais cela peut nuire à la lisibilité de deux manières: les opérateurs ont tendance à être dispersés sur différentes colonnes de l'écran et chaque opérateur est éloigné de son opérande et sur la ligne précédente. Ici, l'œil doit faire un travail supplémentaire pour savoir quels éléments sont ajoutés et lesquels sont soustraits:

# No: operators sit far away from their operands
income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)

Pour résoudre ce problème de lisibilité, les mathématiciens et leurs éditeurs suivent la convention inverse. Donald Knuth explique la règle traditionnelle dans sa série Ordinateurs et composition : "Bien que les formules dans un paragraphe se cassent toujours après les opérations et relations binaires, les formules affichées se cassent toujours avant opérations binaires "

Suivre la tradition des mathématiques donne généralement un code plus lisible:

# Yes: easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

En Python, il est permis de casser avant ou après un opérateur binaire, tant que la convention est cohérente localement. Pour le nouveau code, le style de Knuth est suggéré.

Notez que, comme indiqué dans la citation ci-dessus, PEP 8 a utilisé pour donner le conseil inverse sur l'endroit où se briser autour d'un opérateur, cité ci-dessous pour la postérité:

Le moyen préféré pour encapsuler les longues lignes est d'utiliser la continuation de ligne implicite de Python entre parenthèses, crochets et accolades. Les longues lignes peuvent être coupées sur plusieurs lignes en enveloppant les expressions entre parenthèses. Ceux-ci doivent être utilisés de préférence à l'utilisation d'une barre oblique inverse pour la poursuite de la ligne. Assurez-vous de mettre en retrait la ligne continue de manière appropriée. L'endroit préféré pour contourner un opérateur binaire est après l'opérateur, pas avant lui. Quelques exemples:

class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if (width == 0 and height == 0 and
            color == 'red' and emphasis == 'strong' or
            highlight > 100):
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)
63
Bastien Léonard

PEP 8 dit que la rupture avant l'opérateur est préférable:

Donald Knuth explique la règle traditionnelle dans sa série Ordinateurs et composition: "Bien que les formules d'un paragraphe se cassent toujours après les opérations et les relations binaires, les formules affichées se cassent toujours avant les opérations binaires".

...

En Python, il est permis de casser avant ou après un opérateur binaire, tant que la convention est cohérente localement. Pour le nouveau code, le style de Knuth est suggéré.

https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator

4
Neapolitan

FWIW, autopep8 (avec un --aggressive flag) a produit ceci à partir de votre code d'origine:

my_var = somethinglikethis.where(
    we=do_things).where(
    we=domore).where(
    we=everdomore)

Mais je suis d'accord - la solution de Bastien est plus élégante.

2
Amanda

Faites ce qui fonctionne.

Consultez également ce livre blanc sur les mythes de l'indentation en Python. Cela peut être trouvé ici.

Cela commence par:

"Les espaces sont significatifs dans le code source Python."

Non, pas en général. Seul le niveau d'indentation de vos déclarations est significatif (c'est-à-dire les espaces à l'extrême gauche de vos déclarations). Partout ailleurs, le blanc n'est pas significatif et peut être utilisé comme vous le souhaitez, comme dans n'importe quelle autre langue. Vous pouvez également insérer des lignes vides qui ne contiennent rien (ou seulement des espaces arbitraires) n'importe où.

J'espère que ça aide.

1
Mr_Spock