杰瑞科技汇

Python xrange和range究竟有何不同?

Of course! This is a classic and very important topic in Python, especially when moving between Python 2 and Python 3.

Python xrange和range究竟有何不同?-图1
(图片来源网络,侵删)

Here's a detailed breakdown of range, xrange, and their relationship.


The Short Answer (TL;DR)

  • In Python 3: There is only range. It is a smart object that generates numbers on-the-fly when you loop over it. It is memory-efficient and fast. You should always use range.
  • In Python 2: There were two types:
    • range: Created an actual list of all numbers in memory. This could be very slow and memory-intensive for large ranges.
    • xrange: A "lazy" object, just like Python 3's range. It generates numbers on-the-fly and is the preferred, memory-efficient choice.
  • Compatibility: If you are writing code that needs to run in both Python 2 and Python 3, you can use the xrange from the six library or a try/except block. However, the best practice is to write code for the Python version you are targeting.

Detailed Explanation

Let's break it down by version.

Python 3: The Modern range()

In Python 3, range is a sequence type, similar to list or tuple, but it's a virtual or lazy sequence.

Key Characteristics of range in Python 3:

  1. It's an Object, Not a List: range(5) doesn't create a list [0, 1, 2, 3, 4] in memory. Instead, it creates a range object that knows how to generate the numbers within that range.
  2. Memory-Efficient: This is the biggest advantage. Whether you do range(10) or range(1_000_000_000), the memory usage is constant. It only stores the start, stop, and step values.
  3. Fast for Large Ranges: Because it doesn't pre-compute all the values, creating a range object is extremely fast, regardless of its size.
  4. Behaves Like a List in Loops: When you use it in a for loop, the range object generates the numbers one by one as the loop asks for them.

Example in Python 3:

# Create a range object. No numbers are generated yet.
r = range(5)
print(r)
# Output: range(0, 5)
# Check its type
print(type(r))
# Output: <class 'range'>
# You can iterate over it, and numbers are generated on demand.
for i in r:
    print(i, end=' ')
# Output: 0 1 2 3 4
# You can convert it to a list if you need to (but this will use memory!)
r_list = list(r)
print(r_list)
# Output: [0, 1, 2, 3, 4]

Python 2: The range() vs. xrange() Distinction

In Python 2, you had a choice, and the choice mattered a lot for performance.

Python xrange和range究竟有何不同?-图2
(图片来源网络,侵删)

range() in Python 2

  • Behavior: It created an actual list in memory containing all the integers from the start to the stop value.
  • Memory Usage: High. For range(1000000), it would create a list with 1,000,000 integers, consuming significant memory.
  • Speed: Slow to create. The time it took to create the list was proportional to the size of the range.
# Python 2
# This creates a full list in memory.
r = range(5)
print(r)
# Output: [0, 1, 2, 3, 4]
print(type(r))
# Output: <type 'list'>
# This would consume a huge amount of memory and be slow.
# huge_list = range(1000000000) 

xrange() in Python 2

  • Behavior: It worked exactly like Python 3's range. It was a "lazy" object that generated numbers on-the-fly.
  • Memory Usage: Very low, just like Python 3's range.
  • Speed: Very fast to create, regardless of the range size.
# Python 2
# This creates an xrange object, not a list.
xr = xrange(5)
print(xr)
# Output: xrange(5)
print(type(xr))
# Output: <type 'xrange'>
# Iterating over it is efficient.
for i in xr:
    print(i, end=' ')
# Output: 0 1 2 3 4

Migration and Compatibility

When Python 3 was released, the xrange object was renamed to range because its behavior was superior and became the standard. The old range behavior was removed.

How to Write Code for Both Python 2 and 3?

If you have legacy code that must run on both, you have a few options.

Option 1: The six Library (Recommended for compatibility libraries)

The six library is a popular tool for writing Python 2/3 compatible code. It provides a six.moves.xrange function that acts like xrange in Python 2 and range in Python 3.

Python xrange和range究竟有何不同?-图3
(图片来源网络,侵删)
# pip install six
import six
# This works in both Python 2 and 3
r = six.moves.xrange(5)
for i in r:
    print(i)

Option 2: try...except Block (A manual approach)

You can try to use xrange and fall back to range if it doesn't exist (i.e., you're in Python 3).

try:
    # This will work in Python 2
    range_obj = xrange(5)
except NameError:
    # xrange doesn't exist, so we must be in Python 3
    range_obj = range(5)
print(list(range_obj)) # [0, 1, 2, 3, 4]

Summary Table

Feature Python 2 range() Python 2 xrange() Python 3 range()
Type list xrange object range object
Memory Usage High (stores all numbers) Low (generates on-the-fly) Low (generates on-the-fly)
Creation Speed Slow for large ranges Very fast Very fast
Python 3 Equivalent Removed (replaced by range object) Renamed to range N/A
Recommendation Avoid, use xrange instead Use this in Python 2 Use this in Python 3

Final Recommendation

  • If you are writing new code, use Python 3. Always use range(). It's the modern, efficient, and correct way.
  • If you are reading or maintaining old Python 2 code, replace range() with xrange() if you care about performance and memory, especially for large numbers.
  • If you are writing a library that must support both Python 2 and 3, use the six library's six.moves.xrange for maximum compatibility.
分享:
扫描分享到社交APP
上一篇
下一篇