web-dev-qa-db-fra.com

Comment indenter Python liste-compréhensions?

Les compréhensions de la liste peuvent être utiles dans certaines situations, mais elles peuvent également être plutôt horribles de lire .. comme exemple légèrement exagéré, comment voudriez-vous indenter ce qui suit?

allUuids = [x.id for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) if x.type == "post" and x.deleted is not False]
60
dbr

Cela dépend de combien de temps ils sont. J'ai tendance à les structurer comme:

[x.id for x
 in self.db.query(schema.allPostsUuid).execute(timeout=20)
 if x.type == 'post' 
    and x.deleted is not False
    and ...
    and ...]

De cette façon, chaque expression a sa propre ligne.

Si une ligne devient trop gros, j'aime l'extraire dans une Lambda ou une expression:

transform = lambda x: x.id
results = self.db.query(schema.allPostsUuid).execute(timeout=20)
condition = lambda x: x.deleted is not False and ... and ...
[transform(x) for x in results if condition(x)]

Et puis si une Lambda devient trop longue, elle est promue à une fonction.

65
orestis

Où je travaille, nos directives de codage nous auraient fait quelque chose comme ceci:

all_posts_uuid_query = self.db.query(schema.allPostsUuid)
all_posts_uuid_list = all_posts_uuid_query.execute(timeout=20)
all_uuid_list = [
    x.id 
    for x in all_posts_uuid_list 
    if (
        x.type == "post" 
        and 
        not x.deleted  # <-- if you don't care about NULLs / None
    )
]
44
guzzloid
allUuids = [x.id 
            for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) 
            if x.type == "post" and x.deleted is not False]
7
jfs

Pour moi c'est trop. Peut-être que c'est juste un exemple terrible, car "type" et "supprimé" feraient clairement partie de la requête de la DB.

J'ai tendance à penser que si une compréhension de la liste couvre plusieurs lignes, il ne devrait probablement pas être une compréhension de la liste. Cela dit, je viens de diviser habituellement la chose à "si" comme les autres personnes ont et répondront ici.

6
Ali Afshar

Vous ne devez pas utiliser une compréhension de liste pour cela.

Les compréhensions de la liste sont une fonctionnalité impressionnante, mais elles sont censées être des raccourcis et non du code normal.

Pour un si long extrait, vous devez utiliser les blocs ordinaires:

allUuids = []
for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) :
    if x.type == "post" and x.deleted is not False :
        allUuids.append(x.id)

Exactement le même comportement, beaucoup plus lisible. Guido serait fier de vous :-)

3
e-satis

Si vous êtes prêt sur une compréhension réponse d'Orestis est bon.

Pour des complètes plus complexes comme ça, je suggère d'utiliser un générateur avec yield:

allUuids = list(self.get_all_uuids())


def get_all_uuids(self):
    for x in self.db.query(schema.allPostsUuid).execute(timeout = 20):
        if x.type == "post" and x.deleted is not False:
            yield x.id
3
Henco

Que diriez-vous:

allUuids = [x.id for x in self.db.query(schema.allPostsUuid).execute(timeout = 20) 
                   if (x.type == "post" and x.deleted is not False)]

En règle générale, de longues lignes peuvent être évitées par des subexpressions pré-calculatrices en variables, ce qui pourrait ajouter un coût de performance minuscule:

query_ids = self.db.query(schema.allPostsUuid).execute(timeout = 20)
allUuids = [x.id for x in query_ids
                   if (x.type == "post" and x.deleted is not False)]

Au fait, n'est-ce pas 'is not False' Tirelet de superflue? Êtes-vous inquiet de la différenciation entre aucun et faux? Parce que sinon, il suffit de quitter la condition que: if (x.type == "post" and x.deleted)

1
Eli Bendersky