473,769 Members | 6,126 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Bug in New Style Classes

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((Mamm al,))
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

*************** *************** *************** *************** * *
* David MacQuigg, PhD * email: dmq at gain.com * *
* IC Design Engineer * phone: USA 520-721-4583 * * *
* Analog Design Methodologies * * *
* * 9320 East Mikelyn Lane * * *
* VRS Consulting, P.C. * Tucson, Arizona 85710 *
*************** *************** *************** *************** * *
Jul 18 '05 #1
12 3831
David MacQuigg wrote:
I have what looks like a bug trying to generate new style classes with
a factory function.


IIRC, you can't assign to __bases__ of a new-style class. But you can
use type() instead of your home-made factory function.
Jul 18 '05 #2
Leif K-Brooks wrote:
David MacQuigg wrote:
I have what looks like a bug trying to generate new style classes with
a factory function.

IIRC, you can't assign to __bases__ of a new-style class. But you can
use type() instead of your home-made factory function.


Even better:
see http://www.python.org/doc/current/lib/module-new.html and especially
classobj !

--
Yermat

Jul 18 '05 #3
David MacQuigg <dm*@gain.com > wrote in message news:<rm******* *************** **********@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((Mamm al,))
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. Probably because it could not be done
reliably (I don't know). But I am happy my base classes cannot
change under my feet ;)

You can just create a new class with new bases if you wish.
Michele Simionato
Jul 18 '05 #4
mi************* **@poste.it (Michele Simionato) writes:
David MacQuigg <dm*@gain.com > wrote in message news:<rm******* *************** **********@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((Mamm al,))
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.

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)

Cheers,
mwh

--
Academic politics is the most vicious and bitter form of politics,
because the stakes are so low. -- Wallace Sayre
Jul 18 '05 #5
Michael Hudson <mw*@python.net > wrote in message news:<m3******* *****@pc150.mat hs.bris.ac.uk>. ..
mi************* **@poste.it (Michele Simionato) writes:
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.


It is back!
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.


Uhm, I can see that in certain cases it may work, both what if a class
has "object" as base and we change it to "type" ? What if we change
the base class from new style to old style? What if we change one of
the base classes with another one which is instance of a different
metaclass? How do you solve the conflicts? What about ExtensionClasse s and
replacing normal bases with C-coded ones? I see a recipe for disasters here,
so that's why I thought the developer removed the option of changing the bases.
That would be understable. What I do not understand is why I cannot
change the __name__ of a function, what could possible go wrong with that??
Michele
Jul 18 '05 #6
On Thu, 17 Jun 2004 11:05:58 GMT, Michael Hudson <mw*@python.net >
wrote:
mi************ ***@poste.it (Michele Simionato) writes:
David MacQuigg <dm*@gain.com > wrote in message news:<rm******* *************** **********@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((Mamm al,))
> 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(na me, 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

Jul 18 '05 #7
mi************* **@poste.it (Michele Simionato) writes:
Michael Hudson <mw*@python.net > wrote in message news:<m3******* *****@pc150.mat hs.bris.ac.uk>. ..
mi************* **@poste.it (Michele Simionato) writes:
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.


It is back!
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.


Uhm, I can see that in certain cases it may work, both what if a
class has "object" as base and we change it to "type" ? What if we
change the base class from new style to old style? What if we change
one of the base classes with another one which is instance of a
different metaclass? How do you solve the conflicts? What about
ExtensionClasse s and replacing normal bases with C-coded ones?


You get an exception. Obviously. Did you actually read what I said?
I see a recipe for disasters here, so that's why I thought the
developer removed the option of changing the bases. That would be
understable. What I do not understand is why I cannot change the
__name__ of a function, what could possible go wrong with that??


Beats me too! Maybe it's because you haven't written a patch yet :-)

Cheers,
mwh

--
I think if we have the choice, I'd rather we didn't explicitly put
flaws in the reST syntax for the sole purpose of not insulting the
almighty. -- /will on the doc-sig
Jul 18 '05 #8
David MacQuigg <dm*@gain.com > writes:
On Thu, 17 Jun 2004 11:05:58 GMT, Michael Hudson <mw*@python.net >
wrote:
mi************ ***@poste.it (Michele Simionato) writes:
David MacQuigg <dm*@gain.com > wrote in message news:<rm******* *************** **********@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((Mamm al,))
> 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.


Well, possibly. It's generally assumed that you know what you're
doing if you want to muck with things on this level.

Clarifying patches welcome :-)
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)


Ugh!
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,

^^^^^^^^^^^^^^^ ^^^^^^^
What a what? I _really_ don't think you mean metaclass here.
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
Well, there are ways around that, too, eg:

def newAnimal(bases =(Animal,), **kw):
kw['_count'] = 0
return type('C', bases, kw)

Dog = newAnimal('Dog' , (Mammal,), temperature=102 , 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.
Well, not necessarily. Use the third parameter to the call to type().
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(na me, bases, dict) which appears to do the same thing as
type(name, bases, dict).
new.classobj() is a holdover from the days of old-style classes,
though I see it creates new-style classes if passed new-style bases...
What is the purpose of classobj()? The name is a little more
self-explanatory than 'type', but using it requires a module import.


Historical cruft, more-or-less.

Cheers,
mwh

--
ARTHUR: Why should a rock hum?
FORD: Maybe it feels good about being a rock.
-- The Hitch-Hikers Guide to the Galaxy, Episode 8
Jul 18 '05 #9
David MacQuigg <dm*@gain.com > wrote in message news:<gi******* *************** **********@4ax. com>...
On Thu, 17 Jun 2004 11:05:58 GMT, Michael Hudson <mw*@python.net >
wrote:
mi************ ***@poste.it (Michele Simionato) writes:
David MacQuigg <dm*@gain.com > wrote in message news:<rm******* *************** **********@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((Mamm al,))
> 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(na me, 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
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
1839
by: Eric Wilhelm | last post by:
Hi, By new-style classes, I'm referring to the changes which came into 2.2 as a result of PEP 252 and 253. I discovered this problem when trying to use the Perl Inline::Python module with a python class that was inheriting from the new builting 'object' class like so: class MyClass(object): The problem is in detecting that this class should be treated as a class
4
2082
by: Tuure Laurinolli | last post by:
Someone pasted the original version of the following code snippet on #python today. I started investigating why the new-style class didn't work as expected, and found that at least some instances of new-style classes apparently don't return true for PyInstance_Check, which causes a problem in PySequence_Check, since it will only do an attribute lookup for instances. Things probably shouldn't be this way. Should I go to python-dev with...
12
1591
by: Vaibhav | last post by:
I recently heard about 'new-style classes'. I am very sorry if this sounds like a newbie question, but what are they? I checked the Python Manual but did not find anything conclusive. Could someone please enlighten me? Thanks!
3
1281
by: Kalle Anke | last post by:
I'm confused by the concepts of old-style vs new-style classes, I've read most of the documents I found about this but it doesn't "click". Probably because I wasn't around before 2.2. Anyway, the reason for new style classes are to make the whole type/object thing work better together. There are a number of new features etc. I think my problem is when new-style classes are used, at first I thought that all classes become new-style...
1
1443
by: ankit | last post by:
Hello, Please put some light on, What are new style classes and classic style classes in python. The basic differences in them. And How can I decide to choose one.
2
1779
by: Jeff Rush | last post by:
While I have a reasonable understanding of the differences in new-style versus old-style classes, tonight while working a C extension module I realized I don't know how to indicate which style my C extension module should appear as. I'm following the Python docs for extended modules, but it doesn't say in there anyplace I can find which style I'm creating. My clue that something was wrong is when this: from cextension import Context
26
1837
by: momobear | last post by:
hi, I am puzzled about how to determine whether an object is initilized in one class, anyone could give me any instructions? here is an example code: class coffee: def boil(self): self.temp = 80 a = coffer() if a.temp 60:
13
2502
by: stephenpas | last post by:
We are trying to monkey-patch a third-party library that mixes new and old-style classes with multiple inheritance. In so doing we have uncovered some unexpected behaviour: <quote> class Foo: pass class Bar(object): pass
11
1446
by: allendowney | last post by:
Hi All, I am working on a revised edition of How To Think Like a Computer Scientist, which is going to be called Think Python. It will be published by Cambridge University Press, but there will still be a free version under the GNU FDL. You can see the latest version at thinkpython.com; I am revising now,
0
9589
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10211
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10045
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9994
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7409
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5447
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3959
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3562
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2815
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.