I’ve been using Python 3.7 for weeks so it was a shock to discover that it is a release candidate no more – it’s officially the new Python 3.
The road from Python 2 to 3 has been a long and fairly gentle one. If you really couldn’t move to Python 3 for one reason or another then you have been well served by the ongoing Python 2 development line. But now enough is enough. Python 3 is mature and this is proved by the welcome, but not major, changes and additions to Python 3.7. This is good because only bored programmers want a language that is developing so fast that the thrill is in trying to keep up. Yes, I suppose I am saying Python is getting old.
So what is new in 3.7?
The most important addition for the average programmer is the addition of data classes. Sometimes you just want to create a class so that it can be used to store data. In other languages you would call such an object a “struct” or a “record type”. Java is about to get data classes and Kotlin already has them, for example. Python’s data classes give you a decorator way of creating classes that are ready to work with data. You simply add @dataclass in front of a class definition and then list all the data fields you want to use. Each field is a variable name followed by a type annotation. The decorator converts this into a class definition with a suitable __init__ so you can correctly initialize the fields when you create an instance. You can also modify the way the fields are created using the field helper function. What is impressive is that this additional data type has been implemented using nothing but Python.
Talking of type annotations, 3.7 adds forward references and improves the speed of operation. I have mixed feelings about type annotations. They start out being useful, for example when you describe the signature of a function, but quickly become complex and difficult to get right. Not having to deal with generics and variance is one of the advantages of Python – adding them back in, even as an optional feature, isn’t an obvious improvement.
Another big feature is the ability to work with attributes defined on modules. You can now use __getattr__ and __dir__ on modules. This logically makes modules look like “bigger” classes, which is more or less what they are.
A smaller feature, in the sense that ns is smaller than ms, is the increased precision of the timing package. You can now use functions in the time module to get nanosecond accuracy returned as an integer.
Now we get to the really small improvements:
- Dictionary order is now specified as part of the language and iterators work in the order that objects were added.
- async and await are keywords and if you used a variable with either of these names you deserve the problem that results.
- The asyncio module has been revamped.
- New context variables provide thread local storage for asynchronous tasks.
- A new C API for thread local storage.
Among the major new features in Python 3.7 are:
- PEP 539, new C API for thread-local storage
- PEP 545, Python documentation translations
- New documentation translations: Japanese, French, and Korean.
- PEP 552, Deterministic pyc files
- PEP 553, Built-in breakpoint()
- PEP 557, Data Classes
- PEP 560, Core support for typing module and generic types
- PEP 562, Customization of access to module attributes
- PEP 563, Postponed evaluation of annotations
- PEP 564, Time functions with nanosecond resolution
- PEP 565, Improved DeprecationWarning handling
- PEP 567, Context Variables
- Avoiding the use of ASCII as a default text encoding (PEP 538, legacy C locale coercion and PEP 540, forced UTF-8 runtime mode)
- The insertion-order preservation nature of dict objects is now an official part of the Python language spec.
- Notable performance improvements in many areas.
Please see What’s New In Python 3.7 for more information.
Finally there are speedups – calling the standard library is faster; method calls are faster; and startup is faster.
Python 3.7 is out now and there are no good reasons not to use it and many of the new features work with 3.6.