Changing calling sequence

Chris Angelico rosuav at gmail.com
Sun May 15 00:44:09 EDT 2022


On Sun, 15 May 2022 at 14:27, dn <PythonList at danceswithmice.info> wrote:
>
> On 15/05/2022 11.34, 2QdxY4RzWzUUiLuE at potatochowder.com wrote:
> > On 2022-05-15 at 10:22:15 +1200,
> > dn <PythonList at DancesWithMice.info> wrote:
> >
> >> That said, a function which starts with a list of ifs-buts-and-maybes*
> >> which are only there to ascertain which set of arguments have been
> >> provided by the calling-routine; obscures the purpose/responsibility
> >> of the function and decreases its readability (perhaps not by much,
> >> but varying by situation).
> >
> > Agreed.
> >
> >> Accordingly, if the function is actually a method, recommend following
> >> @Stefan's approach, ie multiple-constructors. Although, this too can
> >> result in lower readability.
> >
> > (Having proposed that approach myself (and having used it over the
> > decades for functions, methods, procedures, constructors, ...), I also
> > agree.)
> >
> > Assuming good names,¹ how can this lead to lower readability?  I guess
> > if there's too many of them, or programmers have to start wondering
> > which one to use?  Or is this in the same generally obfuscating category
> > as the ifs-buts-and-maybes at the start of a function?
> >
> > ¹ and properly invalidated caches
>
> Allow me to extend the term "readability" to include "comprehension".
> Then add the statistical expectation that a class has only __init__().

(Confusing wording here: a class usually has far more than just
__init__, but I presume you mean that the signature of __init__ is the
only way to construct an object of that type.)

> Thus, assuming this is the first time (or, ... for a while) that the
> class is being employed, one has to read much further to realise that
> there are choices of constructor.

Yeah. I would generally say, though, that any classmethod should be
looked at as a potential alternate constructor, or at least an
alternate way to obtain objects (eg preconstructed objects with
commonly-used configuration - imagine a SecuritySettings class with a
classmethod to get different defaults).

> Borrowing from the earlier example:
>
> >   This would be quite pythonic. For example, "datetime.date"
> >   has .fromtimestamp(timestamp), .fromordinal(ordinal),
> >   .fromisoformat(date_string), ...
>
> Please remember that this is only relevant if the function is actually a
> module - which sense does not appear from the OP (IMHO).
>
> The alternatives' names are well differentiated and (apparently#)
> appropriately named*.
>
>
> * PEP-008 hobgoblins will quote:
> "Function names should be lowercase, with words separated by underscores
> as necessary to improve readability.

Note the "as necessary". Underscores aren't required when readability
is fine without them (see for instance PEP 616, which recently added
two methods to strings "removeprefix" and "removesuffix", no
underscores - part of the argument here was consistency with other
string methods, but it's also not a major problem for readability
here).

> Variable names follow the same convention as function names."
> - but this is a common observation/criticism of code that has been in
> the PSL for a long time.
>
> # could also criticise as not following the Software Craftsmanship/Clean
> Code ideal of 'programming to the interface rather than the
> implementation' - which we see in PEP-008 as "usage rather than
> implementation"
> (but please don't ask me how to differentiate between them, given that
> the only reason for the different interfaces is the
> function's/parameters' implementation!)
>
> NB usual caveats apply to PEP-008 quotations!

Notably here, the caveat that PEP 8 is not a permanent and unchanging
document. It is advice, not rules, and not all code in the standard
library fully complies with its current recommendations.

> Continuing the 'have to read further' criticism (above), it could
> equally-well be applied to my preference for keyword-arguments, in that
> I've suggested defining four parameters but the user will only call the
> function with either three or one argument(s). Could this be described
> as potentially-confusing?

Yes, definitely. Personally, I'd split it into two, one that takes the
existing three arguments (preferably with the same name, for
compatibility), and one with a different name that takes just the one
arg. That could be a small wrapper that calls the original, or the
original could become a wrapper that calls the new one, or the main
body could be refactored into a helper that they both call. It all
depends what makes the most sense internally, because that's not part
of the API at that point.

But it does depend on how the callers operate. Sometimes it's easier
to have a single function with switchable argument forms, other times
it's cleaner to separate them.

ChrisA


More information about the Python-list mailing list