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.
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.
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.
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.
This is especially useful for binary protocols and file formats.
Which One Should You Choose
Choose based on the real problem:
- '
dataclassfor normal Python application data' - '
NamedTuplefor lightweight immutable records' - '
ctypes.Structurefor C interop and memory layout' - '
structfor 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.
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
dataclassfor normal structured application data. - Use
NamedTuplewhen immutability and lightweight records are useful. - Use
ctypes.Structurewhen you need genuine C-compatible field layout. - Use the
structmodule for binary packing and unpacking rather than general-purpose objects.

