RE: [Python-Dev] RE: Hot-To Guide for Descriptors - Nits! :-)

François Pinard writes:
Would it be more precise to state: "... new style objects or classes (those for which the meta-class is a subtype of `type')"? Being sub-classed from object or type is just a way, among others, for identifying `type' as the meta-class; but being sub-classed from object is not really required.
Raymond Hettinger responds:
Nope, new-style is taken to mean objects/classes inheriting from object/type. Meta-class objects are neither new-style nor old-style. While there is room to argue with this arbitrary distinction, it is consistent with Guido's essay and especially relevant to my article because most of the rules don't necessarily apply when meta-classes are used. This is because the machinery for descriptors is embedded in type.__getattribute__ and object.__getattribute__. Override or fail to inherit either of these and all bets are off.
Really? I realize the utility of having a term for objects-with-a- meta-type-of-type, but I had always understood "new-style" to mean things-that-are-not-old-style-classes. I can live with either definition, but the Python community should make sure that we use the term "new-style class" in a consistent fashion. Did everyone else agree with Raymond so François and I are the odd men out, or is there a larger confusion over how we use the term? -- Michael Chermside This email may contain confidential or privileged information. If you believe you have received the message in error, please notify the sender and delete the message without copying or disclosing it.

François Pinard writes:
Would it be more precise to state: "... new style objects or classes (those for which the meta-class is a subtype of `type')"? Being sub-classed from object or type is just a way, among others, for identifying `type' as the meta-class; but being sub-classed from object is not really required.
Raymond Hettinger responds:
Nope, new-style is taken to mean objects/classes inheriting from object/type. Meta-class objects are neither new-style nor old-style. While there is room to argue with this arbitrary distinction, it is consistent with Guido's essay and especially relevant to my article because most of the rules don't necessarily apply when meta-classes are used. This is because the machinery for descriptors is embedded in type.__getattribute__ and object.__getattribute__. Override or fail to inherit either of these and all bets are off.
Michael Chermside
Really? I realize the utility of having a term for objects-with-a- meta-type-of-type, but I had always understood "new-style" to mean things-that-are-not-old-style-classes. I can live with either definition, but the Python community should make sure that we use the term "new-style class" in a consistent fashion.
Did everyone else agree with Raymond so François and I are the odd men out, or is there a larger confusion over how we use the term?
I'm with Raymond. Metaclasses that don't derive from 'type' can create objects that are neither fish nor flesh. --Guido van Rossum (home page: http://www.python.org/~guido/)

I'm with Raymond. Metaclasses that don't derive from 'type' can create objects that are neither fish nor flesh.
After thinking this through some more, I have to retract that. After all, even classic classes and their instances are derive from object:
class C: pass
isinstance(C, object) True
isinstance(C(), object) True
What makes a classic class is one very specific metaclass. What makes a classic instance is a class using that very specific metaclass. Everything else is a new-style class. Perhaps an exception should be made for Zope's ExtensionClasses, which are not classic classes but old-style "extension types", but they will disappear in the future and there's really nothing else like them. --Guido van Rossum (home page: http://www.python.org/~guido/)

I'm with Raymond. Metaclasses that don't derive from 'type' can create objects that are neither fish nor flesh.
After thinking this through some more, I have to retract that. After all, even classic classes and their instances are derive from object:
class C: pass
isinstance(C, object) True
isinstance(C(), object) True
Hmm, that surprises me. After all, writing class C(object): pass makes it new-style. Also dir(C()) or dir(C) does not show any of the methods given by dir(object) or dir(object()).
What makes a classic class is one very specific metaclass. What makes a classic instance is a class using that very specific metaclass. Everything else is a new-style class.
While true, I think it more pragmatic to have the docs and terminology *not* expressed in terms of meta-classes; rather, it is simpler to focus on the distinction between class C and class C(object), noting that all the new gizmos only work with the latter. The theory is simple, one shouldn't have to understand meta-classes in order be able to use property, classmethod, staticmethod, super, __slots__, __getattribute__, descriptors, etc. Practically, in all code that doesn't explicitly create meta-classes, the sole trigger between new and old is adding object, list, or other builtin type as a base class. IOW, I think the docs ought to continue using wording like this for property: "Return a property attribute for new-style classes (classes that derive from object)." There would be much loss of clarity and understanding with wording like: "Return a property attribute for a class whose metaclass is type or that implements the class semantics of type.__getattribute__ and the instance semantics of object.__getattribute__." For purposes of my article on descriptors, I'll continue with the current approach of ignoring meta-classes. There is enough information presented that meta-class writers will quickly understand why all the new-style gizmos stopped working when they didn't carry forward the semantics of object.__getattribute__ and type.__getattribute__. I think all of the topics are best understood in terms of three groups: classic classes, new-style classes, and roll your own classes. Lumping the latter two together won't help one bit. 'nuff said, Raymond Hettinger ################################################################# ################################################################# ################################################################# ##### ##### ##### ################################################################# ################################################################# #################################################################

On Wed, 2004-01-21 at 16:48, Raymond Hettinger wrote:
IOW, I think the docs ought to continue using wording like this for property: "Return a property attribute for new-style classes (classes that derive from object)."
I'd love it if we could come up with a different term for these beasts that "new style classes". Some day they won't be new any more, and may in fact be the only kind of classes in Python. Not that I have any good idea for what they should be called... -Barry

I'd love it if we could come up with a different term for these beasts that "new style classes". Some day they won't be new any more, and may in fact be the only kind of classes in Python. Not that I have any good idea for what they should be called...
Well, then we'd call them "classes", of course. --Guido van Rossum (home page: http://www.python.org/~guido/)

On Wed, 2004-01-21 at 16:55, Barry Warsaw wrote:
On Wed, 2004-01-21 at 16:48, Raymond Hettinger wrote:
IOW, I think the docs ought to continue using wording like this for property: "Return a property attribute for new-style classes (classes that derive from object)."
I'd love it if we could come up with a different term for these beasts that "new style classes". Some day they won't be new any more, and may in fact be the only kind of classes in Python. Not that I have any good idea for what they should be called...
Someday new-style classes will be old enough that they'll just be called classes. Classic classes will be a special case that people will have to explain. I don't think that will happen with current Python, because a class is a classic class unless you perform some explicit step to make it otherwise. If new-style classes were the default, then we could just call them classes. (And then we'd need some special way to construct classic classes.) Perhaps it's unfortunate that we have the names "new" and "classic." There could be users thinking that, like Coke, we'll forget about new classes and go back to classic classes. Jeremy

On Wed, Jan 21, 2004 at 04:55:51PM -0500, Barry Warsaw wrote:
I'd love it if we could come up with a different term for these beasts that "new style classes". Some day they won't be new any more, and may in fact be the only kind of classes in Python.
Yes. We should also rename 'newcompile.c' to 'astcompile.c' or something else before merging the AST branch. I've been on a chess kick recently and I find it humorous that the era of hyper-modern openings was about 80 years ago. Neil

On Wed, 2004-01-21 at 17:23, Neil Schemenauer wrote:
On Wed, Jan 21, 2004 at 04:55:51PM -0500, Barry Warsaw wrote:
I'd love it if we could come up with a different term for these beasts that "new style classes". Some day they won't be new any more, and may in fact be the only kind of classes in Python.
Yes. We should also rename 'newcompile.c' to 'astcompile.c' or something else before merging the AST branch. I've been on a chess kick recently and I find it humorous that the era of hyper-modern openings was about 80 years ago.
I had originally planned to just call it compile.c after the merge, but kept it separate so I could also have the original compiler on the same branch. astcompile.c sounds better. The computing literature has got lots of papers with new in the title, but most of the papers are old. Jeremy

[Barry Warsaw]
... I'd love it if we could come up with a different term for these beasts that "new style classes".
Then let me suggest ectomorphic classes, as opposed to the previous endomorphic classes. Roll-your-own classes can be called mesomorphic classes. Extension classes can be called paleomorphic classes. Then there's a precise term for each kind, and bystanders are automically informed by the very terminology used that their lives are too short to worry about the distinctions being drawn <wink>.

[Tim Peters]
Extension classes can be called paleomorphic classes. [...]
:-) -- François Pinard http://www.iro.umontreal.ca/~pinard

Then let me suggest ectomorphic classes, as opposed to the previous endomorphic classes. Roll-your-own classes can be called mesomorphic classes. Extension classes can be called paleomorphic classes. Then there's a precise term for each kind, and bystanders are automically informed by the very terminology used that their lives are too short to worry about the distinctions being drawn <wink>.
I'd be +1 on this being placed in the documentation, just to give readers a chuckle every time they read about classes. A little humor in the docs never hurt. - Josiah

After thinking this through some more, I have to retract that. After all, even classic classes and their instances are derive from object:
class C: pass
isinstance(C, object) True
isinstance(C(), object) True
Hmm, that surprises me. After all, writing class C(object): pass makes it new-style. Also dir(C()) or dir(C) does not show any of the methods given by dir(object) or dir(object()).
dir() special-cases classic classes. Classic class-ness and classic instance-ness are really subsumed by the new-style machinery -- there's a specific metaclass that produces classic classes, and those produce classic instances.
What makes a classic class is one very specific metaclass. What makes a classic instance is a class using that very specific metaclass. Everything else is a new-style class.
While true, I think it more pragmatic to have the docs and terminology *not* expressed in terms of meta-classes; rather, it is simpler to focus on the distinction between class C and class C(object), noting that all the new gizmos only work with the latter.
That's fine; there's nothing wrong with simply stating that classic classes don't *derive* from object. Note that in my little session I showed isinstance(C, object), which is True, but I didn't show issubclass(C, object), which is False -- it is the latter that makes C not a new-style class! (Not necessarily a classic class; it could be be an old-style extension type.)
The theory is simple, one shouldn't have to understand meta-classes in order be able to use property, classmethod, staticmethod, super, __slots__, __getattribute__, descriptors, etc.
Mostly right. But the fact that a class is also an object makes in unavoidable that the question is asked, and then you better have a good answer prepared.
Practically, in all code that doesn't explicitly create meta-classes, the sole trigger between new and old is adding object, list, or other builtin type as a base class.
Right. Or playing with __metaclass__, which is rare.
IOW, I think the docs ought to continue using wording like this for property: "Return a property attribute for new-style classes (classes that derive from object)."
I never said that was wrong. In fact IMO it is right.
There would be much loss of clarity and understanding with wording like: "Return a property attribute for a class whose metaclass is type or that implements the class semantics of type.__getattribute__ and the instance semantics of object.__getattribute__."
Of course.
For purposes of my article on descriptors, I'll continue with the current approach of ignoring meta-classes. There is enough information presented that meta-class writers will quickly understand why all the new-style gizmos stopped working when they didn't carry forward the semantics of object.__getattribute__ and type.__getattribute__.
Right. And meta-classes are still head-exploding material.
I think all of the topics are best understood in terms of three groups: classic classes, new-style classes, and roll your own classes. Lumping the latter two together won't help one bit.
Especially since it can be done using either classic or new-style classes. --Guido van Rossum (home page: http://www.python.org/~guido/)

[Raymond Hettinger]
Hmm, that surprises me. After all, writing class C(object): pass makes it new-style.
This is only because there is not __metaclass__ assignment within the class. In this case, according to: http://www.python.org/2.2.3/descrintro.html in the `Metaclasses' section, under "How is M determined?", we read: "... if there is at least one base class, its metaclass is used". The type of object is type itself. If there is no base class, then "if there's a global variable named __metaclass__, it is used." So my guess would be that adding a mere __metaclass__ = type in global scope for a module would make all classes be "new-style", without the need to subclass them from object explicitly. Experimenting a bit with these things, I noticed that `object.__new__' may be called from a class `__new__', and `object.__init__' the same, without that class needing to be subclassed from object. This does not help me getting away from the feeling that new-style classes do not need to be sub-classed from object. Another point is that in Python 3.0, it is unlikely that Guido forces everybody to subclass all classes from object, for these classes to work. I would not think that being sub-classed from object, at least explicitely in the class declaration, is a proper characterisation of new-style classes. This is one way of course, but not the necessary one. I was reading the "How-to ... Descriptors" as asserting this.
While true, I think it more pragmatic to have the docs and terminology *not* expressed in terms of meta-classes;
While docs and terminology need to be pragmatic, it is important that they could be dependable. One thing I would like to do is experimenting a lot of already written Python code in the context of new-style classes, just to see how solid things would be in that context. I suspect nothing will break, but we have to experiment it. My guess is that merely adding: __metaclass__ = type at the beginning of each module is sufficient for the experiment. It is simpler adding one line per module than to edit all base class declarations for adding (object) to them. I am not tempted to add them without at least understanding that they are really necessary. Adding at random would be symptomatic of my lack of grasp on the implied matters. In one other message, you assert that "All bets are off!" if I do not sub-class from object, but are you really damn fully sure of this? :-) It looks a bit like an argument of authority, and maybe more a guess than knowledge (no offence intended, of course). I just want to make sure I really got a definitive reply on this, and preferably, one that I can understand enough to repeat it myself with conviction! :-)
IOW, I think the docs ought to continue using wording like this for property: "Return a property attribute for new-style classes (classes that derive from object)."
Yes, as long as this wording does not mislead the reader into thinking untrue things. Now, I'm not sure what `derive' really means. I read it as meaning `derive by explicit sub-classing', but it might imply something else. Without a precise meaning, the sentence is not so meaningful. The classic metatype itself is an object, you know, so one could say that classic classes also derive from object.
I think all of the topics are best understood in terms of three groups: classic classes, new-style classes, and roll your own classes. Lumping the latter two together won't help one bit.
Unless there is only two groups, in which case "lumping" would just get nearer the truth. I surely have to study a lot more, descriptors in particular, before I can make more sense of all this. Once again, I apologise for any wrong assertion I could have made above, or elsewhere, I do not intend to hurt or contradict anybody, but only to develop a more solid understanding. -- François Pinard http://www.iro.umontreal.ca/~pinard

On Wed, 2004-01-21 at 20:24, François Pinard wrote:
If there is no base class, then "if there's a global variable named __metaclass__, it is used." So my guess would be that adding a mere
__metaclass__ = type
in global scope for a module would make all classes be "new-style", without the need to subclass them from object explicitly.
Unless you define a class that inherits from a base class defined in another module. __metaclass__ does not apply when there are base classes. I prefer to inherit from object, because it is more explicit, and avoids possible confusion when some classes have classic bases. Jeremy

[Jeremy Hylton]
On Wed, 2004-01-21 at 20:24, François Pinard wrote:
If there is no base class, then "if there's a global variable named __metaclass__, it is used." So my guess would be that adding a mere
__metaclass__ = type
in global scope for a module would make all classes be "new-style", without the need to subclass them from object explicitly.
Unless you define a class that inherits from a base class defined in another module.
I thought about this of course. This is no problem in our case, since these other modules will have their `__metaclass__ = type' themselves.
I prefer to inherit from object, because it is more explicit, and avoids possible confusion when some classes have classic bases.
A `__metaclass__ = type' at the beginning of a module is explicit enough to my eyes. If I can demonstrate that this does not harm, it will become a convention here to include this line in each and every module for all in-house projects, and we should be done with classic classes. Unless we sub-class classic classes from the Python library, I do not know how frequently we do that. By the way :-), I presume there are plans for the Python library to progressively switch to new-style classes whenever possible? If not, should they be? -- François Pinard http://www.iro.umontreal.ca/~pinard

On Wed, Jan 21, 2004, Raymond Hettinger wrote:
I think all of the topics are best understood in terms of three groups: classic classes, new-style classes, and roll your own classes. Lumping the latter two together won't help one bit.
While that's technically true, most of the idiomatic uses of metaclasses that I've seen *do* result in the creation of "normal" new-style classes. We don't want to obscure that, either, IMO. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ A: No. Q: Is top-posting okay?

I think all of the topics are best understood in terms of three groups: classic classes, new-style classes, and roll your own classes. Lumping the latter two together won't help one bit.
While that's technically true, most of the idiomatic uses of
[Aahz] metaclasses
that I've seen *do* result in the creation of "normal" new-style classes. We don't want to obscure that, either, IMO.
Okay, I've added a paragraph to the descriptor guide: """ The details above show that the mechanism for descriptors is embedded in the __getattribute__() methods for object, type, and super. Classes inherit this machinery when they derive from object or if they have a meta-class providing similar functionality. Likewise, classes can turn-off descriptor invocation by overriding __getattribute__(). """ Raymond Hettinger

[Raymond Hettinger]
""" The details above show that the mechanism for descriptors is embedded in the __getattribute__() methods for object, type, and super. Classes inherit this machinery when they derive from object or if they have a meta-class providing similar functionality. Likewise, classes can turn-off descriptor invocation by overriding __getattribute__(). """
Nice! :-) -- François Pinard http://www.iro.umontreal.ca/~pinard
participants (11)
-
Aahz
-
Barry Warsaw
-
Chermside, Michael
-
François Pinard
-
Guido van Rossum
-
Jeremy Hylton
-
Jeremy Hylton
-
Josiah Carlson
-
Neil Schemenauer
-
Raymond Hettinger
-
Tim Peters