In Python documentation Struct Sequence Objects:
Struct sequence objects are the C equivalent of
namedtuple()objects, i.e. a sequence whose items can also be accessed through attributes. To create a struct sequence, you first have to create a specific struct sequence type.
PyStructSequence types are subclasses of
tuple and can access the items by attributes. However, they are not equivalent in some aspects. For example, they have different signatures to create a new instance:
structseq.__new__(sequence: Iterable, dict: Optional[dict] = None) -> structseq namedtuple.__new__(field1, field2, ..., fieldN) -> namedtuple values: Iterable[Any] new_tuple = somestructseq(values) new_tuple = somenamedtuple(*values)
For libraries involved with “pytree” manipulation, e.g., JAX, PyTorch, OpTree, we need to reconstruct the Python object with an iterable of leaf values. Due to this difference in the
__new__ method, we need to handle
PyStructSequence types differently.
- pytorch/pytorch#75982: API to determine if a torch.return_type is a “structseq”.
- metaopt/optree#29: Consider
PyStructSequencetypes as internal node types
Here are the criteria I’m using:
namedtuple: a subclass of
tupleand has an attribute
PyStructSequence: a subclass of
tupleand has attributes
n_*fieldsand cannot be subclassed.
import inspect def is_namedtuple(obj: object | type) -> bool: cls = obj if inspect.isclass(cls) else type(obj) return ( issubclass(cls, tuple) and isinstance(getattr(cls, '_fields', None), tuple) and all(isinstance(field, str) for field in cls._fields) ) def is_structseq(obj: object | type) -> bool: cls = obj if inspect.isclass(cls) else type(obj) if ( cls.__base__ is tuple and isinstance(getattr(cls, 'n_sequence_fields', None), int) and isinstance(getattr(cls, 'n_fields', None), int) and isinstance(getattr(cls, 'n_unnamed_fields', None), int) ): try: class subcls(cls): pass except ( TypeError, # CPython AssertionError, # PyPy ): return True return False
>>> is_structseq(torch.return_types.max) True >>> is_structseq(time.struct_time) True
Would there be a C API, such as
PyStructSequence_Check, to check if an object is an instance of