[Pyrex] Cannot cdef __init__?

Paul Prescod paul.prescod at blastradius.com
Tue Jan 20 02:42:12 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?
> 
> 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 take your point. It's okay to make objects that cannot be constructed from
Python (though it might be nice to be able manipulate some of these from
Python, for instance for faking up tracebacks or frames in tracebacks). 

But though I admit that even Guido does this, I also note that the mechanism
is not just making type type uncallable or __init__ unavailable.

>>> callable(types.TracebackType)
True
>>> callable(1)
False
>>> types.TracebackType.__init__
<slot wrapper '__init__' of 'object' objects>
>>> types.TracebackType.__init__(5)

> 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 :)

At the C level the signature of __init__ is fixed. What you call a "cdef
__init__" cannot be what Python calls a tp_init. That's why I'm having
something of a mental blockage. Python's allocator is really more like
tp_new but even that function has a globally standardized signature. You'll
have to put your initializer somewhere else (like a function rather than a
method). And then the __init__ slot is unused which seems a waste.

Also, I'd be curious to see how the proposed solution handles this case:

cdef class Pair:
	pair *p
	cdef __init__(pair *p):
		self.p = p

cdef make_pair(pair *p1):
	p_constructor = Pair
	p_constructor(p1)

You would probably have to disallow it (which is fine, but an added
complication).

> ...
> 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!

Right. Thanks for reading my mind!

And then I meant to compare it to the slightly more elegant:

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

Which would be possible if extension types could accept C types in their
constructors.

 Paul Prescod




More information about the Pyrex mailing list