can't set attributes of built-in/extension type

Neal Becker ndbecker2 at gmail.com
Thu Feb 21 20:20:23 EST 2008


Steve Holden wrote:

> Neal Becker wrote:
>> Steve Holden wrote:
>> 
>>> Neal Becker wrote:
>>>> 7stud wrote:
>>>>
>>>>> On Feb 21, 11:19 am, Neal Becker <ndbeck... at gmail.com> 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?




More information about the Python-list mailing list