1.3 Python 2 vs Python 3

1.2 History of Python
1.1 Overview of PythonWhat is Python? Python is a high-level, interpreted programming language known for its simplicity, readability, and versatility. Created by Guido van Rossum and first released in 1991, Python is designed to emphasize code readability with its clean and straightforward syntax, making it an ideal language for

Python 2 and Python 3 are two major versions of the Python programming language, but they are not backward-compatible, meaning code written in Python 2 may not work in Python 3 without modifications. Understanding the differences between these versions is crucial for developers who need to work on legacy code or are migrating projects from Python 2 to Python 3. In this section, we’ll explore the key distinctions between the two versions.


1.3.1 Overview of Python 2 and Python 3

  • Python 2: Released in 2000, Python 2 became immensely popular and was widely used in production environments for many years. It brought significant features like garbage collection, list comprehensions, and better memory management. However, Python 2 had certain design limitations, which prompted the development of Python 3.
  • Python 3: Released in 2008, Python 3 was created to address issues and design flaws in Python 2. Although Python 3 introduced many improvements, it was not backward-compatible with Python 2, causing a long transition period as developers migrated their codebases.

As of January 1, 2020, Python 2 is officially no longer supported, and developers are strongly encouraged to use Python 3 for new projects and migrate any existing Python 2 code.


1.3.2 Key Differences Between Python 2 and Python 3

Here are the main differences between Python 2 and Python 3 that developers should be aware of:


1.3.2.1 Print Function

Python 3:
In Python 3, print() is a function that requires parentheses around the arguments.Example in Python 3:

print("Hello, World!")

Python 2:
In Python 2, print is a statement, not a function. This means you can print text without parentheses.Example in Python 2:

print "Hello, World!"

This change enhances consistency across the language, as all built-in operations in Python 3 are functions.


1.3.2.2 Integer Division

Python 3:
In Python 3, dividing two integers using / returns a floating-point result (i.e., it performs true division). To perform integer division in Python 3, you must use //.Example in Python 3:

print(7 / 2)    # Output: 3.5
print(7 // 2)   # Output: 3 (integer division)

Python 2:
In Python 2, dividing two integers using / performs integer division by default, which means the result is an integer (it discards the decimal part).Example in Python 2:

print 7 / 2    # Output: 3 (not 3.5)

This change prevents common bugs that occurred in Python 2 when developers expected floating-point results but received integers.


1.3.2.3 Unicode Support

Python 3:
In Python 3, strings are stored as Unicode by default, and the str type refers to Unicode strings. If you need to work with byte data, you must explicitly use the bytes type.Example in Python 3:

s = "Hello"         # Unicode string
b = b"Hello"        # Bytes string

Python 2:
In Python 2, the default string type (str) is a sequence of bytes, and you need to explicitly define Unicode strings using a u prefix.Example in Python 2:

s = "Hello"         # Bytes string
u = u"Hello"        # Unicode string

This change makes handling text data more consistent and easier in Python 3, especially for non-English characters.


1.3.2.4 Iterators and Generators

Python 3:
In Python 3, range(), zip(), and similar functions return iterators instead of lists. This means that these functions return objects that generate items lazily, which saves memory when dealing with large sequences.Example in Python 3:

r = range(5)    # Creates a range object (not a list)
z = zip([1, 2], [3, 4])  # Creates an iterator (not a list)

Python 2:
In Python 2, functions like range() and zip() return lists. This can cause inefficiency in terms of memory usage, especially when dealing with large data sets.Example in Python 2:

r = range(5)    # Creates a list: [0, 1, 2, 3, 4]
z = zip([1, 2], [3, 4])  # Creates a list of tuples: [(1, 3), (2, 4)]

To convert these iterators to lists, you can use the list() function.


1.3.2.5 Error Handling Syntax

Python 3:
In Python 3, the except block uses the as keyword to catch exceptions.Example in Python 3:

try:
    # some code
except ValueError as e:
    print(e)

Python 2:
In Python 2, the except block uses a comma to catch exceptions.Example in Python 2:

try:
    # some code
except ValueError, e:
    print e

This change makes the syntax clearer and more in line with other parts of the language.


1.3.2.6 Input Function

Python 3:
In Python 3, the input() function always returns a string, and there’s no raw_input(). If you need to convert the input to another type (e.g., an integer), you must explicitly do so.Example in Python 3:

name = input("Enter your name: ")       # Always returns a string
age = int(input("Enter your age: "))    # Explicit type conversion

Python 2:
In Python 2, input() evaluates the user input as code, which can lead to potential security risks. To safely accept string input, you need to use raw_input().Example in Python 2:

name = raw_input("Enter your name: ")   # Safe string input
age = input("Enter your age: ")         # Evaluates input

This change eliminates the security risks associated with the Python 2 input() function.


1.3.2.7 Libraries and Compatibility

  • Python 2:
    During its peak, Python 2 had a large ecosystem of libraries that were specifically developed for it. However, many of these libraries were not immediately compatible with Python 3.
  • Python 3:
    By 2020, the vast majority of popular Python libraries are compatible with Python 3, and many are exclusively developed for Python 3. Libraries such as NumPy, Pandas, TensorFlow, and Django now fully support Python 3, and development on Python 2-specific versions has ceased.

1.3.2.8 xrange() vs range()

Python 3:
In Python 3, xrange() was removed, and range() now behaves like xrange() in Python 2, returning an iterator.Example in Python 3:

r = range(5)      # Range object (iterator, not a list)

Python 2:
Python 2 has two functions for generating sequences: range() (which returns a list) and xrange() (which returns an iterator).Example in Python 2:

r = range(5)      # [0, 1, 2, 3, 4]
xr = xrange(5)    # xrange object (iterator)

This change simplifies the language by reducing redundancy.


1.3.3 Migration from Python 2 to Python 3

Migrating from Python 2 to Python 3 can involve changes to syntax, data types, and library compatibility. Tools like 2to3 can help automate much of the migration process by translating Python 2 code into Python 3 code.

  • Common Migration Steps:
    1. Use the 2to3 tool to analyze and modify your Python 2 code.
    2. Test your code in Python 3 and resolve any compatibility issues.
    3. Review changes in key areas such as string handling, division, and libraries.
    4. Update third-party libraries to their Python 3-compatible versions.

1.3.4 Conclusion: Why Python 3 is the Future

Python 3 is the future of the Python language. Its