[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Creating new types and invoking super

Guilherme Polo

1/23/2008 8:55:00 PM

Hello,

Before starting, let me show some sample codes so I can explain:

class A(object):
def __init__(self):
super(A, self).__init__()

x = type("X", (A, ), {})()

This works fine, but suppose I have several classes like A and I would
like to create a decorator to call super. First I tried this:

def init(func):
def _init(inst):
super(inst.__class__, inst).__init__()
func(inst)

return _init

class A(object):
@init
def __init__(self): pass

This works when I create a instance by doing A(), but I get
"RuntimeError: maximum recursion depth exceeded" when I create a new
type doing type("X", (A, ), {}) and then create an instance of it.
To "solve" this problem, I changed the init function to this then:

def init(func):
def _init(inst):
super(inst.__class__.__mro__[-2], inst).__init__()
func(inst)

return _init

It works if A is a direct subclass of object, if it is not I have to
adapt the index [-2].
So, is there a better way to do this ?

--
-- Guilherme H. Polo Goncalves
7 Answers

Arnaud Delobelle

1/23/2008 9:56:00 PM

0

On Jan 23, 8:55 pm, "Guilherme Polo" <ggp...@gmail.com> wrote:
> Hello,

Hi
[...]
> First I tried this:
>
> def init(func):
>     def _init(inst):
>         super(inst.__class__, inst).__init__()
>         func(inst)
>
>     return _init
>
> class A(object):
>     @init
>     def __init__(self): pass

This kind of approach can't work, you need to call super(A, obj).
super(type(obj), obj) is pointless, it defeats the whole purpose of
the mro!

The only way I can think of would be to create a metaclass, but I
don't think it's worth it. super(A, obj).__init__() isn't that bad!

--
Arnaud

Guilherme Polo

1/23/2008 10:18:00 PM

0

2008/1/23, Arnaud Delobelle <arnodel@googlemail.com>:
> On Jan 23, 8:55 pm, "Guilherme Polo" <ggp...@gmail.com> wrote:
> > Hello,
>
> Hi
> [...]
> > First I tried this:
> >
> > def init(func):
> > def _init(inst):
> > super(inst.__class__, inst).__init__()
> > func(inst)
> >
> > return _init
> >
> > class A(object):
> > @init
> > def __init__(self): pass
>
> This kind of approach can't work, you need to call super(A, obj).
> super(type(obj), obj) is pointless, it defeats the whole purpose of
> the mro!
>

Yeh, as shown in the next examples in the previous email. Using a
decorator for that doesn't sound useful at all, was just trying
something different ;) I will stick to the no-decorator option.

> The only way I can think of would be to create a metaclass, but I
> don't think it's worth it. super(A, obj).__init__() isn't that bad!
>

Metaclass doesn't apply here because metaclass is related to
class-construction. This is related to instance initialization, and
I'm creating the types as the user asks.

> --
> Arnaud
>
> --
> http://mail.python.org/mailman/listinfo/p...
>


--
-- Guilherme H. Polo Goncalves

Guilherme Polo

1/23/2008 10:42:00 PM

0

2008/1/23, Guilherme Polo <ggpolo@gmail.com>:
> 2008/1/23, Arnaud Delobelle <arnodel@googlemail.com>:
> > On Jan 23, 8:55 pm, "Guilherme Polo" <ggp...@gmail.com> wrote:
> > > Hello,
> >
> > Hi
> > [...]
> > > First I tried this:
> > >
> > > def init(func):
> > > def _init(inst):
> > > super(inst.__class__, inst).__init__()
> > > func(inst)
> > >
> > > return _init
> > >
> > > class A(object):
> > > @init
> > > def __init__(self): pass
> >
> > This kind of approach can't work, you need to call super(A, obj).
> > super(type(obj), obj) is pointless, it defeats the whole purpose of
> > the mro!
> >
>
> Yeh, as shown in the next examples in the previous email. Using a
> decorator for that doesn't sound useful at all, was just trying
> something different ;) I will stick to the no-decorator option.
>
> > The only way I can think of would be to create a metaclass, but I
> > don't think it's worth it. super(A, obj).__init__() isn't that bad!
> >
>
> Metaclass doesn't apply here because metaclass is related to
> class-construction. This is related to instance initialization, and
> I'm creating the types as the user asks.

Oops, actually it can be done. But I am not going to stick to it, just
did a sample here that "solves" for a not so deep structure:

def init(func):
def _init(cls):
if hasattr(cls, "myclass"):
super(cls.myclass, cls).__init__()
else:
super(cls.__class__, cls).__init__()
func(cls)

return _init

class M(type):
def __new__(cls, classname, bases, classdict):
if not len(classdict):
if 'myclass' in bases[0].__dict__:
classdict['myclass'] = bases[0].__dict__['myclass']
else:
classdict['myclass'] = bases[0]


return type.__new__(cls, classname, bases, classdict)

class Y(object):
__metaclass__ = M

class X(Y):
@init
def __init__(self):
print "X"

X()
y = type("Z", (X, ), {})
w = type("W", (y, ), {})
y()
w()

>
> > --
> > Arnaud
> >
> > --
> > http://mail.python.org/mailman/listinfo/p...
> >
>
>
> --
> -- Guilherme H. Polo Goncalves
>


--
-- Guilherme H. Polo Goncalves

Arnaud Delobelle

1/23/2008 11:51:00 PM

0

On Jan 23, 10:18 pm, "Guilherme Polo" <ggp...@gmail.com> wrote:
> 2008/1/23, Arnaud Delobelle <arno...@googlemail.com>:
>
> > The only way I can think of would be to create a metaclass, but I
> > don't think it's worth it.  super(A, obj).__init__() isn't that bad!
>
> Metaclass doesn't apply here because metaclass is related to
> class-construction. This is related to instance initialization, and
> I'm creating the types as the user asks.

Not completely clear to me what you want but here is a 'proof of
concept':

==========

class callsuper(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, cls=None):
def newfunc(*args, **kwargs):
super(self.cls, obj).__init__()
return self.f(obj, *args, **kwargs)
return newfunc

class Type(type):
def __init__(self, name, bases, attrs):
for attrname, attr in attrs.iteritems():
if isinstance(attr, callsuper):
attr.cls = self

class A:
__metaclass__ = Type
def __init__(self):
print "init A"

class B(A):
@callsuper
def __init__(self):
print "init B"

==========

>>> b=B()
init A
init B

Guilherme Polo

1/24/2008 12:11:00 AM

0

2008/1/23, Arnaud Delobelle <arnodel@googlemail.com>:
> On Jan 23, 10:18 pm, "Guilherme Polo" <ggp...@gmail.com> wrote:
> > 2008/1/23, Arnaud Delobelle <arno...@googlemail.com>:
> >
> > > The only way I can think of would be to create a metaclass, but I
> > > don't think it's worth it. super(A, obj).__init__() isn't that bad!
> >
> > Metaclass doesn't apply here because metaclass is related to
> > class-construction. This is related to instance initialization, and
> > I'm creating the types as the user asks.
>
> Not completely clear to me what you want but here is a 'proof of
> concept':
>
> ==========
>
> class callsuper(object):
> def __init__(self, f):
> self.f = f
> def __get__(self, obj, cls=None):
> def newfunc(*args, **kwargs):
> super(self.cls, obj).__init__()
> return self.f(obj, *args, **kwargs)
> return newfunc
>
> class Type(type):
> def __init__(self, name, bases, attrs):
> for attrname, attr in attrs.iteritems():
> if isinstance(attr, callsuper):
> attr.cls = self
>
> class A:
> __metaclass__ = Type
> def __init__(self):
> print "init A"
>
> class B(A):
> @callsuper
> def __init__(self):
> print "init B"
>
> ==========
>
> >>> b=B()
> init A
> init B
>
> --
> http://mail.python.org/mailman/listinfo/p...
>

Thanks for this concept, works better than mine :)


--
-- Guilherme H. Polo Goncalves

Arnaud Delobelle

1/24/2008 7:20:00 AM

0

On Jan 23, 11:51 pm, Arnaud Delobelle <arno...@googlemail.com> wrote:
Oops:

>
> class callsuper(object):
>     def __init__(self, f):
>         self.f = f
>     def __get__(self, obj, cls=None):
>         def newfunc(*args, **kwargs):
>             super(self.cls, obj).__init__()

Change this line to:
getattr(super.cls, obj), self.f.__name__)()

>             return self.f(obj, *args, **kwargs)
>         return newfunc

Arnaud Delobelle

1/24/2008 7:27:00 AM

0

On Jan 24, 7:19 am, Arnaud Delobelle <arno...@googlemail.com> wrote:
Oops again
>
> Change this line to:
>               getattr(super.cls, obj), self.f.__name__)()

I mean
getattr(super(self.cls, obj), self.f.__name__)()

--
Arnaud