Why return None?

Antoon Pardon apardon at forel.vub.ac.be
Fri Aug 27 10:19:19 CEST 2004

```Op 2004-08-26, Alex Martelli schreef <aleaxit at yahoo.com>:
> Antoon Pardon <apardon at forel.vub.ac.be> wrote:
>    ...
>> Then python has already deviated from the one obvious way to do it.
>
> Yep, ever since it let you code 2+3 and 3+2 with just the same effect --
> which was from day one, and couldn't have been otherwise.  _Preferably_
> only one way, but as I said what's preferable can't always be achieved.
>
> Nevertheless, when for some task there _is_ one obvious way to do it,
> adding a feature whose main effect would be giving two alternative
> obvious ways to do it would be unPythonic.
>
>> I can do:
>>
>>   a = a + b   vs    a += b.
>
> Yes you can, and in the general case get very different effects, e.g.:

a += b    vs   a.extend(b)

>
>>>> c=a=range(3)
>>>> b=range(2)
>>>> a+=b
>>>> c
> [0, 1, 2, 0, 1]
>
> versus:
>
>>>> c=a=range(3)
>>>> b=range(2)
>>>> a=a+b
>>>> c
> [0, 1, 2]

I wouldn't say you get different effects in *general*. You get the
same effect if you use numbers or tuples or any other immutable
object.

> So, which one is the obvious way to do it depends on what 'it' is.  In
> some cases it doesn't matter, just like b+a and a+b are going to have
> the same effect when a and b are numbers rather than sequences, and
> there's nothing Python can do to fight this -- practicality beats
> purity.  If you're (when feasible) altering the object to which name 'a'
> is bound, a+=b is the obvious way to do it; if you're in any case
> rebinding name 'a' and letting the original object stand undisturbed,
> 'a=a+b' is the one obvious way to do THAT.  Not all objects can be
> altered, so the first ones of these tasks isn't always going to be
> feasible, of course.
>
>>
>> or
>>
>>   a = b + c   vs     a = ''.join(b,c)
>
> You should try out the code you post, otherwise you risk ending up with
> code in your face -- ''.join(b, c) will just raise an exception, which
> is a VERY different effect from what b + c will give in most cases.
> I'll be charitable and assume you meant ''.join((a, b)) or something
> like that.
>
> Again, it's only in one very special case that these two very different
> 'ways to do it' produce the same effect, just like in other different
> special cases 'a = b + c' and 'a = c + b' produce the same effect and
> there's nothing Python can do about it.
>
> But let's be sensible: if 'it' is joining two strings which are bound to
> names b and c, b+c is the only OBVIOUS way to do it.  Building a
> sequence whose items are b and c and calling ''.join on it is clearly an
> indirect and roundabout -- therefore NOT "the one obvious way"! -- to
> achieve a result.  Proof: it's so unobvious, unusual, rarely used if
> ever, that you typed entirely wrong code for the purpose...

That is just tradition. Suppose the "+" operator wouldn't have worked
on strings an concatenating would from the start been done by joining,
then that would have been the one obvious way to do it.

> Nobody ever even wished for there to never be two sequences of code with
> the same end-result.  The idea (a target to strive for) is that out of
> all the (probably countable) sequences with that property, ONE stands
> out as so much simpler, clearer, more direct, more obvious, to make that
> sequence the ONE OBVIOUS way.

And what if it are three sequences of code with the same end-result,
or four. From what number isn't it a problem any more if two sequences
of that length or more produce the same result.

> We can't always get even that, as a+b vs
> b+a show when a and b are bound to numbers, but we can sure get closer
> to it by respecting most of GvR's design decisions than by offering
> unfounded, hasty and badly reasoning critiques of them.

I think that this goal of GvR is a bad one. If someway of doing it
is usefull then I think it should be included and the fact that
it introduces more than one obvious way to do some things shouldn't
count for much.

Sure you shouldn't go the perl-way where things seemed to have
been introduced just for the sake of having more than obvious way
to do things. But eliminating possibilities (method chaining)
just because you don't like them and because they would create
more than one obvious way to do things, seems just as bad to
me.

What I have herad about the decorators is that one of the
arguments in favor of decorators is, that you have to
give the name of the function only once, where tradionally
you have to repeat the function name and this can introduce
errors.

But the same argument goes for allowing method chaining.
Without method chaining you have to repeat the name of
the object which can introduce errors.

>
>> The difference between
>>
>>   print somelist.sort()
>>
>> and
>>
>>   somelist.sort()
>>   print somelist
>>
>>
>> is IMO of the same order as the difference between
>>
>>
>>   print a + b
>>
>> and
>>
>>   r = a + b
>>   print r
>
> For a sufficiently gross-grained comparison, sure.  And so?  In the
> second case, if you're not interested in having the value of a+b kept
> around for any subsequent use, then the first approach is the one
> obvious way;

No it isn't because programs evolve. So you may think you don't
need the result later on, but that may change, so writing it
the second way, will making changes easier later on.

> if you ARE, the second, because you've bound a name to it
> (which you might have avoided) so you can reuse it (if you have no
> interest in such reuse, it's not obvious why you've bound any name...).
>
> In the first case, fortunately the first approach is illegal, the second
> one is just fine.  Were they exactly equivalent in effect neither would
> be the one obvious way for all reasonable observer -- some would hate
> the side effect in the first case, some would hate the idea of having
> two statements where one might suffice in the second case.

So? I sometimes get the idea that people here can't cope with
differences in how people code. So any effort must be made
to force people to code in one specific way.

> Fortunately the first approach does NOT do the same thing as the second
> (it prints out None:-) so Python sticks to its design principles.  Let
> me offer a private libation to whatever deities protect programmers,
> that Python was designed by GvR rather than by people able to propose
> analogies such as this last one without following through on all of
> their implications and seeing why this SHOWS Python is consistent in
> applying its own design principles!

That these implications are important is just an implication on the
design principles. If someone doesn't think particular design principles
are that important, he doesn't care that if somethings is changed that
particulat design principle will be violated. Personnaly I'm not
that impressed with the design of python, it is a very usefull language
but having operators like '+=' which have a different kind of result
depending on whether you have a mutable or immutable object is IMO
not such a good design and I wonder what design principle inspired
them.

--
Antoon Pardon

```