classification
Title: Show the address in the repr for class objects
Type: enhancement Stage: resolved
Components: Versions: Python 3.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: kushal.das Nosy List: Nofar Schnider, Tim.Graham, Winterflower, abarry, brett.cannon, gvanrossum, kushal.das, martin.panter, matrixise, mbussonn, ned.deily, petere, ppperry, python-dev, rhettinger, terry.reedy
Priority: release blocker Keywords: patch

Created on 2015-11-03 18:40 by rhettinger, last changed 2016-07-14 04:13 by python-dev. This issue is now closed.

Files
File name Uploaded Description Edit
issue25548.patch kushal.das, 2016-06-02 21:44 Code and test updates for the same review
issue25548v2.patch kushal.das, 2016-06-03 16:40 Second version of the patch review
issue25548v4.patch kushal.das, 2016-06-03 18:01 with news update review
Messages (27)
msg254012 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2015-11-03 18:40
In old-style classes, the memory address of the class object is shown for both the class and for the instance.  In new-style classes, only the instance shows the address.  I and other Python instructors have found the memory address display to be useful and I think it should be added back:

Old-style
=========
 
  >>> class A:
  	pass

  >>> a = A()
  >>> A
  <class __main__.A at 0x10061e328>
  >>> a
  <__main__.A instance at 0x105292cb0> 


New-style
=========

  >>> class A(object):
  	pass

  >>> a = A()
  >>> A
  <class '__main__.A'>
  >>> a
  <__main__.A object at 0x105332cd0>
msg254017 - (view) Author: St├ęphane Wirtel (matrixise) * (Python committer) Date: 2015-11-03 21:06
Hi Raymond,

I just executed the code with python 3.5 and I don't have this result:

Python 3.5.0 (default, Sep 23 2015, 04:41:38)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.72)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class A: pass
...
>>> A
<class '__main__.A'>
>>> class A(object): pass
...
>>> A
<class '__main__.A'>
>>>
msg254232 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2015-11-06 21:56
In 3.x, old style classes are gone, so you get a new style class with or without '(object)'.
msg265883 - (view) Author: (ppperry) Date: 2016-05-19 19:09
I don't quite get why the memory address is helpful, but you could work around this using a custom metaclass:

    class IdMeta(type):
        def __repr__(cls):
            return super().__repr__()[:-1] + " at 0x%x>"%id(cls)
    class IdInRepr(metaclass=IdMeta):pass

`IdInRepr` and all its subclasses will then have the memory address in their representation:

  <class 'module.name' at address>
msg266038 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2016-05-22 01:27
> I don't quite get why the memory address is helpful

For the same reason that we've found the address to helpful in other reprs, it helps people understand that classes are objects just like anything else and to know which objects are distinct.

My instructors have found that this matters when teaching Python and more than one of them immediately noticed the loss of information when switching from teaching Python 2 to Python 3.
msg266963 - (view) Author: Kushal Das (kushal.das) * (Python committer) Date: 2016-06-02 21:44
Attaching the patch for the same. Had to update the test cases for the following tests to have this behavior as expected.

test_functools 
test_cmd_line_script 
test_ctypes 
test_defaultdict 
test_descr
test_descrtut 
test_doctest 
test_generators
test_genexps 
test_metaclass 
test_pprint 
test_reprlib
test_statistics 
test_trace 
test_wsgiref
msg267110 - (view) Author: Kushal Das (kushal.das) * (Python committer) Date: 2016-06-03 16:40
Uploading the new patch with a new test case for the same.
msg267112 - (view) Author: Anilyka Barry (abarry) * (Python triager) Date: 2016-06-03 17:13
I'd probably change all instances of ".*" in the regex matches to be "0x.+" instead. For the docstrings that have "..." in them, I would probably make those " at ..." as well (although you get decide if it hinders readability too much).

Other than that patch LGTM.
msg267113 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2016-06-03 17:18
Patch LGTM. Just needs doc and What's New updates.
msg267119 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2016-06-03 17:47
Kushal.  If you don't mind, I would like Nofar to be able to do this patch.  She's been working on it since before the sprints and was slowed down by a schoolwork crunch.
msg267121 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2016-06-03 17:56
Nofar is about to upload her patch as well (she's been working on this for a while).  Perhaps the two can be compared and reconciled so that both can be credited on the commit.
msg267122 - (view) Author: Kushal Das (kushal.das) * (Python committer) Date: 2016-06-03 18:01
Hey Raymond, I am uploading the patch which I almost committed along with whats new update :)
I am also reassigning the ticket to you so that you can decide the next steps.
msg267225 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2016-06-04 03:14
Thanks Kushal.   It looks like we had a race condition ;-)   I'll assign it back after Nofar's work is in and reconciled.
msg267286 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2016-06-04 17:34
Nofar said not to wait for her on this one.
msg267344 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-06-04 23:24
New changeset af29d89083b3 by Kushal Das in branch 'default':
Issue #25548: Showing memory address of class objects in repl
https://hg.python.org/cpython/rev/af29d89083b3
msg267403 - (view) Author: Nofar Schnider (Nofar Schnider) * (Python triager) Date: 2016-06-05 08:57
Kushal, you've beat me to it. Great work!
msg267704 - (view) Author: Matthias Bussonnier (mbussonn) * Date: 2016-06-07 16:56
Hi guys, the title of the issues is "show address in the **repR**", but the NEWS file says[1] in the **repL*, which are 2 different things ! :-)

And this patch change the repR so it also affect scripts and unittests. 

[1] since https://hg.python.org/cpython/rev/af29d89083b3
msg268760 - (view) Author: Peter Eisentraut (petere) * Date: 2016-06-18 04:30
I understand the reasoning here, but I want to say booh to this change in 3.6.0a2 because it breaks my tests.  It used to be that type(x) returned a predictable string, and that was an easy way to verify the result types of things.

Perhaps a __str__ implementation could be added that avoids the memory address?
msg268763 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2016-06-18 04:51
There is also Issue 13224 proposing to change __str__() to just return the __name__ or __qualname__ if I remember correctly.
msg269075 - (view) Author: Tim Graham (Tim.Graham) * Date: 2016-06-22 14:38
I'll echo what Peter said and say that this breaks 5 tests in Django's test suite which are checking error messages. If it stays, perhaps it could be added to the release notes instead of just NEWS.
msg270262 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2016-07-12 18:45
I'm also echoing this... It breaks too many tests. I filed issue27498.
msg270296 - (view) Author: Kushal Das (kushal.das) * (Python committer) Date: 2016-07-13 04:14
The NEWS file got a typo. Thanks for noticing that.
This change did require a lot of updates to the tests.
If rest of the people agrees to revert this change, then we should go ahead and do it. Just wondering if Raymond has anything to add.
msg270313 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2016-07-13 14:59
Would there be a way to confine this to just heap types?  The user defined classes are where there is the most benefit.  For the built-in types, it just seems to add noise.
msg270314 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2016-07-13 15:07
Doing it only for user-defined types would still break my tests.
msg270342 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2016-07-13 20:24
+1 on rolling this back.  It sounds like it hurt more than it would have helped.

To satisfy my curiosity, can you post one of the tests that broke.  It would be nice to see what kind of tests are depend the repr of the class.  AFAICT, there was never an issue with this for old-style classes in Python2.7, so something new must be occurring in the wild.
msg270345 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2016-07-13 20:47
Thanks, let's roll it back.

The reason it never was an issue for old-style classes is that they
behaved like this from the start, so nobody wrote tests that depended
on the predictability of repr(). But new-style classes have had this
nice clean repr() since they were introduced (in 2.3?) so it's
unsurprising that this is now depended upon.

Here's a link to some test code for mypy that broke:
https://github.com/python/mypy/blob/master/mypy/util.py#L22-L23

It may be irreprehensible code but it works for Python 3.2-3.5 (and
for new-style classes in Python 2, except mypy requires Python 3), and
broke in 3.6.
msg270360 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-07-14 04:13
New changeset 4f11e6b72e8f by Benjamin Peterson in branch 'default':
Backed out changeset af29d89083b3 (closes #25548) (closes #27498)
https://hg.python.org/cpython/rev/4f11e6b72e8f
History
Date User Action Args
2016-10-06 11:09:54berker.peksagunlinkissue27232 superseder
2016-07-14 04:13:42python-devsetstatus: open -> closed

nosy: + ned.deily
messages: + msg270360

resolution: fixed
stage: commit review -> resolved
2016-07-13 22:30:47ned.deilysetpriority: normal -> release blocker
2016-07-13 20:47:36gvanrossumsetmessages: + msg270345
2016-07-13 20:24:10rhettingersetmessages: + msg270342
2016-07-13 15:07:52gvanrossumsetmessages: + msg270314
2016-07-13 14:59:40rhettingersetmessages: + msg270313
2016-07-13 04:14:42kushal.dassetmessages: + msg270296
2016-07-12 18:45:27gvanrossumsetnosy: + gvanrossum
messages: + msg270262
2016-06-22 14:38:25Tim.Grahamsetnosy: + Tim.Graham
messages: + msg269075
2016-06-18 04:51:51martin.pantersetnosy: + martin.panter
messages: + msg268763
2016-06-18 04:30:37peteresetnosy: + petere
messages: + msg268760
2016-06-07 16:56:28mbussonnsetnosy: + mbussonn
messages: + msg267704
2016-06-06 06:50:15SilentGhostlinkissue27232 superseder
2016-06-05 08:57:57Nofar Schnidersetmessages: + msg267403
2016-06-04 23:24:19python-devsetnosy: + python-dev
messages: + msg267344
2016-06-04 17:34:04rhettingersetassignee: rhettinger -> kushal.das
messages: + msg267286
2016-06-04 03:14:30rhettingersetmessages: + msg267225
2016-06-03 18:01:09kushal.dassetfiles: + issue25548v4.patch
assignee: kushal.das -> rhettinger
messages: + msg267122
2016-06-03 17:56:19rhettingersetmessages: + msg267121
2016-06-03 17:47:08rhettingersetmessages: + msg267119
2016-06-03 17:18:39brett.cannonsetnosy: + brett.cannon
messages: + msg267113

assignee: kushal.das
stage: patch review -> commit review
2016-06-03 17:13:15abarrysetnosy: + abarry

messages: + msg267112
stage: patch review
2016-06-03 16:40:32kushal.dassetfiles: + issue25548v2.patch

messages: + msg267110
2016-06-02 21:44:30kushal.dassetfiles: + issue25548.patch

nosy: + kushal.das
messages: + msg266963

keywords: + patch
2016-05-31 09:28:20Nofar Schnidersetnosy: + Nofar Schnider
2016-05-22 01:27:30rhettingersetmessages: + msg266038
2016-05-19 19:09:37ppperrysetnosy: + ppperry
messages: + msg265883
2016-05-18 20:18:05Winterflowersetnosy: + Winterflower
2015-11-06 21:56:28terry.reedysetnosy: + terry.reedy
messages: + msg254232
2015-11-03 21:06:20matrixisesetnosy: + matrixise
messages: + msg254017
2015-11-03 18:40:11rhettingercreate