Neal Becker wrote: > Steve Holden wrote: > >> Neal Becker wrote: >>> Steve Holden wrote: >>> >>>> Neal Becker wrote: >>>>> 7stud wrote: >>>>> >>>>>> On Feb 21, 11:19 am, Neal Becker <[EMAIL PROTECTED]> wrote: >>>>>>> I'm working on a simple extension. Following the classic 'noddy' >>>>>>> example. >>>>>>> >>>>>>> In [15]: cmplx_int32 >>>>>>> Out[15]: <type 'numpy.cmplx_int32'> >>>>>>> >>>>>>> Now I want to add an attribute to this type. More precisely, I want >>>>>>> a class attribute. >>>>>>> >>>>>>> cmplx_int32.test = 0 >>>>>>> --------------------------------------------------------------------------- >>>>>>> TypeError Traceback (most recent call >>>>>>> last) >>>>>>> >>>>>>> /home/nbecker/numpy/<ipython console> in <module>() >>>>>>> >>>>>>> TypeError: can't set attributes of built-in/extension >>>>>>> type 'numpy.cmplx_int32' >>>>>>> >>>>>>> What am I missing? >>>>>> class Dog(object): >>>>>> def __setattr__(self, attr, val): >>>>>> print "TypeError: can't set attributes of built-in/extension" >>>>>> print "type 'Dog.cmplx_int32'" >>>>>> >>>>>> d = Dog() >>>>>> d.test = 0 >>>>>> >>>>>> --output:-- >>>>>> TypeError: can't set attributes of built-in/extension >>>>>> type 'Dog.cmplx_int32' >>>>> Not quite, I'm setting a class attribute, not an attribute on an >>>>> instance. >>>>> >>>> Quite. The problem is that extension types' attributes are determined by >>>> the layout of the object's slots and forever fixed in the C code that >>>> implements them: the slots can't be extended, so there's no way to add >>>> attributes. This is an efficiency feature: it would be *extremely* slow >>>> to look up the basic types' attributes using late-binding (it would also >>>> change the nature of the language somewhat, making it more like Ruby or >>>> Self). >>>> >>>> So the reason you can't do what you want to is the same reason why you >>>> can't add attribute to the built-in types (which are, of course, clearly >>>> mentioned in the error message). >>>> >>>> >>> object.anyoldname = "You lose!" >>>> Traceback (most recent call last): >>>> File "<stdin>", line 1, in <module> >>>> TypeError: can't set attributes of built-in/extension type 'object' >>>> >>> >>>> >>>> If you look in typeobject.c you'll find this error message occurs when >>>> the object's type isn't a PyHeapTypeObject (in other words, if it's one >>>> of the built-in or extension types). >>>> >>> Thanks, but I'm a bit confused. After reading in my "Python in a >>> Nutshell", I found that if after calling PyReady on my type object, if I >>> use PyDict_SetItemString (my_type_obj.tp_dict,) >>> >>> That seems to work fine (which isn't exactly what it said in the Nutshell >>> book, but close). >>> > > I wanted to add an attribute to my type. > Specifically, my type object is a static cmplx_int32_scalar_obj. > > After calling PyType_Ready (&cmplx_int32_scalar_obj), then I did > PyDict_SetItemString (cmplx_int32_scalar_obj.tp_dict, "dtype", (PyObject*)d1); > > Now my type has the property: > cmplx_int32.dtype > dtype('cmplx_int32') > > Now, I do see that I still can't set it: > > cmplx_int32.dtype = 2 > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > TypeError: can't set attributes of built-in/extension type 'numpy.cmplx_int32' > > In this case, I don't need to. > > But I still don't know why I can have a python class and set class or instance > attributes as I like, but this type acts differently. What would I need to > do if I did want to allow arbitrary attributes to be set/added to my type? > I believe it's because PyType_Ready(), among its many other duties, calls mro_internal() on the type. It seems obvious that one would want to optimize the MRO by not allowing modifications. Yet in C it is possible, as you point out, to do so. Hmm ...
I'll let you know if I come to any conclusion - a query to python-dev would probably get an answer, but surely someone on this list knows already? [Left this as a draft for a while to mull it over]. After further consideration I have concluded (without further scrutiny of the source) that it's because the method slots in C-implemented types are pointers to C functions not to Python functions. Would this make sense? regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list