[Tutor] Side effect and return value
Cameron Simpson
cs at cskk.id.au
Thu Sep 19 17:16:51 EDT 2024
On 19Sep2024 22:40, Albert-Jan Roskam <sjeik_appie at hotmail.com> wrote:
> I've just read "Code that fits into your Brain".
> The author says a function with a side effect should not have a return
> value.
This is a rule of thumb partitioning functions into those which "do
something" and those which "compute something". The typical examples
might be `list.append`, which modifies a list and returns `None`, and
`list.__len__` aka `len(list)`, which returns the length of the list and
changes nothing.
This is a good design rule - it broadly lets you use "compute" functions
in expressions without worrying that they have side effects. Things with
side effects are not provided as useful-in-expressions (i.e. they're not
written to return a useful value, which precludes them being enticing in
expressions).
But not everything is _quite_ that cut and dry as you've discovered.
The rule is a way of thinking about functions.
So, your example:
>But how would one write this function in order to do that? This looks totally fine to me:
>
> from uuid import UUID
> from requests import post
> def create_user(info: dict) -> UUID:
> resp = post("https://some-thing/user", json=info)
> resp.raise_for_status()
> return UUID(resp.json()["id"])
This function creates something (the user record) and returns its key
for later use.
It looks like it "does something", but that's mostly an artifact of its
interaction with a storage system: the web server which holds the
database records for the users.
it isn't very different from a function like this:
def list_of_characters(s: str) -> List[str]:
return list(s)
We're making a new list and returning a reference to the list. You can
think of that reference as like the user UUID key above. We might use it
in some computation:
letters = [ c for c in list_of_characters(s) if c.isalpha() ]
It doesn['t really have much of a side effect other than allocating
storage for the result of the computation (the new list). Your
`create_user` function is similar - it creates a user record and returns
a reference. That the reference is a UUID isn't very different.
Any "compute" function has side effects of a sort - storage must be
allocated for intermediate values and for its result. Your example just
brings that into the light.
More information about the Tutor
mailing list