diff --git a/docs/src/userguide/extension_types.rst b/docs/src/userguide/extension_types.rst index 9bf803310aad6441a164a42f0e625096137a23e8..6a574fa80a19c674b7c40f914da469ec73871da8 100644 --- a/docs/src/userguide/extension_types.rst +++ b/docs/src/userguide/extension_types.rst @@ -39,14 +39,16 @@ interface to them. .. _readonly: -Attributes -============ +Static Attributes +================= Attributes of an extension type are stored directly in the object's C struct. The set of attributes is fixed at compile time; you can't add attributes to an extension type instance at run time simply by assigning to them, as you could -with a Python class instance. (You can subclass the extension type in Python -and add attributes to instances of the subclass, however.) +with a Python class instance. However, you can explicitly enable support +for dynamically assigned attributes, or subclass the extension type with a normal +Python class, which then supports arbitrary attribute assignments. +See :ref:`dynamic_attributes`. There are two ways that attributes of an extension type can be accessed: by Python attribute lookup, or by direct access to the C struct from Cython code. @@ -76,6 +78,47 @@ and the depth attribute readable but not writable. Python access, not direct access. All the attributes of an extension type are always readable and writable by C-level access. + +.. _dynamic_attributes: + +Dynamic Attributes +================== + +It is not possible to add attributes to an extension type at runtime by default. +You have two ways of avoiding this limitation, both add an overhead when +a method is called from Python code. Especially when calling ``cpdef`` methods. + +The first approach is to create a Python subclass.:: + + cdef class Animal: + + cdef int number_of_legs + def __cinit__(self, int number_of_legs): + self.number_of_legs = number_of_legs + + + class ExtendableAnimal(Animal): # Note that we use class, not cdef class + pass + + + dog = ExtendableAnimal(4) + dog.has_tail = True + + +Declaring a ``__dict__`` attribute is the second way of enabling dynamic attributes.:: + + cdef class Animal: + + cdef int number_of_legs + cdef dict __dict__ + def __cinit__(self, int number_of_legs): + self.number_of_legs = number_of_legs + + + dog = Animal(4) + dog.has_tail = True + + Type declarations ===================