[Cython] PEP 3135 -- New Super

Vitja Makarov vitja.makarov at gmail.com
Thu Jul 7 23:13:04 CEST 2011


2011/7/8 mark florisson <markflorisson88 at gmail.com>

> On 7 July 2011 22:39, Vitja Makarov <vitja.makarov at gmail.com> wrote:
> >
> >
> > 2011/7/8 mark florisson <markflorisson88 at gmail.com>
> >>
> >> On 7 July 2011 22:15, Vitja Makarov <vitja.makarov at gmail.com> wrote:
> >> >
> >> >
> >> > 2011/7/7 mark florisson <markflorisson88 at gmail.com>
> >> >>
> >> >> On 6 July 2011 10:01, Vitja Makarov <vitja.makarov at gmail.com> wrote:
> >> >> > 2011/7/6 Stefan Behnel <stefan_ml at behnel.de>:
> >> >> >> Vitja Makarov, 06.07.2011 09:05:
> >> >> >>>
> >> >> >>> 2011/7/6 Stefan Behnel<stefan_ml at behnel.de>:
> >> >> >>>>
> >> >> >>>> Stefan Behnel, 05.07.2011 10:04:
> >> >> >>>>>
> >> >> >>>>> Vitja Makarov, 05.07.2011 09:17:
> >> >> >>>>>>
> >> >> >>>>>> 2011/7/5 Stefan Behnel:
> >> >> >>>>>>>
> >> >> >>>>>>> Vitja Makarov, 05.07.2011 08:21:
> >> >> >>>>>>>>
> >> >> >>>>>>>> I was thinking about implementing new super() with no
> >> >> >>>>>>>> arguments.
> >> >> >>>>>>>
> >> >> >>>>>>> http://trac.cython.org/cython_trac/ticket/696
> >> >> >>>>>>>
> >> >> >>>>>>>> The problem is where to store __class__, I see two options
> >> >> >>>>>>>> here:
> >> >> >>>>>>>>
> >> >> >>>>>>>> 1. Add func_class member to CyFunction, this way __class__
> >> >> >>>>>>>> will
> >> >> >>>>>>>> be
> >> >> >>>>>>>> private and not visible for inner functions:
> >> >> >>>>>>>> 2. Put it into closure
> >> >> >>>>>>>
> >> >> >>>>>>> The second option has the advantage of requiring the field
> only
> >> >> >>>>>>> when
> >> >> >>>>>>> super()
> >> >> >>>>>>> is used, whereas the first impacts all functions.
> >> >> >>>>>>>
> >> >> >>>>>>> I would expect that programs commonly have a lot more
> functions
> >> >> >>>>>>> than
> >> >> >>>>>>> specifically methods that use a no-argument call to super(),
> so
> >> >> >>>>>>> this
> >> >> >>>>>>> may
> >> >> >>>>>>> make a difference.
> >> >> >>>>>>>
> >> >> >>>>>>
> >> >> >>>>>> So, now classes are created the following way:
> >> >> >>>>>>
> >> >> >>>>>> class_dict = {}
> >> >> >>>>>> class_dict.foo = foo_func
> >> >> >>>>>> class = CreateClass(class_dict)
> >> >> >>>>>>
> >> >> >>>>>> So after class is created I should check its dict for
> CyFunction
> >> >> >>>>>> members (maybe only ones that actually require __class__)
> >> >> >>>>>> and set __class__:
> >> >> >>>>>>
> >> >> >>>>>> for value in class.__dict__.itervalues():
> >> >> >>>>>> if isinstance(value, CyFunction) and value.func_class is
> >> >> >>>>>> WantClass:
> >> >> >>>>>> value.func_class = class
> >> >> >>>>>>
> >> >> >>>>>> Btw, first way requires cyfunction signature change, it would
> >> >> >>>>>> accept
> >> >> >>>>>> cyfunction object as first argument.
> >> >> >>>>>
> >> >> >>>>> We currently pass the binding (i.e. owning) object, right?
> >> >> >>>>
> >> >> >>>> So, how would this work for methods? We need to pass the 'self'
> >> >> >>>> object
> >> >> >>>> there, which the CyFunction doesn't know. If anything, it only
> >> >> >>>> knows
> >> >> >>>> the
> >> >> >>>> class it was defined in, which doesn't help here.
> >> >> >>>
> >> >> >>> From PEP: "super() is equivalent to: super(__class__,<firstarg>)"
> >> >> >>
> >> >> >> I wasn't speaking of super(). What I meant, was: how do we pass
> >> >> >> 'self'
> >> >> >> when
> >> >> >> we pass the CyFunction object as the first argument?
> >> >> >>
> >> >> >
> >> >> >
> >> >> > Oh, ok. Now we pass closure or nothing in self. So method's self is
> >> >> > passed via tuple.
> >> >> > Instancemethod do this for us. Now CyFucntion uses PyCFunction_Call
> >> >> > we
> >> >> > can override this and change signature of cyfunction to:
> >> >> >
> >> >> > PyObject func(CyFunction *func, PyObject *self, PyObject *args,
> >> >> > PyObject *kwargs);
> >> >> >
> >> >> > This way we should implement new instancemethod type.
> >> >>
> >> >> Would it be easier to make scope objects attributes of functions?
> Then
> >> >> you could still utilize PyCFunction_Call without needing to check the
> >> >> argument flags and such right?
> >> >>
> >> >
> >> > Sure, scope object is already functions attribute now it's stored
> inside
> >> > self.
> >> > But, instancemethods desc_get builds new args tuple with self as first
> >> > element.
> >> > We can implement cython version of instance method and change method
> >> > signature a little bit.
> >>
> >> Right, and you pass it in as the first argument to the C function.
> >> However, if you want to change the signature, you have to override
> >> PyCFunction_Call, which, if I'm not mistaken, means you will have to
> >> interpret the flags from the PyMethodDef and call the C function in
> >> the right way (e.g. with or without the args tuple and kwargs) and
> >> check if it's being called correctly. If you leave it as an attribute
> >> of the function, you can pass in the function and access the scope
> >> object from the function object in the closure C function. So I think
> >> changing the signature might be a bit harder?
> >>
> >
> > Yes, but how to handle instantmethods self arg?
> > We can't store it inside function object as it is different for each
> > instance.
>
> In descr_get you create and return a new CyFunction with a __self__
> set (note, not m_self) and in __call__ you put __self__ in the args
> tuple and the function as m_self, and then call the CyFunction using
> PyCFunction_Call. But copying and modifying PyCFunction_Call works
> just as well I suppose :)
>

Yes, that would work) But I think CyFunction is too heavy for methods.
I've just realized that descr_get is called each time you access method,
each time you call it and so on.



> Anyway, the important question was whether I could pull from your
> branch or whether I should wait for the merge.
>
>
It's better not to use my branch this way as it's marked with underscore and
sometimes I do forced pushes.
I hope it will be merged soon.
There is one more thing left CPython uses pool for frequently used objects
to avoid unnecessary memory allocations.
Probably we should implement something like that too.

You are going to subclass cyfunction and then override its tp_call method,
right?

-- 
vitja.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cython-devel/attachments/20110708/946413f3/attachment-0001.html>


More information about the cython-devel mailing list