Overview
Python 3.0, released on December 3, 2008, is a landmark version of the language. Nicknamed "Python 3000" or "Py3k", this version deliberately breaks backward compatibility with the 2.x branch to fix design flaws that had accumulated since the language's inception.
The goal was ambitious: clean up the language by removing redundancies, unifying types, and modernizing the syntax. This bold decision led to a long transition period during which both branches coexisted, but it laid the foundation for the modern Python we use today.
Major Features
print() becomes a function
The most iconic change in Python 3.0 is the transformation of print from a statement into a function. This choice allows print() to be used like any other function: it can be passed as an argument, replaced, and most importantly, it supports keyword parameters like sep, end, and file.
# Python 2: print was a statement
# print "Hello", "World"
# Python 3: print is a function
print("Hello", "World")
# Hello World
# The sep parameter controls the separator
coordinates = [48.8566, 2.3522]
print("Latitude", coordinates[0], sep=" : ")
# Latitude : 48.8566
# The end parameter prevents the newline
for fruit in ["apple", "pear", "banana"]:
print(fruit, end=" | ")
# apple | pear | banana |
# The file parameter redirects output
with open("journal.log", "w") as f:
print("Starting processing", file=f)
print("Processing complete", file=f)
Unicode strings by default
In Python 3.0, all strings are now Unicode (type str). The bytes type explicitly represents binary data. This clear separation between text and binary data eliminates an entire category of encoding-related bugs.
# Strings are natively Unicode
message = "Caf\u00e9 cr\u00e8me and cr\u00eape au chocolat"
print(message) # Caf\u00e9 cr\u00e8me and cr\u00eape au chocolat
print(len(message)) # 31 (each character counts as 1)
# Clear distinction between text and bytes
text = "R\u00e9sum\u00e9"
raw_bytes = text.encode("utf-8")
print(type(text)) # <class 'str'>
print(type(raw_bytes)) # <class 'bytes'>
print(raw_bytes) # b'R\\xc3\\xa9sum\\xc3\\xa9'
# Reverse conversion
recovered_text = raw_bytes.decode("utf-8")
print(recovered_text) # R\u00e9sum\u00e9
# You can no longer mix text and bytes
# text + raw_bytes # TypeError!
Integer division
In Python 2, dividing two integers returned an integer (floor division). In Python 3.0, the / operator always performs true division, while // performs floor division. This change eliminates a frequent source of errors, especially in scientific computations.
# Python 2: 7 / 2 gave 3
# Python 3: 7 / 2 gives 3.5
# True division (always a float)
result = 7 / 2
print(result) # 3.5
# Floor division (truncation)
integer_result = 7 // 2
print(integer_result) # 3
# Practical example: computing an average
grades = [14, 17, 12, 15, 18]
average = sum(grades) / len(grades)
print(f"Average: {average}") # Average: 15.2
# Practical example: splitting into groups
students = 37
groups = 5
per_group = students // groups
remaining = students % groups
print(f"{per_group} per group, {remaining} remaining")
# 7 per group, 2 remaining
New exception syntax
Python 3.0 replaces the except Exception, e syntax with except Exception as e. This new form is more readable and consistent with the rest of the language. It also allows catching multiple exception types without ambiguity.
# Python 2: except ValueError, e:
# Python 3: except ValueError as e:
def convert_to_integer(value):
"""Convert a value to integer with error handling."""
try:
return int(value)
except ValueError as error:
print(f"Cannot convert: {error}")
return None
# Catching multiple exception types
def read_config(path):
"""Read a configuration file with robust error handling."""
try:
with open(path) as f:
return f.read()
except FileNotFoundError as e:
print(f"File not found: {e.filename}")
except PermissionError as e:
print(f"Permission denied: {e}")
except OSError as e:
print(f"System error: {e}")
return None
print(convert_to_integer("42")) # 42
print(convert_to_integer("abc")) # Cannot convert: ...
# None
Minor Improvements
dict.keys(),dict.values(), anddict.items()now return views instead of lists.map()andfilter()return iterators instead of lists.range()replacesxrange()and returns an efficient sequence object.raw_input()is removed:input()replaces it.- Comparisons between incompatible types raise an exception instead of returning an arbitrary result.
- Octal literals use the
0oprefix (e.g.,0o777instead of0777).
Deprecations and Removals
Python 3.0 removes many obsolete elements:
- Old-style classes are gone: all classes now inherit from
object. - The
longandinttypes are merged into a singleinttype. - The
execkeyword becomes a function. - Backticks (
`x`) for representation are removed in favor ofrepr(x). - The
stringmodule loses its deprecated functions (string.join,string.find, etc.). - The
raise Exception, "message"statement is replaced byraise Exception("message").
