Python 3.6 is now officially available. This release brings many new syntax features, including formatted string literals and underscores in numeric variables. Significant improvements in CPython implementation and standard library have also been made.

Today, Python is one of the most used programming languages, and it’s enjoying an extensive growth in different fields of technology. Just in case you’re wishing to know more about Python’s strength, go ahead and read this article.

Python 3.6 is now officially available. Compared to version 3.5, Python 3.6 brings many new features, additional security measures, and tries to make things more productive and easy for developers. This article presents a short overview of the Python 3.6 features and syntax additions. Let’s take a look:

Python 3.6 Features

The version 3.6 introduces some important syntax features —

Formatted string literals: These are new kind of string literals, also called f-strings. They are prefixed with ‘f’ and contain certain replacement fields surrounded by {}. The replacement fields are expressions that are evaluated at runtime and formatted using format() protocol.

Underscores in numeric literals: For better readability, Python 3.6 brings the ability to use underscores in numeric literals. Now, single underscores can be used between digits and after any base specified.

Syntax for variable annotations: Here, we’re talking about the standard for type annotations of function parameters. This adds the syntax for annotating different types of variables

Asynchronous generators: Python 3.6 improves the support for native coroutines and sync / await syntax introduced in Python 3.5. Now, one can use await and yield in the same function body.

Asynchronous comprehensions: There’s support for using async for in the list, set, dict comprehensions and generator expressions. Also, await expressions are now supported in all types of comprehensions.

Python 3.6 also adds new library modules, CPython implementation improvements, and many security enhancements.

You can visit Python 3.6 What’s new page to know about all the changes in detail.

Python 3.6 Lifespan

This version will continue receiving bugfixes every 3-6 months for the next 18 months. After Python 3.7 release, a final 3.6 bug fix will be released. After that, 3.6 is expected to get security updates until December 2021.

Did you find the new features of Python 3.6? Don’t forget to share your views in the comments section below.

What: With Python 3.6, the async and await keywords in Python can now be used inside generators and comprehensions, instead of simply to decorate functions.

Why: Processing that normally involves long delays, such as reading from a network socket, can now be done without holding up the rest of the app — and via syntax built into the language.

The nitty-gritty: Earlier versions of Python allowed developers to build functions that could run asynchronously, without blocking each other, but not in a particularly elegant manner. Python 3.5 introduced asynchronous behavior to Python’s syntax through the async and await keywords. Now Python 3.6 has extended async and await to work in two other major parts of Python: generators and comprehensions.

Generators are functions that yield values iteratively, like a list that’s computed on demand. When paired with async syntax, generators can be used to concisely create functions that yield values when external conditions are met. Python’s documentation provides this as an example:

"""Yield numbers from 0 to *to* every *delay* seconds."""
for i in range(to):
await asyncio.sleep(delay)

Comprehensions let you assemble data structures like lists or dictionaries using a concise syntax. The async/await syntax can now be used in the context of a comprehension:

result = [i async for i in aiter()]

This would append the output of the function aiter() to the list result as values are yielded from the asynchronous function. With this it’s possible to use asynchronous syntax within functions like Python lambdas or simply as a convenient option to condense the syntax of a list declaration.

Other major changes in this vein elevate the status of asyncio, a Python library used to perform asynchronous I/O such as reading from network sockets. Bearing new and refined methods, asyncio becomes a full-blown member of Python’s standard library; before it was included provisionally while its API was being nailed down.

Note that the async/await keywords aren’t really a replacement for asyncio. As core Python developer Brett Cannon has pointed outasync/await can be used to create all kinds of asynchronous behaviors; asyncio is only one of the many ways async/await can be put to use.

Speed and memory usage improvements

What: Python 3.6 introduces a number of improvements that render CPython, the default implementation of the Python runtime, both faster and more economical with memory — without breaking backward compatibility.

Why: Python has traditionally been slower than C by an order of magnitude or more, but attempts to dramatically speed up Python tend to come at the expense of compatibility. The increased quickness in Python 3.6 aren’t warp-speed improvements, but they help. Any changes that help Python use a little less memory are welcome as well, especially when dealing with applications that create large data structures.

The best part is that developers can make use of these improvements in speed and memory efficiency with little or no reworking of existing Python code. They come for free.

The nitty-gritty: The performance optimizations in Python 3.6 come through bytecode parsing improvements, faster function calling, and more efficient dictionaries.

Bytecode speedups. Python scripts are compiled to cached bytecode to speed execution. As a result, many optimizations of Python have focused on making the bytecode faster to parse. A slew of improvements has landed in Python 3.6 around bytecode, such as using a 16-bit format for bytecode, providing more opcodes for common use cases (essentially, condensing several instructions into one), simplifying some opcodes to remove less-used ones, and simplifying the interpreter loop that handles bytecodes.

The improvements aren’t dramatic — a fraction of a percent here and there across various benchmarks. But those slivers of improvement add up over time, and they come for free. That is, the only effort the developer has to make is to migrate to the newest version of the language runtime.

The one place where these changes break compatibility is with anything that works directly with Python bytecode. That said, Python has never guaranteed bytecode compatibility across versions, so this is well within the scope of what seasoned Python devs can expect from any major revision of the language.

Faster function calling. Core Python developer Victor Stinner has made speeding up CPython a big part of his work with the language. One of his projects, which landed in Python 3.6, amounts to a faster option to perform function calls in the language.

Tests show the improvement isn’t enormous, but they’re measurable and demonstrably faster than Python 2.x, so it works to defray a common criticism that the “new” Python is less performant than the “old” one. Such criticisms have lent legitimacy to the idea that Python 2.x is worth keeping alive. (At least one project is working to keep Python 2.x current in the face of eventually losing official support.)

If you use Cython, the Python library that compiles Python code to C, note that it has been updated to take advantage of the this new calling convention.

More efficient dictionaries. Python dictionaries, or the dict type, are an efficient method to store information by way of key/value pairs. The folks at the PyPy project, the just-in-time compiled version of Python that many look to as a quick speed-up for the language, created their own implementation of dict that was faster and used up to 25 percent less memory. It was an impressive achievement — so impressive that it got ported back into the mainline version of the language.