Cython cdef vs cpdef vs def Syntax Differences

Cython provides three distinct function declaration keywords—def, cdef, and cpdef—which control how functions are compiled, where they can be accessed, and how efficiently they execute. Understanding the differences among these keywords allows developers to balance execution speed with Python interoperability. This guide outlines the syntax, accessibility, performance implications, and practical use cases for each function type in Cython.

Quick Comparison

Feature def cdef cpdef
Callable from Python? Yes No Yes
Callable from Cython/C? Yes Yes Yes
Return/Argument Types Python objects (or auto-coerced) C types and Python objects C types and Python objects
Call Overhead High (Python standard) Minimal (Pure C call) Minimal via Cython; High via Python
Primary Use Case Public Python API Internal, performance-critical tasks Hybrid public/private functions

1. The def Function

The def statement declares a standard Python function. It produces a regular Python function object that is placed into the module's namespace and can be invoked directly from pure Python code.

Syntax

def add_py(int a, int b):
    return a + b

Characteristics


2. The cdef Function

The cdef statement defines a pure C-level function. It cannot be accessed directly from pure Python code because it is not exported to the Python module’s symbol table.

Syntax

cdef int add_c(int a, int b):
    return a + b

Characteristics


3. The cpdef Function

The cpdef keyword creates a hybrid function. The Cython compiler generates two versions: a fast C-level function and a lightweight Python wrapper that forwards arguments to the C function.

Syntax

cpdef int add_hybrid(int a, int b):
    return a + b

Characteristics


Summary of Syntax Rules

  1. Return Types:
    • def does not allow an explicit C return type before the function name (e.g., def int func(): is invalid).
    • cdef and cpdef require or allow a C return type directly after the keyword (e.g., cdef double compute(): or cpdef void process():).
  2. Type Compatibility:
    • Use cdef if you need to use non-Python-compatible types (like raw memory pointers: int*).
    • Use cpdef if you want maximum speed in Cython while keeping the function accessible to standard Python scripts.
    • Use def when creating external module interfaces that do not benefit from C-level internal calls.