classification
Title: descriptor and repr get into conflict
Type: crash Stage:
Components: Versions: Python 3.5
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Sabine.maennel@gmail.com, benjamin.peterson
Priority: normal Keywords:

Created on 2016-09-30 06:31 by Sabine.maennel@gmail.com, last changed 2016-09-30 06:40 by benjamin.peterson. This issue is now closed.

Files
File name Uploaded Description Edit
descriptor_and_repr_error Sabine.maennel@gmail.com, 2016-09-30 06:31 interactive session protocol
Messages (2)
msg277740 - (view) Author: Sabine Maennel (Sabine.maennel@gmail.com) Date: 2016-09-30 06:31
I was working with descriptors and hit on an error, that I do not understand. 
I attach a protocol of my interactive python session that will show you what happened and the session is reproducible:

I had a class employing a descriptor: 
class Descriptor(object):
    def __init__(self, name):
        self.name = name
    def __set__(self, instance, val):
        print('Updating', self.name, 'for', instance)
        instance.__dict__[self.name] = val

class A:
    x = Descriptor('x')
    def __init__(self, name, x):
        self.x = x
        self.name = name
    def __repr__(self):
        return "I am {}".format(self.name)

if defined like this it hits an error when I want to initialize it:
a = A('a', 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
  File "<stdin>", line 5, in __set__
  File "<stdin>", line 7, in __repr__
AttributeError: 'A' object has no attribute 'name'
Updating x for 

The error could be fixed by just exchanging the assignments in the __init__ of A:
class A:
    x = Descriptor('x')
    def __init__(self, name, x):
        self.name = name
        self.x = x
    def __repr__(self):
        return "I am {}".format(self.name)
Now a = A('a', 2) works as expected. But this seems weird to me.
msg277742 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2016-09-30 06:40
This is no different than this simpler case:

class A:
    def __init__(self, name):
        print("init {!r}".format(self))
        self.name = name
    def __repr__(self):
        return "I am {}".format(self.name)

The instance of A doesn't not have a name attribute for __repr__ to use until you set it.
History
Date User Action Args
2016-09-30 06:40:19benjamin.petersonsetstatus: open -> closed

nosy: + benjamin.peterson
messages: + msg277742

resolution: not a bug
2016-09-30 06:31:55Sabine.maennel@gmail.comcreate