杰瑞科技汇

Python dict 的顺序是固定的吗?

Of course! This is a fundamental concept in modern Python that has changed significantly between versions. Here’s a complete guide to dictionary ordering in Python.

The Short Answer (TL;DR)

In Python 3.7 and newer, dictionaries preserve insertion order. This is a guaranteed language feature, not just an implementation detail.

  • What you put in is what you get out, when you iterate over the keys, values, or items.
  • This applies to all modern versions of Python (3.7, 3.8, 3.9, 3.10, 3.11, 3.12).

The Detailed Explanation

Let's break it down by Python version and look at the key concepts.

Python 3.7 and Later: Guaranteed Insertion Order

This is the current standard. You can rely on the fact that a dictionary will remember the order in which you added its key-value pairs.

Example:

# In Python 3.7+
user_info = {}
user_info['name'] = 'Alice'
user_info['age'] = 30
user_info['city'] = 'New York'
# When you iterate, the order is preserved
for key in user_info:
    print(key)
# Output:
# name
# age
# city
# You can also see the order when you print the dict directly
print(user_info)
# Output (on most Python versions):
# {'name': 'Alice', 'age': 30, 'city': 'New York'}

Why did this change?

  • Python 3.6: The order preservation was an implementation detail of the CPython interpreter. It worked, but you shouldn't have relied on it in your code, as other implementations (like PyPy or Jython) might not have behaved the same way.
  • Python 3.7: The order preservation became a guaranteed feature of the language. The official documentation was updated to state that dict objects now preserve insertion order.

Python 3.6 and Earlier: No Order Guarantee

In versions before 3.7, dictionaries were unordered. The order of keys when you iterated over a dictionary was essentially arbitrary and could change between different runs of your program, or even between different operations on the same dictionary.

Example (simulating old behavior):

# In Python 3.5 or earlier
# The order you see might be different every time you run this.
my_dict = {'c': 3, 'a': 1, 'b': 2}
for key in my_dict:
    print(key)
# Possible Output 1:
# c
# a
# b
# Possible Output 2 (if the dictionary was rebuilt):
# a
# b
# c

Why were they unordered? Dictionaries historically used a hash table for fast lookups. The order of items in the hash table depended on the hash values of the keys and the internal state of the hash table, which was not related to the insertion order.


How Does Ordering Affect Dictionary Operations?

Order preservation has some interesting side effects.

a) Deleting and Re-adding a Key

If you delete a key and then add it back, it goes to the end of the dictionary.

d = {'a': 1, 'b': 2, 'c': 3}
print(d)  # {'a': 1, 'b': 2, 'c': 3}
del d['b']
print(d)  # {'a': 1, 'c': 3}
d['b'] = 2 # 'b' is added to the end
print(d)  # {'a': 1, 'c': 3, 'b': 2}

b) Updating an Existing Key

If you update the value of an existing key, its position in the order does not change.

d = {'a': 1, 'b': 2, 'c': 3}
print(d)  # {'a': 1, 'b': 2, 'c': 3}
d['b'] = 99 # The key 'b' already exists
print(d)  # {'a': 1, 'b': 99, 'c': 3}  # Order is unchanged

c) dict.update() Method

The update() method respects the order of both dictionaries. New keys from the updated dictionary are appended to the end.

d1 = {'a': 1, 'b': 2}
d2 = {'c': 3, 'a': 100} # Note 'a' already exists in d1
d1.update(d2)
print(d1)
# Output:
# {'a': 100, 'b': 2, 'c': 3}
# 'a' was updated in-place (order stays)
# 'c' was added to the end

What About Sorting a Dictionary?

Sometimes you don't want the original insertion order; you want to sort the dictionary by its keys or values. Since dictionaries themselves are not "sorted" objects, the standard way to do this is to create a new dictionary from a sorted list of its items.

The sorted() function is your best friend here.

Example: Sorting by Keys

unsorted_dict = {'banana': 3, 'apple': 1, 'pear': 2, 'orange': 4}
# sorted() on a dict iterates over its keys by default
sorted_keys = sorted(unsorted_dict)
print(sorted_keys)
# Output: ['apple', 'banana', 'orange', 'pear']
# Create a new dictionary from the sorted key-value pairs
sorted_by_key = {k: unsorted_dict[k] for k in sorted_keys}
print(sorted_by_key)
# Output: {'apple': 1, 'banana': 3, 'orange': 4, 'pear': 2}

A more common and "Pythonic" way to do this is with dict.items() and a lambda function.

unsorted_dict = {'banana': 3, 'apple': 1, 'pear': 2, 'orange': 4}
# Sort by key (the first element of each tuple)
sorted_by_key = dict(sorted(unsorted_dict.items(), key=lambda item: item[0]))
print(sorted_by_key)
# Output: {'apple': 1, 'banana': 3, 'orange': 4, 'pear': 2}

Example: Sorting by Values

unsorted_dict = {'banana': 3, 'apple': 1, 'pear': 2, 'orange': 4}
# Sort by value (the second element of each tuple)
sorted_by_value = dict(sorted(unsorted_dict.items(), key=lambda item: item[1]))
print(sorted_by_value)
# Output: {'apple': 1, 'pear': 2, 'banana': 3, 'orange': 4}

Other "Ordered" Dictionary Types

While standard dict is now ordered, you might still encounter these two types.

collections.OrderedDict

This was the pre-3.7 solution for creating ordered dictionaries. It's part of the collections module.

  • In Python 3.7+: You don't need OrderedDict for simple insertion order. A standard dict is faster and more idiomatic.
  • When to use it today: OrderedDict still has one feature that dict doesn't: it remembers the order in which items were last inserted or moved. This can be useful in specific caching scenarios.
from collections import OrderedDict
# A regular dict (Python 3.7+) also remembers insertion order
d = {}
d['a'] = 1
d['b'] = 2
d['c'] = 3
d.move_to_end('a') # This method doesn't exist on a regular dict!
print(d) # Raises AttributeError
# An OrderedDict does this correctly
od = OrderedDict()
od['a'] = 1
od['b'] = 2
od['c'] = 3
od.move_to_end('a') # Moves 'a' to the end
print(od)
# Output: OrderedDict([('b', 2), ('c', 3), ('a', 1)])

dict vs. defaultdict vs. OrderedDict

  • dict: Standard, unordered (pre-3.6), ordered by insertion (3.7+).
  • defaultdict: A subclass of dict that calls a factory function to supply a default value for a missing key. It is ordered just like a dict.
  • OrderedDict: A subclass of dict that remembers insertion order (and move order). Slower than a standard dict.

Summary Table

Feature Python 3.7+ Python 3.6 and Earlier
Order Guarantee Guaranteed (Language Feature) Not Guaranteed (Implementation Detail)
dict Type Preserves insertion order. Unordered.
del and re-add Item moves to the end. Behavior is undefined.
update() Appends new keys to the end. Behavior is undefined.
Primary Use Case The default, go-to dictionary. Use collections.OrderedDict if order is critical.
Sorting Use sorted(dict.items(), key=...) to create a new sorted dict. Same method.
分享:
扫描分享到社交APP
上一篇
下一篇