YaGoi Root
YaGoi Root

Reputation: 29

Python - How to print the variable name of an Object

Thanks for reading. Preface, I don't mean how to make a print(objectA) make python output something other than the <__main__.A object at 0x00000273BC36A5C0> via the redefining the __str__ attribute.

I will use the following example to try to explain what I'm doing.

class Point:
    '''
    Represents a point in 2D space
    attributes: x, y
    '''

    def __init__(self, x=0, y=0):

        allowed_types = {int, float}

        if type(x) not in allowed_types or type(y) not in allowed_types:
            raise TypeError('Coordinates must be numbers.')

        else:
            self.x = x
            self.y = y

    def __str__(self):
        return f' "the points name" has the points: ({self.x}, {self.y})'

    __repr__ = __str__

I would like the "the points name" to be replaced with whatever the variable name assigned to a specific object. So if I instantiated pointA=Point(1,0), I would like to be able to print pointA has the points: (1,0)

I can't seem to find anything like this online, just people having issues that are solved by redefining __str__. I tried to solve this issue by adding a .name attribute, but that made this very unwieldy (especially since I want to make other object classes that inherit Point()). I'm not entirely sure if this is possible from what I know about variable and object names in python, but after wrestling with it for a couple of days I'd figured I'd reach out for ideas.

Upvotes: 0

Views: 1268

Answers (1)

Kota Mori
Kota Mori

Reputation: 6730

Note that an object may be referred to as multiple names. It is also possible that there is no object name referring to the object.

Below is one approach that achieves your goal. It uses globals(), the dictionary that stores mappings from names to objects inside the global environment. Essentially, the __str__ method searches the object in the global listings (so it can be very slow if there are many objects) and keeps the name if matches. You could possibly use locals instead to narrow the search scope.

In the example, C is referring to the same object as A. So print(C) tells both A and C are the names.

class Point:
  def __init__(self, x=0, y=0):
    self.x = x
    self.y = y
    
  def __str__(self):
    results = []
    for name, obj in globals().items():
      if obj == self:
        results.append(f' "{name}" has the points: ({self.x}, {self.y})')
    return "; ".join(results)

A = Point()
B = Point()
print(A) 
#"A" has the points: (0, 0)
print(B)
# "B" has the points: (0, 0)

C = A
print(C)
# "A" has the points: (0, 0);  "C" has the points: (0, 0)

Upvotes: 1

Related Questions