On Sat, Jan 08, 2022 at 06:30:53PM -0800, Ethan Furman wrote:
> On 1/8/22 5:46 PM, Steven D'Aprano wrote:
> 
> > [...] if you hate type annotations because they are unreadable, then you
> > hate Python because Python is unreadable.
> 
> Not so.

Are you disputing that annotations use the same syntax as other Python 
expressions? If not, I don't see how you can deny that "type annotations 
are unreadable" implies "Python expressions are unreadable", which in 
turn implies "Python is unreadable".


> A simple list comprehension is (usually) quite readable, while a 
> triply-nested list comprehension all on one line is not.

Indeed. We can abuse any syntax. So do we conclude that comprehensions 
are "unreadable" because we can write obfuscated triply-nested list 
comprehensions?


> Similarly, adding type information in between a variable name and its value 
> is not (for me, and apparently others too) readable.

I think that "unreadable" or "not readable" is a complaint that gets 
overused, often for the most trivial cases, to the point that it loses 
all credibility. Especially when it comes from people who are fluent in 
C (which may not be you, Ethan).

http://unixwiz.net/techtips/reading-cdecl.html

"Easily learned", huh. I think that this is one of the clearest examples 
of the curse of knowledge as it applies to programming that one could 
hope to find.

Anyway, let's compare:

    # C
    int n = 44;

    # Pascal
    var
      n: integer;
    n := 44;

    # Typescript
    var n: number = 44;

    # Java
    int n = 44;

    # Python
    n: int = 44


There are millions who find the C, Pascal, TypeScript and Java perfectly 
readable. I don't find it credible that people are incapable of 
reading the last one.

Aside: such a type hint is redundant, as mypy is perfectly capable of 
inferring that n = 44 makes n an int. Style guides should recommend 
against such redundancy, and I would certainly flag that in a code 
review. A better example of a *useful* type hint would be:

    L: list[str] = []


 
> Most horribly of all, cluttering a function header with type information is 
> most unreadable.

I hear you. Adding redundant or unnecessary type hints to parameters 
just for the sake of having type hints is just clutter, especially if 
they are never tested by actually running a type checker over the file.

(Untested code is broken code. If not right now, it soon will be.)

Fortunately, we have *gradual typing*, and nobody should be forced to 
use type hints in their projects if they don't want them. Just as we 
don't make linters mandatory, we don't make typing mandatory either.

I think that, outside of very simple functions, once we make the 
decision to annotate a function, we should space them out:

    # Better
    def func(spam: list[str], 
             eggs: float, 
             cheese: str = 'cheddar', 
             aardvark: str|bytes = "", 
             eels: Optional[Tuple[int, str]] = None
             ) -> Hovercraft:


which makes them much easier to read.

Trying to cram them all into one line is abuse of the syntax every bit 
as bad as cramming a triply-nested list comp into one line:


    # Worse
    def func(spam: list[str], eggs: float, cheese: str = 'cheddar', aardvark: 
str|bytes = "", eels: Optional[Tuple[int, str]] = None) -> Hovercraft:


I can read it, I just don't want to. It is too much like hard work 
compared to the previous layout.

Even if you don't run a type-checker, those annotations can make useful 
documentation. (At least *sometimes*.) If the parameter name doesn't 
make it clear what types are allowed, then the annotation can make it 
clear. So if you don't use a static checker, you can think of type 
annotations as introspectable documentation.


> I started using Python at 2.5.  It was simple, clean, and elegant.

And I started using Python at 1.5, when the syntax was even simpler and 
cleaner. And to this day I will never forget the first time I read 
Python code, after being told repeatedly how easy to read it, and I 
couldn't make head or tails of it. All those colons and square brackets, 
it might as well have been APL. (Not that I knew what APL was back 
then.)

I knew what a for-loop was, from Pascal, Hypertalk and HP RPN 
calculators:

    # Pascal
    for i := 0 to 10 do 
      begin
        block;
      end;

    # Hypertalk
    repeat with i = 0 to 10
      block
    end repeat

    # HP-48 RPN language
    0 10 FOR I block NEXT

but I kept seeing loops like this in Python:

    for i in range(11):

or worse:

    for somename in [stuff, thing, another_thing, widget]:

and worse of all:

    for somename in values[1:-1]:

Python for loops looked nothing like any for loop I had seen before, and 
they freaked me out, and at the time (early 1990s) there was no publicly 
available internet where I could look anything up or ask for help.

And then there were the brackets. Why does Python sometimes use round 
brackets, sometimes curly brackets, and sometimes square brackets? x[a] 
versus x(a)? Why were there sometimes colons inside square brackets and 
curly brackets {a:b} but never inside round brackets? What was the 
difference between [1, 2, 3] and (1, 2, 3)?

The whole thing was intimidating, and I just put Python away for about a 
year and didn't look at it again until I had bought Mark Lutz' "Python 
Pocket Reference" which helped me make sense of it all. That and his 
"Learning Python". And never looked back. (Since then, I've often felt 
that Python has spoiled me from learning other languages. 

The point I am making here is not that I was a dimwit who couldn't even 
read Python, but that "easy to read" and "readable" is more a matter of 
familiarity than an inherent property of the language itself. With 
enough familiarity, even APL is easy to read.


> If I 
> had stumbled on it at 3.16 with samples, tutorials, and books all infused 
> with typing clutter (which *looks* like boiler-plate even if it isn't) I 
> wouldn't have given it a second glance.

And again, I hear you. I too wish people would tone down their 
enthusiasm for adding typing to examples that don't need type hints.

We should remember that type hints are a feature aimed at large code 
bases, where static typing really is valuable. For three line example 
functions, not so much, not even as documentation.


-- 
Steve
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/35G7WXSHOB3G7GPNLIVWXZ27RZZC2VRM/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to