ctypes inheritance issue

Carl Banks pavlovevidence at gmail.com
Wed Feb 23 07:38:29 CET 2011


Steve wrote:

> I've filed a bug in python but I wanted to see if other ctypes users/
> experts viewed this issue as a bug.
> Consider the following:
> python code:
> import ctypes
> class my_array( ctypes.Array ):
>     _type_    = ctypes.c_uint8
>     _length_  = 256
>
> class my_array2( my_array ):
>     pass
>
> Output:
> class my_array2( my_array ):
> AttributeError: class must define a '_length_' attribute, which must
> be a positive integer

I'm not sure if I'd call it a bug, but I can tell you (probably) why it
happens.

ctypes.Array uses a custom metaclass that inspects the class dictionary
directly for those attributes before passing them on to the type
constructor.  In simple terms, it means that ctypes is using the
_length_ and _type_ attributes before it creates the class.

That's an unfortunate aspect of metaclass programming: sometimes you
need that information in order to create the class, but you need the
class in order to inherit.  So, you are stuck with forcing subtypes to
redefine the same attributes as their parents, or trying to mimic the
inheritance by searching the bases yourself (which can be prone to
mistakes).

Point is: this behavior is probably the way it is because of a technical
difficulty as opposed to an oversight or design choice.

> This is analogous to the C code
> typedef char my_array[ 256 ];
> typedef my_array my_array2;

Not really.  Typedefs don't define new types in C; they define aliases
for existing types. This is what would be analogous to your C code:

my_array_2 = my_array

(Which is not to say this affects whether this is a bug or not.)

> As shown above, the python code raises exceptions claiming _type_ and
> _length_ have not been defined.  This seems like a bug.  I shouldn't
> need to redefine _type_ and _length_, otherwise there was no point in
> subclassing from my_array.
>
> Thoughts?

I would vote "not a bug", though I'm pretty close to the fence.

I doubt this behavior is documented one way or the other (if it is
that that would change things), so for it to be considered a bug it'd
have to be very contrary to user expectations. Not inheriting is quite
unexpected, yes, but when metaclass programming is involved all bets are
off about stuff like that.  A lot of what makes metaclasses useful
depends on them breaking expectations with respect to ordinary
classes, so I don't think it would be wise to label every divergence a
bug.


Carl Banks



More information about the Python-list mailing list