Features Download
From: Vitja Makarov <vitja.makarov-Re5JQEeQqe8AvxtiuMwx3w <at> public.gmane.org>
Subject: Re: [Cython] PEP 3135 -- New Super
Newsgroups: gmane.comp.python.cython.devel
Date: Tuesday 5th July 2011 08:37:40 UTC (over 5 years ago)
2011/7/5 Stefan Behnel :
> 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
>>> 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
> Remember that no-args super() can only be used in functions that are
> literally written inside of a class body, so we actually know at compile
> time which functions need this field. We can thus do better than a
> loop over all fields. We even have the function object pointers directly
> available in the module init function where we create the class body.

Yes, but now cyfunction references are lost as they were in temps.

> BTW, we also need a way to make this work for cdef classes. No idea how
> different that would be.

I think super() for cdef classes should be much easy to implement as
we already know cname for a class at compile time. That would be
simple transform.

>>> OTOH, not all methods have a closure, so creating one just to store the
>>> "__class__" field is very wasteful, in terms of both runtime and memory
>>> overhead. A lot more wasteful than paying 8 bytes of memory for each
>>> function, with no additional time overhead.
>> Going this way it only requires to initialize closure:
> Yes, and that's costly.
>> 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?

Right. When we pass CyFunction closure should be moved into its members.

>> This also could help to solve default args problem.
> And potentially other problems, too. Think of heap allocated modules, for
> example.
> http://trac.cython.org/cython_trac/ticket/173
> http://trac.cython.org/cython_trac/ticket/218
> Seeing this, I'm all for using a field in CyFunction.
>> Yeah, I think Cython super with no args should be a little bit faster
>> then classic one.
> I think speed isn't really all that important here. Calling Python
> is costly enough anyway.
> IMO, the main reason for the heuristic is to prevent class objects from
> being kept alive by their methods, except for the single case where
> is used. Keeping a class alive just because one of its methods is still
> somewhere can be very costly, depending on the content of the class dict.
> also creates a reference cycle, which is another costly thing in CPython
> it requires a GC run over the whole class dict to get cleaned up.
> The situation for modules is at least slightly different, as modules do
> tend to get unloaded, so there's always a reference to them from
> sys.modules. If that ever gets removed, it's really ok if it takes time
> clean things up.

Yes, but I hope that classes are rarely deleted.
And I'm afraid that we can't avoid cycles when implementing __class__
for pure-python classes.

CD: 5ms