class Foo(object) vs class Foo: should be clearly explained in python 2 and 3 doc

Hi. Referring to my discussion on [1] and then on #python this afternoon. A little background would help people to understand where this was coming from. 1. I write Python 2 code and have done zero Python-3 specific code. 2. I have always been using class Foo(object) so I do not know the new style is no longer required in Python 3. I feel "stupid" and "wrong" by thinking (object) is still a convention in Python 3. 3. Many Python 2 tutorials do not use object as the base class whether for historical reason, or lack of information/education, and can cause confusing to newcomers searching for answers when they consult the official documentation. While Python 3 code no longer requires object be the base class for the new-style class definition, I believe (object) is still required if one has to write a 2-3 compatible code. But this was not explained or warned anywhere in Python 2 and Python 3 code, AFAIK. (if I am wrong, please correct me) I propose the followings: * It is desirable to state boldly to users that (object) is no longer needed in Python-3 **only** code and warn users to revert to (object) style if the code needs to be 2 and 3 compatible. * In addition, Python 2 doc [2] should be fixed by introducing the new-style classes. This problem was noted a long long time ago according to [4]. * I would like to see warnings from suggested action item 1 on [2] and [3], for python 2 and 3 documentations. Possible objections(s): * We are pushing toward Python 3, some years later we don't need to maintain both Python 2 and 3 code. And many people, especially the newcomers will probably have no need to maintain Python 2 and 3 compatible codes. My answer to that is we need to be careful with marketing. First, it is a little embarrassing to assume and to find out the assumption is not entirely accurate. Secondly, Python 2 will not go away any time soon and most tutorials available on the Internet today are still written for Python 2. Furthermore, this CAN be a "gotcha" for new developers knowing only Python 3 writing Python 2 & 3 compatible code. * Books can do a better job I haven't actually reviewed/read any Python 3 books knowing most of my code should work without bothering Python 3-2 incompatibility yet. So I don't have an accurate answer, but a very very quick glance over a popular Python 3 book (I am not sure if naming it out is ethical or not so I am going to grey it out here) the book just writes class Foo: and doesn't note the different between 2 and 3 with classes. It is not wrong since the book is about programming in Python 3, NOT writing 2 and 3, but this is where the communication breaks. Docs and books don't give all the answers needed. P.S. Sorry if I should've have asked on #python-dev first or made a ticket but I've decided to send to mailing list before making a bug ticket. First time! Thanks. Best, Yeuk Hon [1]: https://news.ycombinator.com/item?id=8154471 [2]: https://docs.python.org/2/tutorial/classes.html https://docs.python.org/3/tutorial/classes.html [3]: https://docs.python.org/3/tutorial/classes.html [4]: https://www.python.org/doc/newstyle/

On 8/9/2014 2:44 PM, John Yeuk Hon Wong wrote:
Hi.
Referring to my discussion on [1] and then on #python this afternoon.
A little background would help people to understand where this was coming from.
1. I write Python 2 code and have done zero Python-3 specific code. 2. I have always been using class Foo(object) so I do not know the new style is no longer required in Python 3. I feel "stupid" and "wrong" by thinking (object) is still a convention in Python 3.
If someone else tried to make you feel that way, they are Code of Conduct violators who should be ignored. If you are beating yourself on the head, stop.
3. Many Python 2 tutorials do not use object as the base class whether for historical reason, or lack of information/education,
Probably both. Either way, the result is a disservice to readers.
and can cause confusing to newcomers searching for answers when they consult the official documentation.
I and some other people STRONGLY recommend that newcomers start with Python 3 and Python 3 docs and completely ignore Python 2 unless they cannot.
While Python 3 code no longer requires object be the base class for the new-style class definition, I believe (object) is still required if one has to write a 2-3 compatible code. But this was not explained or warned anywhere in Python 2 and Python 3 code, AFAIK. (if I am wrong, please correct me)
I propose the followings:
* It is desirable to state boldly to users that (object) is no longer needed in Python-3 **only** code and warn users to revert to (object) style if the code needs to be 2 and 3 compatible.
I think 'boldly' and 'warn' are a bit overstated.
* In addition, Python 2 doc [2] should be fixed by introducing the new-style classes.
Definitely. The 2.x tutorial start with class x: and continues that way half way through the chapter. I think it should start with class x(object): and at the end of the first half, briefly mention that class x in 2.x gets something slightly different that beginners can mostly ignore, while class x: in 3.x == class x(object): and that the latter works the same for both. The 3.x tutorial, in the same place could *briefly* mention that class x: == class x(object): and the the latter is usually only used in code that also runs on 2.x or has been converted without removing the extra code. The 3.x tutorial should *not* mention old style classes.
This problem was noted a long long time ago according to [4].
The opening statement "Unfortunately, new-style classes have not yet been integrated into Python's standard documention." is perhaps a decade out of date. That page should not have been included in the new site design without being modified.
[1]: https://news.ycombinator.com/item?id=8154471
[2]: https://docs.python.org/2/tutorial/classes.html https://docs.python.org/3/tutorial/classes.html
-- Terry Jan Reedy

On Sat, Aug 09, 2014 at 02:44:10PM -0400, John Yeuk Hon Wong wrote:
Hi.
Referring to my discussion on [1] and then on #python this afternoon.
A little background would help people to understand where this was coming from.
1. I write Python 2 code and have done zero Python-3 specific code. 2. I have always been using class Foo(object) so I do not know the new style is no longer required in Python 3. I feel "stupid" and "wrong" by thinking (object) is still a convention in Python 3.
But object is still a convention in Python 3. It is certainly required when writing code that will behave the same in version 2 and 3, and it's optional in 3-only code, but certainly not frowned upon or discouraged. There's nothing wrong with explicitly inheriting from object in Python 3, and with the Zen of Python "Explicit is better than implicit" I would argue that *leaving it out* should be very slightly discouraged. class Spam: # okay, but a bit lazy class Spam(object): # better Perhaps PEP 8 should make a recommendation, but if so, I think it should be a very weak one. In Python 3, it really doesn't matter which you write. My own personal practice is to explicitly inherit from object when the class is "important" or more than half a dozen lines, and leave it out if the class is a stub or tiny.
3. Many Python 2 tutorials do not use object as the base class whether for historical reason, or lack of information/education, and can cause confusing to newcomers searching for answers when they consult the official documentation.
We can't do anything about third party tutorials :-(
While Python 3 code no longer requires object be the base class for the new-style class definition, I believe (object) is still required if one has to write a 2-3 compatible code. But this was not explained or warned anywhere in Python 2 and Python 3 code, AFAIK. (if I am wrong, please correct me)
It's not *always* required, only if you use features which require new-style classes, e.g. super, or properties.
I propose the followings:
* It is desirable to state boldly to users that (object) is no longer needed in Python-3 **only** code
I'm against that. Stating this boldly will be understood by some readers that object should not be used, and I'm strongly against that. I believe explicitly inheriting from object should be mildly preferred, not strongly discouraged.
and warn users to revert to (object) style if the code needs to be 2 and 3 compatible.
I don't think that should be necesary, but have no objections to it being mentioned. I think it should be obvious: if you need new-style behaviour in Python 2, then obviously you have to inherit from object otherwise you have a classic class. That requirement doesn't go away just because your code will sometimes run under Python 3. Looking at your comment here:
there is a reply from zeckalpha, who says: "Actually, leaving out `object` is the preferred convention for Python 3, as they are semantically equivalent." How does (s)he justify this claim? "Explicit is better than implicit." which is not logical. If you leave out `object`, that's implicit, not explicit. -- Steven

On Sun, Aug 10, 2014 at 10:44 AM, Steven D'Aprano <steve@pearwood.info> wrote:
Looking at your comment here:
there is a reply from zeckalpha, who says:
"Actually, leaving out `object` is the preferred convention for Python 3, as they are semantically equivalent."
How does (s)he justify this claim?
"Explicit is better than implicit."
which is not logical. If you leave out `object`, that's implicit, not explicit.
The justification is illogical. However, I personally believe boilerplate should be omitted where possible; that's why we have a whole lot of things that "just work". Why does Python not have explicit boolification for if/while checks? REXX does (if you try to use anything else, you get a run-time error "Logical value not 0 or 1"), and that's more explicit - Python could require you to write "if bool(x)" for the case where you actually want the truthiness magic, to distinguish from "if x is not None" etc. But that's unnecessary boilerplate. Python could have required explicit nonlocal declarations for all names used in closures, but that's unhelpful too. Python strives to eliminate that kind of thing. So, my view would be: Py3-only tutorials can and probably should omit it, for the same reason that we don't advise piles of __future__ directives. You can always add stuff later for coping with Py2+Py3 execution; chances are any non-trivial code will have much bigger issues than accidentally making an old-style class. ChrisA

Chris Angelico writes:
The justification is illogical. However, I personally believe boilerplate should be omitted where possible;
But it mostly can't be omitted. I wrote 22 classes (all trivial) yesterday for a Python 3 program. Not one derived directly from object. That's a bit unusual, but in the three longish scripts I have to hand, not one had more than 30% "new" classes derived from object. As a matter of personal style, I don't use optional positional arguments (with a few "traditional" exceptions); if I omit one most of the time, when I need it I use a keyword. That's not an argument, it's just an observation that's consistent with support for using an explicit parent class of object "most of the time".
that's why we have a whole lot of things that "just work". Why does Python not have explicit boolification for if/while checks?
Because it does have explicit boolification (signaled by the control structure syntax itself). No? I don't think this is less explicit than REXX, because it doesn't happen elsewhere (10 + False == 10 -- not True, and even bool(10) + False != True).
So, my view would be: Py3-only tutorials can and probably should omit it,
But this doesn't make things simpler. It means that there are two syntaxes to define some classes, and you want to make one of them TOOWTDI for classes derived directly from object, and the other TOOWTDI for non-trivial subclasses. I'll grant that in some sense it's no more complex, either, of course. Note that taken to extremes, your argument could be construed as "we should define defaults for all arguments and omit them where possible". Of course for typing in quick programs, and for trivial classes, omitting the derivation from object is a useful convenience. But I don't think it's something that should be encouraged in tutorials. Steve

On Sat, Aug 9, 2014 at 8:44 PM, Steven D'Aprano <steve@pearwood.info> wrote:
It is certainly required when writing code that will behave the same in version 2 and 3
This is not true. An alternative is to put __metaclass__ = type at the top of your module to make all classes in your module new-style in python2.

On Aug 10, 2014, at 11:51 AM, Alexander Belopolsky wrote:
This is not true. An alternative is to put
__metaclass__ = type
at the top of your module to make all classes in your module new-style in python2.
I like this much better, and it's what I do in my own bilingual code. It makes it much easier to remove the unnecessary cruft when you drop the Python 2 support. -Barry

On Sun, Aug 10, 2014 at 11:51:51AM -0400, Alexander Belopolsky wrote:
On Sat, Aug 9, 2014 at 8:44 PM, Steven D'Aprano <steve@pearwood.info> wrote:
It is certainly required when writing code that will behave the same in version 2 and 3
This is not true. An alternative is to put
__metaclass__ = type
at the top of your module to make all classes in your module new-style in python2.
So it is. I forgot about that, thank you for the correction. -- Steven
participants (7)
-
Alexander Belopolsky
-
Barry Warsaw
-
Chris Angelico
-
John Yeuk Hon Wong
-
Stephen J. Turnbull
-
Steven D'Aprano
-
Terry Reedy