Python
Programming
Data Structures
C Language
Python Tips

C-like structures in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Python does not have a direct built-in equivalent of C's struct type as a language feature, but it offers several good substitutes depending on what you mean by "C-like." If you want a simple field-based data container, dataclass or NamedTuple is often the right answer; if you need binary layout compatibility, ctypes.Structure or the struct module is closer to real C behavior.

For Ordinary Structured Data: dataclass

If your goal is "a named bundle of fields," a dataclass is usually the cleanest Python option.

python
1from dataclasses import dataclass
2
3
4@dataclass
5class Point:
6    x: int
7    y: int
8
9
10p = Point(10, 20)
11print(p.x, p.y)

This feels similar to a C struct in that the object mainly stores fields, but it also gives you Python niceties such as readable repr, equality, and type annotations.

Immutable Alternative: NamedTuple

If you want something lighter and immutable, NamedTuple works well.

python
1from typing import NamedTuple
2
3
4class Point(NamedTuple):
5    x: int
6    y: int
7
8
9p = Point(10, 20)
10print(p.x)
11print(p[1])

This is useful when the data is record-like and should not be modified after creation.

For Actual C-Compatible Layout: ctypes.Structure

If you need to match a real C struct in memory, use ctypes.Structure.

python
1import ctypes
2
3
4class Point(ctypes.Structure):
5    _fields_ = [
6        ("x", ctypes.c_int),
7        ("y", ctypes.c_int),
8    ]
9
10
11p = Point(10, 20)
12print(p.x, p.y)
13print(ctypes.sizeof(Point))

This is the closest Python gets to a true C-like structure because:

  • fields have explicit C types
  • layout follows C-compatible rules
  • the object can interoperate with native libraries

That makes it appropriate for FFI work, not just ordinary application data modeling.

Packing and Unpacking Raw Binary Data

If you do not need an object with named attributes but do need C-like binary encoding, the struct module is often simpler.

python
1import struct
2
3packed = struct.pack("ii", 10, 20)
4x, y = struct.unpack("ii", packed)
5
6print(x, y)
7print(len(packed))

This is especially useful for binary protocols and file formats.

Which One Should You Choose

Choose based on the real problem:

  • 'dataclass for normal Python application data'
  • 'NamedTuple for lightweight immutable records'
  • 'ctypes.Structure for C interop and memory layout'
  • 'struct for packing and unpacking bytes'

Many questions about "C-like structures in Python" are really questions about field grouping, not about memory layout. In those cases, dataclass is usually the best answer.

A Plain Class Is Still Valid

It is also perfectly reasonable to use a normal class when the object needs behavior as well as fields.

python
1class Point:
2    def __init__(self, x: int, y: int) -> None:
3        self.x = x
4        self.y = y
5
6    def magnitude_squared(self) -> int:
7        return self.x * self.x + self.y * self.y
8
9
10p = Point(3, 4)
11print(p.magnitude_squared())

This is more verbose than a dataclass, but it is the right choice when the object is not just a passive record.

Common Pitfalls

The most common mistake is reaching for ctypes.Structure when you only need a simple data container. That adds complexity and C-level concerns unnecessarily.

Another issue is assuming Python objects behave like plain C structs in memory. Regular Python classes and dataclasses carry Python object overhead and are not raw packed memory blocks.

A third pitfall is forgetting alignment and byte-order details when using ctypes or struct for binary interchange. If the binary format matters, those details are part of the contract.

Finally, do not use a dictionary just because it is convenient if the data has a stable schema. Named fields are easier to read, validate, and refactor.

Summary

  • Python offers several ways to model struct-like data, depending on your goal.
  • Use dataclass for normal structured application data.
  • Use NamedTuple when immutability and lightweight records are useful.
  • Use ctypes.Structure when you need genuine C-compatible field layout.
  • Use the struct module for binary packing and unpacking rather than general-purpose objects.

Course illustration
Course illustration

All Rights Reserved.