Mutant Registration: Implicit or Explicit

Steven D'Aprano steve at
Wed Feb 3 12:10:09 EST 2016

On Thu, 4 Feb 2016 02:08 am, Mark Lawrence wrote:

> Rather more interesting than RR or the RUE?

Hmmm. Well, it's an interesting blog post. The author says:

"My question deals with the implicit nature of the mutation. Not that Python
is somehow wrong, it is the fact that the function usage does not convey
the mutation to the reader as pointedly as I want."

We can't help what he wants (possibly a pony and a plastic rocket?), but the
code is idiomatic and should be clear to any moderately experienced
programmer of any language. The code is:


which clearly doesn't return a value. (Or if it does, the return value is
being ignored.) Hence, it is being called for its side-effects. Nearly
every programming language has some form of procedure call that doesn't
return a value but operates only by side-effect. In Pascal, you declare
such routines as "procedure" instead of "function". In C, you declare them
as functions with a return type of "void". In Python, you explicitly or
implicitly return None. Perhaps some purely functional languages don't have
such a thing, but they're not common.

So regardless of what language(s) they are familiar with, most people should
be able to correctly recognise toggle(mobject) as a procedure (of sorts).

I can accept that the documentation for toggle() is insufficient. It should
explicitly state that it modifies the flag in place. But since the author
of the blog wrote the documentation, he has nobody to blame but himself.

The author suggests returning the dict after mutating it, but that's
possibly the worst of both worlds: the extra typing of functional
programming plus unexpected side-effects:

mobject = toggle(mobject)

The experienced Pythonista will, on reading the source or documentation,
realise that the binding is a waste of time, and rewrite that line as a
pseudo-procedure call:


while less experienced programmers (or those merely not paying attention)
will write this:

new_dict = toggle(old_dict)

and then be painfully surprised that old_dict is modified. It looks like
some sort of scary action-at-a-distance, where every time he modifies
new_dict, old_dict gets modified too. But its not, since new_dict and
old_dict are just two names for the one dict.

In general, mutator functions and methods should not return the object they
just mutated, unless there is a good reason to do so (e.g. decorators).


More information about the Python-list mailing list