## 2.2.3 Attribute Management Functions

          getattrfunc tp_getattr;
          setattrfunc tp_setattr;

The `tp_getattr` handle is called when the object requires an attribute look-up. It is called in the same situations where the `__getattr__()` method of a class would be called.

A likely way to handle this is (1) to implement a set of functions (such as `newdatatype_getSize()` and `newdatatype_setSize()` in the example below), (2) provide a method table listing these functions, and (3) provide a getattr function that returns the result of a lookup in that table.

Here is an example:

      static PyMethodDef newdatatype_methods[] = {
          {"getSize", (PyCFunction)newdatatype_getSize, METH_VARARGS,
           "Return the current size."},
          {"setSize", (PyCFunction)newdatatype_setSize, METH_VARARGS,
           "Set the size."},
          {NULL, NULL, 0, NULL}           /* sentinel */
      };

      static PyObject *
      newdatatype_getattr(newdatatypeobject *obj, char *name)
      {
          return Py_FindMethod(newdatatype_methods, (PyObject *)obj, name);
      }

The `tp_setattr` handler is called when the `__setattr__()` or `__delattr__()` method of a class instance would be called. When an attribute should be deleted, the third parameter will be `NULL`. Here is an example that simply raises an exception; if this were really all you wanted, the `tp_setattr` handler should be set to `NULL`.

      static int
      newdatatype_setattr(newdatatypeobject *obj, char *name, PyObject *v)
      {
          (void)PyErr_Format(PyExc_RuntimeError, "Read-only attribute: \%s", name);
          return -1;
      }