Strong typing implementation for Python

Josef Pktd josef.pktd at gmail.com
Tue Oct 13 20:26:02 EDT 2015


On Tuesday, October 13, 2015 at 9:40:56 AM UTC-4, Steven D'Aprano wrote:
> On Tue, 13 Oct 2015 06:55 pm, Todd wrote:
> 
> > On Oct 13, 2015 2:11 AM, "Steven D'Aprano" <...> wrote:
> 
> >> Consider the following piece of code:
> >>
> >> def addone(x):
> >>     return x + 1
> >>
> >>
> >> The human programmer reading that can trivially infer that x must be a
> >> number (or at least something which supports numeric addition). So can
> >> the compiler. In a strongly typed language with no numeric promotion, the
> >> compiler can infer that x must be an int. In a language with numeric
> >> promotion, it can infer that x must be an int or float.
> > 
> > Or a decimal, complex number, numpy array, any one of a dozen or so pandas
> > classes, any one of the dozen or so units classes, sympy variable, etc...

A good example is `y = x * 2` followed by long calculations with y.

I have no idea what this does if I don't know the type of x.
(list and tuples get duplicated, arrays as in numpy or pandas multiply elementwise, matrix packages use dot (@) product. Two out of three will give us the wrong result but don't raise a runtime exception.)

The flip side of the flexibility with dynamic typing is that we spend a lot of time and effort in asserting or converting types.

There are cases when being able to quack is not enough, it needs to have the right quack. And when we allow for different sounds created by the duck look-a-likes, then code can get complicated and avoiding subtle mistakes will become very difficult.

Annotations might help the editors, but doesn't enforce the right behavior.
Also, in some cases we don't want to restrict ducktyping in the function or method arguments but we need to protect our calculations. Function annotations won't help her.

One common pattern then guarantees fixed types within a function:

def calculate_something(x):

    <save the class of x>
    x = numpy.asarray(x, numpy.float64)  # convert anything array_like to array

    do calculations that only use numpy arrays

    <convert result back to something corresponding to original class of x>
    return result

In the center we have static types (as far as numpy arrays are static), and we don't have to guess on what methods are actually doing, and code inspection could infer this.

Outside we still have all the flexibility of duck typing.

I guess it's gradual typing but not through unenforced function annotations.

Josef


> 
> I knew my over-simplification would get me in trouble...
> 
> Firstly, if we're talking about Python specifically, the compiler won't
> actually infer anything (see PEP 484, which "assumes the existence of a
> separate off-line type checker which users can run over their source code
> voluntarily"). It is up to the external type checker (or linter, IDE,
> documentation generator, refactoring tool, etc) to perform any type checks.
> 
> Secondly, what the tool actually infers will depend on the tool. I would
> expect that a basic type checker (say, in a text editor) will infer that x
> is an int or float only. A more powerful checker might infer the Number ABC
> (Abstract Base Class). A specialist checker might even know about numpy,
> pandas, units and sympy, but I wouldn't expect a general-purpose type
> checker to infer them.
> 
> If the programmer cares about such specialist types, then she can easily add
> type hints to supplement the checker's type inference, or the checker
> itself may be configurable. That's a *quality of implementation* detail.
> 
> The beauty of *gradual typing* is that you don't have to care about every
> possible class in the entire universe of Python code, only about the
> classes you actually care about in the parts of your code you choose to
> type check.
> 
> http://wphomes.soic.indiana.edu/jsiek/what-is-gradual-typing/
> 
> Because the Python interpreter itself doesn't care about the compile-time
> type checking, if the checker gets in your way, you can just *not run it*.
> I also expect that good checkers will include directives to skip sections
> of code, so you can include annotations as documentation while still
> silencing over-strict or incorrect compile-time type errors. (Runtime type
> errors will still occur as normal.)
> 
> 
> 
> -- 
> Steven




More information about the Python-list mailing list