Overview
Python 3.1, released on June 27, 2009, is the first improvement release of the 3.x branch. While Python 3.0 had broken compatibility to clean up the language, Python 3.1 focuses on performance and stability.
It is a relatively modest release in terms of new features, but it brings highly anticipated additions like OrderedDict and the int.bit_length() method. The I/O module also receives significant performance improvements.
Major Features
OrderedDict
The collections module gains an OrderedDict, a dictionary that preserves the insertion order of keys. It is a valuable tool for processing configuration files, JSON serialization with a predictable order, or creating simple LRU-style caches.
from collections import OrderedDict
# Configuration with guaranteed ordering
config = OrderedDict()
config["host"] = "localhost"
config["port"] = 5432
config["database"] = "my_db"
config["user"] = "admin"
# Order is always preserved
for key, value in config.items():
print(f"{key} = {value}")
# host = localhost
# port = 5432
# database = my_db
# user = admin
# Preserving order during a JSON round-trip
import json
json_data = '{"name": "Martin", "age": 35, "city": "Lyon"}'
result = json.loads(json_data, object_pairs_hook=OrderedDict)
print(list(result.keys())) # ['name', 'age', 'city']
# Moving an element to the end of the dictionary
config.move_to_end("host")
print(list(config.keys())) # ['port', 'database', 'user', 'host']
int.bit_length()
The int.bit_length() method returns the number of bits needed to represent an integer in binary, excluding the sign and leading zeros. This is useful for determining minimum storage sizes or for bit-manipulation algorithms.
# Number of bits needed to represent an integer
print((0).bit_length()) # 0
print((1).bit_length()) # 1
print((7).bit_length()) # 3 (binary: 111)
print((255).bit_length()) # 8 (binary: 11111111)
print((256).bit_length()) # 9 (binary: 100000000)
# Practical application: determine the minimal storage type
def minimal_storage_type(value):
"""Determine the smallest integer type to store a value."""
bits = value.bit_length()
if bits <= 8:
return "uint8"
elif bits <= 16:
return "uint16"
elif bits <= 32:
return "uint32"
else:
return "uint64"
values = [42, 300, 70000, 5000000000]
for v in values:
print(f"{v:>12} -> {v.bit_length():>2} bits -> {minimal_storage_type(v)}")
# 42 -> 6 bits -> uint8
# 300 -> 9 bits -> uint16
# 70000 -> 17 bits -> uint32
# 5000000000 -> 33 bits -> uint64
Improved io module
The io module, introduced in Python 3.0, receives significant performance improvements in Python 3.1. File read and write operations are noticeably faster, which was a frequent complaint about Python 3.0.
# Writing and reading in text mode (str)
with open("example.txt", "w", encoding="utf-8") as f:
f.write("First line\n")
f.write("Accented characters: \u00e9\u00e8\u00ea\n")
with open("example.txt", "r", encoding="utf-8") as f:
content = f.read()
print(type(content)) # <class 'str'>
# Writing and reading in binary mode (bytes)
data = bytes(range(256))
with open("data.bin", "wb") as f:
f.write(data)
with open("data.bin", "rb") as f:
binary_content = f.read()
print(type(binary_content)) # <class 'bytes'>
print(len(binary_content)) # 256
# The io module also allows working in-memory
import io
buffer = io.StringIO()
buffer.write("temporary data\n")
buffer.write("in memory\n")
print(buffer.getvalue())
# temporary data
# in memory
Minor Improvements
- Floating-point numbers are now displayed with the shortest representation that allows exact reconstruction (e.g.,
1.1instead of1.1000000000000001). - The
unittestmodule gains theassertAlmostEqualmethod and other useful assertions. - The
jsonmodule accepts theobject_pairs_hookparameter to control the dictionary type used during decoding. - Module imports are slightly faster.
.pycfiles can be executed directly if the corresponding.pyfile does not exist.
Deprecations and Removals
Python 3.1 does not remove major features, as the bulk of the cleanup was done in Python 3.0. A few notable points:
- The
compilermodule is permanently removed. - Several obsolete methods in the
unittestmodule are marked as deprecated (such asassertEqualsin favor ofassertEqual). contextlib.nestedis deprecated in favor of the multiplewithstatement syntax.
