[Pyrex] Cannot cdef __init__?

Andrew Bennetts andrew-pyrex at puzzling.org
Tue Jan 20 00:34:40 CET 2004


On Mon, Jan 19, 2004 at 09:10:07AM -0800, Paul Prescod wrote:
> My opinion is that the idea of having an initializer that can accept C 
> types is okay but calling it __init__ is probably not. First, there are 
> basically no type objects in Python that are not callable from Python. 

Really?

>>> import types
>>> for name in dir(types):
...     try:
...         x = getattr(types, name)()
...     except TypeError, e:
...         if str(e).lower().find('cannot create') != -1:
...             print 'Cannot construct ', name
... 
Cannot construct  BuiltinFunctionType
Cannot construct  BuiltinMethodType
Cannot construct  DictProxyType
Cannot construct  EllipsisType
Cannot construct  FrameType
Cannot construct  GeneratorType
Cannot construct  NoneType
Cannot construct  NotImplementedType
Cannot construct  TracebackType

I don't consider "almost ten" to be "basically no" :)

And this is just the list of builtin types, let alone types from standard
library modules or common extensions.  And it's entirely possible to have
uncallable types written in pure python (e.g. an abstract base class that
raises TypeError or NotImplementedError if it is constructed instead of its
base class).

I don't believe that this is such an unusual situation at all.

Or to put it differently: writing raw C, it is easy enough to write a type
that is not callable from Python.  Pyrex should be easier than writing C :)

> Second, you might very well want to have a constructor that is callable 
> from Python alongside a constructor that is only callable from C. You 
> could call the cdef version __cinit__. Or you could add some kind of 
> overloading to Pyrex in general (interesting idea...maybe you could 
> define cdef method XXX alongside a def method XXX and it would call the 
> more appropriate one based on the calling types) I'd guess you'd have to 
> discuss different design options on Greg's return before you'd get a 
> patch accepted.

This is an option, but I'm a little wary of the idea of adding overloading
-- it's not something I'd do to Greg's language, I'll leave that up to him
:)

I think my proposed solution of simply allowing __init__ to be cdef'd (and
thus not directly callable from Python) is probably simpler and would add
consistency.  But I'll try not to harp on about it too much until I've spent
more time trying to implement it :)

> But anyhow, I don't think that the workaround in this case is too 
> unweildy. Let's say that there are seven functions that can construct 
> pair objects. You define each of them like this:
> 
> cdef Pair my_init_pair_from_another_pair(pair *p1):
> 	pair * p=init_pair_from_another_pair(p1):
> 	rc = Pair()
> 	Pair.p = p

I presume you really mean:

cdef Pair my_init_pair_from_another_pair(pair *p1):
        pair * p = init_pair_from_another_pair(p1)
        rc = Pair()
        rc.p = p
        return rc

You're right, this isn't particularly unwieldy.  I'll try this.  Thanks!

> And so forth. Basically you have one extra line of code in each of them 
> over this:
> 
> cdef Pair my_init_pair_from_another_pair(pair *p1):
> 	pair * p=init_pair_from_another_pair(p1):
> 	rc = Pair()
> 	Pair.p = p

I don't understand you here... what extra line?  This looks identical to
your example above -- including typos :)

Again, thanks,

-Andrew.





More information about the Pyrex mailing list