0

I am a quit new python programer and just for curiosity I want to know how I can reach to the name of instance which is made in the body of main,in the methods of my class . I want to know whether there is a built-in method for classes or I should manage it myself. by the way, I don't want to use lists or Dictionaries. a sample code is following:

class Vec2D(object):
   def __init__(self,X, Y):
     self.x=X
     self.y=Y
     print "X coordinate is ",self.x # I want to add it here 
     print "Y coordinate is ",self.y # and here

if __name__ == '__main__':
    mypoint1 = Vec2D(0,1)
    mypoint2 = Vec2D(1,2)

It could be considered as a reporting issue...

martineau
  • 119,623
  • 25
  • 170
  • 301
msc87
  • 943
  • 3
  • 17
  • 39

3 Answers3

3

You can't. A value has no way to know what variable refers to it.

The reason is quite simple; you can have multiple variables refer to the same value:

mypoint3 = mypoint1

Now what name does the instance have?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • You *could* probably inspect the frame object and compare all of the objects in `frame.f_locals` or `frame.f_globals` with `self` until you got a match ... but that's pretty messy and (as you point out), there is no guarantee for a unique name. – mgilson Jan 14 '13 at 16:25
  • you mean there is a one-way pointer to the value from instance?!!! what if I want to check an instance by its values and then do something with the instance for example equal it with another instance?! – msc87 Jan 14 '13 at 16:25
  • @msc87 because it's a terrible violation of the decomposition principle. What is a language where you saw such a practice? – Ivan Yurchenko Jan 14 '13 at 16:36
  • @Ivan: as I menetioned it is only my curiosity...:) but, in object oriented, you use constructor to create an object, after you create it, you might want to check it in order to see if it follows the rules, if not you set the instance to default instance. it is not exactly the application of my question. – msc87 Jan 14 '13 at 16:42
  • 1
    @msc87: Checking the instance would be the job of the class. You could use a factory function to create an instance or return a default instead if validation fails. – Martijn Pieters Jan 14 '13 at 16:57
1

As @MartijnPieters said, these's no way to get the variable name of an instance. The names are not kept after interpreting.

But if you do have the special need, I think there're at least 2 approaches for you.

Let's say you have an instance MyInstance of class MyClass, then

  1. str(MyInstance) will give you a string like <__main__.MyClass instance at 0x1044b6f80>, it uniquely indicates MyInstanceduring the runtime. You might want to use it as the name of the instance.

  2. Explicitly define a "name" in the construction of the class, like:

    class MyClass:
        def __init__(self, name):
            self.name = name
    

    . Afterwards you can always get the name by:

    MyInstance = MyClass("Instance1")
    print MyInstance.name
    
Timothy
  • 4,467
  • 5
  • 28
  • 51
1

Well, for starters, you couldn't print the name in __init__() because the object is still being constructed and hasn't been assigned one yet. Even if it were, there's no built-in way to find out what it is in Python.

However it is possible to search for the object after construction in the module's global namespace, which allows you to do things like this:

class Vec2D(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        my_name = '<unknown>'
        namespace = globals().copy()
        for name,obj in namespace.items():
            if obj is self:
                my_name = name
                break
        return "\n".join(["{!r}:",
                          "  X coordinate is {}",
                          "  Y coordinate is {}"]).format(my_name, self.x, self.y)

if __name__ == '__main__':
    mypoint1 = Vec2D(0,1)
    mypoint2 = Vec2D(1,2)

    print mypoint1
    print mypoint2

Output:

'mypoint1':
  X coordinate is 0
  Y coordinate is 1
'mypoint2':
  X coordinate is 1
  Y coordinate is 2

However this isn't foolproof because if there are two names for the same object, the for search loop will stop as soon as it finds one of them. It could be modified to find them all, I suppose...

martineau
  • 119,623
  • 25
  • 170
  • 301
  • I copied your code, but it returns this error: zero length field name in format. I think this should be caused by my python version. I am using 2.6 – msc87 Jan 14 '13 at 18:39
  • I'm using Python 2.7.3, but I don't think that's the problem...but don't know what else it could be. Perhaps you can determine which field it's complaining about by breaking the building of the returned string value up into separate statements and seeing which one it complains about. – martineau Jan 14 '13 at 18:48