Bug in New Style Classes

Michele Simionato michele.simionato at poste.it
Fri Jun 18 06:29:01 EDT 2004


David MacQuigg <dmq at gain.com> wrote in message news:<giu4d05rdkvm9sgmj44dnks909ahba43hn at 4ax.com>...
> On Thu, 17 Jun 2004 11:05:58 GMT, Michael Hudson <mwh at python.net>
> wrote:
> 
> >michele.simionato at poste.it (Michele Simionato) writes:
> >
> >> David MacQuigg <dmq at gain.com> wrote in message news:<rmu1d09qiqtosgdq1vavv3736sb62bktri at 4ax.com>...
> >> > I have what looks like a bug trying to generate new style classes with
> >> > a factory function.
> >> > 
> >> > class Animal(object): pass
> >> > class Mammal(Animal): pass
> >> > 
> >> > def newAnimal(bases=(Animal,), dict={}):
> >> >     class C(object): pass
> >> >     C.__bases__ = bases
> >> >     dict['_count'] = 0
> >> >     C.__dict__ = dict
> >> >     return C
> >> > 
> >> > Canine = newAnimal((Mammal,))
> >> > TypeError: __bases__ assignment: 'Mammal' deallocator differs from
> >> > 'object'
> >> > 
> >> > If I remove the 'object' from the class C(object) statement, then I
> >> > get a different, equally puzzling error message:
> >> > 
> >> > TypeError: __bases__ items must be classes
> >> > 
> >> > The function works only if I remove 'object' from all base classes.
> >> > 
> >> > -- Dave
> >> 
> >> This is not a bug. The developers removed the possibility to change
> >> the bases of a new-style class. 
> >
> >Bad news for you: I put it back in for 2.3.
> >
> >If you read the error message, you'll notice that it's phrased to
> >suggest that assignment to __bases__ is *sometimes* possible :-)
> >
> >David's assignment probably should work -- there's a bug on sf about
> >this -- but there are definitely situations where assignment to bases
> >*shouldn't* be allowed -- e.g. when the so-called 'solid base' changes
> >-- but noone's put in the thinking time to make this precise in code.
> >Being over-restrictive seems the better course.
> 
> This may be just a documentation problem then.  The error message is
> definitely misleading.
> 
> >However, newAnimal could be written like this:
> >
> >def newAnimal(bases=(Animal,), ns=None):
> >    if ns is None:
> >        ns = {}
> >    ns['_count'] = 0
> >    return type('C', bases, ns)
> >
> >which 
> >
> >a) doesn't use the name of a builtin as a variable
> >b) doesn't suffer the 'mutable default arguments' problem
> >c) is rather less insane
> >d) actually works :-) (probably, haven't tested it)
> 
> It works great.  The only thing I would change is the return line,
> making that
> 
>     globals()[name] = type('C', bases, ns)
> 
> so we don't have to type the name twice when creating a new class.
> I've also added an __init__ function.  Using the factory is now very
> easy:
> 
> >>> newAnimal('Dog',(Mammal,))
> >>> dog1 = Dog()
>  Hello from __init__ in Dog
> >>> Dog._count
> 1
> 
> The main limitation I see in using a factory function like this,
> instead of a metaclass, is that I can't customize the new animal as
> easily, because I don't have an indented block like in a class
> definition.  I've got to call the newAnimal function, then add a bunch
> of attributes one at a time, with fully-qualified names.
> 
> Dog.temperature = 102
> Dog.pulse = 82
> Dog.respiration = 36
> 
> If I'm adding methods, it gets even messier, because I've got to
> define functions at the module level, then assign them to attributes
> of Dog, then maybe delete all the excess names from the module
> namespace.
> 
> I have one last question. In reviewing all the ways to solve the
> problem of creating specialized classes, I see there is a function
> new.classobj(name, bases, dict) which appears to do the same thing as
> type(name, bases, dict).  What is the purpose of classobj()?  The name
> is a little more self-explanatory than 'type', but using it requires a
> module import.
> 
> - Dave

I heard somebody saying that the module 'new' will be deprecated
at some moment. new.classobj returns old-style classes:

>>> import new
>>> new.classobj("C",(),{})
<class __main__.C at 0x403afd1c>
>>> type(_)
<type 'classobj'>

whereas type returns new style ones. You can create oldstyle classes
even without recurring to new.classobj.


  Michele Simionato



More information about the Python-list mailing list