This article is a monthly feature article on digging Python

There is a popular saying that “dynamic typing is good for a while, code refactoring is a crematorium.” This is often said by advocates of static languages. It sounds a bit scary, but it’s not as serious as you might think.

Python, as a dynamic language, does not need to specify data types when defining variables, function return values and method parameters, which to some extent makes code extremely concise and flexible, regardless of program operation efficiency. However, dynamic language also has disadvantages, such as:

The IDE does not know what properties and methods a variable has because it cannot determine the type of the variable. It is very painful for the IDE to have no intelligent prompt. For example, the impression is that STR has a startwith method, but the correct way to write it is startswith, with an S. I have to look up a file. (But I suggest beginners or old honest utility editor hand knock code, in order to deepen memory)

2, during compilation, only syntax errors can be found, and type mismatches can only be known when the program is actually running. It can be circumvented by unit testing, but wouldn’t it be nice if we had an IDE to point us through during code writing?

3. Interface calls depend entirely on the documentation. When calling a method or function, the return value and parameter type description can only be determined according to the documentation. While we can ask programmers to use docStrings or comments to specify function parameter types and return value types, the problem is that even if you write a docString properly in the first place, your docString may not be synchronized after the code is updated.

These problems are particularly acute in large projects, especially those involving multiple people. Code specification, Code Review becomes more important. Because of these issues, the community is increasingly calling for the introduction of static typing features, which is why Type Hints are in Python3.5, also known as PEP484. When you define a function, you can specify the return value type and parameter type of the function.

I used to write a function like this:

def greeting(name):
    return "Hello" + name

>>> greeting("bob")
'Hellobob'
>>> greeting(1)
TypeError: must be str, not int
Copy the code

When you don’t look at the documentation or source code, you don’t know what type of value you can pass in, and when you pass in the integer 1, you won’t find the error until the program is running. A datatype checker that checks before the program starts can prevent errors.

In Python3.5, a Type Hint is written like this:

def greeting(name: str) -> str:
    return 'Hello ' + name
Copy the code

Statically typed: STR (” : STR “); STR (” -> STR “); STR (” : STR “); As a result, IDE tools like PyCharm can spot code problems in real time.

Of course, in addition to the IDE, we have a more powerful static type checking tool called mypy, which is also implemented by The father of Python GUido himself static type checking tool.

pip install mypy

$ mypy test.py
test.py:4: error: Argument 1 to "greeting" has incompatible type "int"; expected "str"
Copy the code

Type hinting, Python code calls, refactoring, even is a static analysis, etc have a better effect, not only reduce the burden of the development type checks on its own, and, more importantly, because of the type of tips, let the past Python integrated development tools on various smart tips, refactoring, and other functions do not have a unified reference standard.

In a sense, the type hint is just an auxiliary feature. Although we add the data type hint, the Python interpreter ignores the type hint directly and does not prevent the program from running even if the type is wrong.

For the type of variable, PEP484 can explain it through type annotation, that is, to explain the type of variable in the way of annotation, for example:

from typing import List

x = []                # type: List[Employee]
y = [1.2]            # type: List[int]
y.append("a")
Copy the code

The above type comment indicates that x must be a list of Employee objects and y must be a list of ints. After appending a string to the list of integers y, we use mypy to check what’s wrong with the code:

mypy test.py
xx.py:3: error: Name 'Employee' is not defined
xx.py:5: error: Argument 1 to "append" of "list" has incompatible type "str"; expected "int"
Copy the code

In Python3.6, also known as PEP526, variable annotations were further optimized to include type declarations as part of the syntax, making them more readable than comments, for example:

my_var: int  A variable declared as an integer
my_var = 5  Pass type checking
other_var: int = 'a'  The inspector will report an error when assigning a string to an integer variable, but the interpreter will run without any problems
print(other_var)
Copy the code
mypy xx.py  Run the type checker
xx.py:3: error: Incompatible types in assignment (expression has type "str", variable has type "int")

python test.py Run the interpreter
a
Copy the code

While type hints make IDE intelligence hints and refactoring very convenient, it is precisely because of these type information declarations that dynamic languages become bloated. For example:

T = TypeVar('T')
S = TypeVar('S')
class Foo(Generic[T]):
    def method(self, x: T, y: S) -> S:
    # Body
Copy the code

This is a generic annotation that looks like Java code. Ironically, Java is also beginning to add dynamic language features, such as local variable type inference in Java10, which allows variables to be defined using the keyword var without specifying data types, meaning that static languages are also beginning to develop dynamic language features.

public class VarTest {

    public static void main(String[] args) {
        var name = "java"; System.out.println(name); }}Copy the code

Java and Python are the representatives of static and dynamic languages respectively. One obvious feature is that they both learn from each other’s advantages. It is said that the world is in a trend. No language is perfect, and Python is flexible but less controllable, more like an open parent, giving developers the most freedom in what they do with the language. After all, We are all consenting adults! Java, on the other hand, is like a strict parent who treats every developer with kid gloves, afraid you’ll get in trouble.