Of course! Let's break down "little endian" in Python, from the basic concept to practical code examples.

What is Endianness?
At its core, endianness is the order in which a computer stores a sequence of bytes that make up a larger data type (like a 4-byte integer or an 8-byte float).
Think of it like writing a multi-digit number. You write the most significant digit first (e.g., 1 in 123 is the most significant). This is called Big-Endian.
However, computers can store these bytes in two main ways:
-
Big-Endian (Most Significant Byte First - MSB): The most significant byte is stored at the lowest memory address.
(图片来源网络,侵删)- Analogy: Writing a number from left to right (
123). - The number
0x12345678would be stored in memory as:[0x12, 0x34, 0x56, 0x78]
- Analogy: Writing a number from left to right (
-
Little-Endian (Least Significant Byte First - LSB): The least significant byte is stored at the lowest memory address.
- Analogy: Writing a number from right to left (
321). - The number
0x12345678would be stored in memory as:[0x78, 0x56, 0x34, 0x12]
- Analogy: Writing a number from right to left (
Why does this matter? When you read data from a file, a network socket, or hardware, you need to know the endianness of the source. If you read 4 bytes expecting a big-endian number but they are actually little-endian, you will get the wrong value.
Little Endian in Python
Python has built-in tools to handle endianness, primarily through the struct module and the int.from_bytes() / int.to_bytes() methods.
Key Takeaway:
Modern Intel/AMD x86 and x64 processors (which most desktop and server computers use) are natively little-endian. Therefore, when you work with integers and bytes in Python on these systems, you are often dealing with little-endian data by default.

Practical Examples with the struct Module
The struct module is perfect for converting between Python values (like integers) and C-style byte data. It uses a format string to specify the data types and endianness.
The format string character for endianness is:
<: Little-endian>: Big-endian- Native (whatever the system's native format is, which is usually little-endian on x86/x64)
Let's use the number 305419896 (which is 0x12345678 in hexadecimal).
import struct
# The number we want to pack and unpack
number = 305419896 # This is 0x12345678
# --- Little Endian Example ---
# The format string '<I' means:
# <: Little-endian
# I: Unsigned Integer (4 bytes)
little_endian_bytes = struct.pack('<I', number)
print(f"Packed as Little-Endian: {little_endian_bytes.hex(' ')}")
# Expected Output: 78 56 34 12
# Notice the bytes are in reverse order of the hex representation.
# Now, let's unpack them back into an integer
unpacked_number = struct.unpack('<I', little_endian_bytes)[0]
print(f"Unpacked from Little-Endian: {unpacked_number}")
# Expected Output: 305419896
print("-" * 20)
# --- Big Endian Example (for comparison) ---
# The format string '>I' means:
# >: Big-endian
# I: Unsigned Integer (4 bytes)
big_endian_bytes = struct.pack('>I', number)
print(f"Packed as Big-Endian: {big_endian_bytes.hex(' ')}")
# Expected Output: 12 34 56 78
# Notice the bytes are in the same order as the hex representation.
# Unpack them back
unpacked_number_big = struct.unpack('>I', big_endian_bytes)[0]
print(f"Unpacked from Big-Endian: {unpacked_number_big}")
# Expected Output: 305419896
Practical Examples with int.from_bytes() and int.to_bytes()
This is a more modern and often simpler way to work with integers and bytes.
# The number we want to convert
number = 305419896 # 0x12345678
# --- Convert an integer to little-endian bytes ---
# The 'byteorder' argument is 'little' or 'big'
# 'length' is the size of the integer in bytes
little_endian_bytes = number.to_bytes(length=4, byteorder='little')
print(f"Converted to Little-Endian bytes: {little_endian_bytes.hex(' ')}")
# Expected Output: 78 56 34 12
# --- Convert little-endian bytes back to an integer ---
# We need to know the byte order was 'little' to read it correctly
recovered_number = int.from_bytes(little_endian_bytes, byteorder='little')
print(f"Recovered from Little-Endian bytes: {recovered_number}")
# Expected Output: 305419896
print("-" * 20)
# --- Convert an integer to big-endian bytes (for comparison) ---
big_endian_bytes = number.to_bytes(length=4, byteorder='big')
print(f"Converted to Big-Endian bytes: {big_endian_bytes.hex(' ')}")
# Expected Output: 12 34 56 78
recovered_number_big = int.from_bytes(big_endian_bytes, byteorder='big')
print(f"Recovered from Big-Endian bytes: {recovered_number_big}")
# Expected Output: 305419896
A Real-World Scenario: Reading a Binary File
Imagine you have a file data.bin that contains a 4-byte unsigned integer in little-endian format. You can read it like this:
import struct
# Let's create the dummy file first for this example
with open('data.bin', 'wb') as f:
# Write the number 1000 in little-endian format
f.write(struct.pack('<I', 1000))
# --- Now, let's read it back ---
print("Reading from data.bin...")
try:
with open('data.bin', 'rb') as f:
# Read exactly 4 bytes from the file
byte_data = f.read(4)
# Check if we read 4 bytes
if len(byte_data) == 4:
# Unpack the 4 bytes as a little-endian unsigned integer
number = struct.unpack('<I', byte_data)[0]
print(f"The number read from the file is: {number}")
else:
print("Error: Could not read 4 bytes from the file.")
except FileNotFoundError:
print("Error: data.bin not found.")
# Expected Output:
# Reading from data.bin...
# The number read from the file is: 1000
Summary
| Task | Method | Example (Little Endian) |
|---|---|---|
| Pack (int -> bytes) | struct.pack() |
struct.pack('<I', 305419896) |
| Unpack (bytes -> int) | struct.unpack() |
struct.unpack('<I', b'xV4\x12')[0] |
| Convert to Bytes | int.to_bytes() |
to_bytes(4, 'little') |
| Convert from Bytes | int.from_bytes() |
int.from_bytes(b'xV4\x12', 'little') |
Remember to always check the documentation or specification of the data source (file format, network protocol, hardware manual) to know whether it uses little-endian or big-endian.
