pythonpep8pep

Python readibility of long statement


I have a call to a function which returns a lot of elements, and the way to respect PEP8 is to do the following, but I don't find it very readable:

colonne_dernier_attribut, colonne_non_explained_beads, colonne_non_explained_beads_recipient, \
    colonne_non_explained_beads_donor, colonne_score, colonne_comments, colonne_loci_manquants, \
    colonne_edta, colonne_temps, colonne_summary = \
    formatageRes(ws, wrsep, wdsep, feuille, feuille_corrigee, all_epitopes_considered, nbr_ep_considered, nrows)

I would want something like this where we can clearly see where the call to the function. In other words, I would like to see a clear difference before and after the = sign.

colonne_dernier_attribut, colonne_non_explained_beads, colonne_non_explained_beads_recipient, \
colonne_non_explained_beads_donor, colonne_score, colonne_comments, colonne_loci_manquants, \
colonne_edta, colonne_temps, colonne_summary = \
    formatageRes(ws, wrsep, wdsep, feuille, feuille_corrigee, all_epitopes_considered, nbr_ep_considered, nrows)

But this isn't following the PEP8 guidelines. I'm looking for a third alternative which is both more readable and follows PEP8.


Solution

  • One handy trick is to use parens to allow you to split the assignments across lines without having to escape the linebreaks:

    (
        colonne_dernier_attribut,
        colonne_non_explained_beads,
        colonne_non_explained_beads_recipient,
        colonne_non_explained_beads_donor, 
        colonne_score,
        colonne_comments,
        colonne_loci_manquants,
        colonne_edta, 
        colonne_temps,
        colonne_summary
    ) = formatageRes(
        ws, 
        wrsep, 
        wdsep, 
        feuille, 
        feuille_corrigee, 
        all_epitopes_considered, 
        nbr_ep_considered, 
        nrows
    )
    

    This makes it pretty obvious where the list of assigned variables ends and the function call begins.

    I'd suggest though that if just calling this function is this complicated, you probably want to rethink this API and have it return some kind of object (maybe just something as simple as a dataclass or NamedTuple) rather than an anonymous tuple that requires all this destructuring in order to be usable. E.g.:

    from dataclasses import dataclass
    
    @dataclass
    class Collone:
        dernier_attribut: str
        non_explained_beads: int
        non_explained_beads_recipient: str
        non_explained_beads_donor: str
        score: int
        comments: list[str]
        loci_manquants: tuple[int, int]
        edta: str
        temps: list[int]
        summar: int
    
    def formatageRes(
        ws, 
        wrsep, 
        wdsep, 
        feuille, 
        feuille_corrigee, 
        all_epitopes_considered, 
        nbr_ep_considered, 
        nrows
    ) -> Collone: ...
    

    so that you can do:

    collone = formatageRes(
         ws, 
         wrsep, 
         wdsep, 
         feuille, 
         feuille_corrigee, 
         all_epitopes_considered, 
         nbr_ep_considered, 
         nrows
    )
    

    The remainder of the calling code is then essentially the same, but with collone_varname replaced with collone.varname.