Getting an instance name inside class __init__() [duplicate]

Posted on

Question :

Getting an instance name inside class __init__() [duplicate]

While building a new class object in python, I want to be able to create a default value based on the instance name of the class without passing in an extra argument. How can I accomplish this? Here’s the basic pseudo-code I’m trying for:

class SomeObject():
    defined_name = u""

    def __init__(self, def_name=None):
        if def_name == None:
            def_name = u"%s" % (<INSTANCE NAME>)
        self.defined_name = def_name

ThisObject = SomeObject()
print ThisObject.defined_name   # Should print "ThisObject"

Answer #1:

Instances don’t have names. By the time the global name ThisObject gets bound to the instance created by evaluating the SomeObject constructor, the constructor has finished running.

If you want an object to have a name, just pass the name along in the constructor.

def __init__(self, name):
    self.name = name
Answered By: Jonathan Feinberg

Answer #2:

Well, there is almost a way to do it:

#!/usr/bin/env python
import traceback
class SomeObject():
    def __init__(self, def_name=None):
        if def_name == None:
            (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
            def_name = text[:text.find('=')].strip()
        self.defined_name = def_name

ThisObject = SomeObject()
print ThisObject.defined_name 
# ThisObject

The traceback module allows you to peek at the code used to call SomeObject().
With a little string wrangling, text[:text.find('=')].strip() you can
guess what the def_name should be.

However, this hack is brittle. For example, this doesn’t work so well:

ThisObject,ThatObject = SomeObject(),SomeObject()
print ThisObject.defined_name
# ThisObject,ThatObject
print ThatObject.defined_name 
# ThisObject,ThatObject

So if you were to use this hack, you have to bear in mind that you must call SomeObject()
using simple python statement:

ThisObject = SomeObject()

By the way, as a further example of using traceback, if you define

def pv(var):
    # stack is a list of 4-tuples: (filename, line number, function name, text)
    # see http://docs.python.org/library/traceback.html#module-traceback
    #
    (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
    # ('x_traceback.py', 18, 'f', 'print_var(y)')
    print('%s: %s'%(text[text.find('(')+1:-1],var))

then you can call

x=3.14
pv(x)
# x: 3.14

to print both the variable name and its value.

Answered By: unutbu

Answer #3:

You can create a method inside your class that check all variables in the current frame and use hash() to look for the self variable.

The solution proposed here will return all the variables pointing to the instance object.

In the class below, isinstance() is used to avoid problems when applying hash(), since some objects like a numpy.array or a list, for example, are unhashable.

import inspect
class A(object):
    def get_my_name(self):
        ans = []
        frame = inspect.currentframe().f_back
        tmp = dict(frame.f_globals.items() + frame.f_locals.items())
        for k, var in tmp.items():
            if isinstance(var, self.__class__):
                if hash(self) == hash(var):
                    ans.append(k)
        return ans

The following test has been done:

def test():
    a = A()
    b = a
    c = b
    print c.get_my_name()

The result is:

test()
#['a', 'c', 'b']

Answer #4:

This cannot work, just imagine this: a = b = TheMagicObjet(). Names have no effect on Values, they just point to them.

Answered By: Jochen Ritzel

Answer #5:

One horrible, horrible way to accomplish this is to reverse the responsibilities:

class SomeObject():
    def __init__(self, def_name):
        self.defined_name = def_name
        globals()[def_name] = self

SomeObject("ThisObject")
print ThisObject.defined_name

If you wanted to support something other than global scope, you’d have to do something even more awful.

Answered By: Russell Borogove

Answer #6:

In Python, all data is stored in objects. Additionally, a name can be bound with an object, after which that name can be used to look up that object.

It makes no difference to the object what names, if any, it might be bound to. It might be bound to dozens of different names, or none. Also, Python does not have any “back links” that point from an object to a name.

Consider this example:

foo = 1
bar = foo
baz = foo

Now, suppose you have the integer object with value 1, and you want to work backwards and find its name. What would you print? Three different names have that object bound to them, and all are equally valid.

print(bar is foo) # prints True
print(baz is foo) # prints True

In Python, a name is a way to access an object, so there is no way to work with names directly. You could search through various name spaces until you find a name that is bound with the object of interest, but I don’t recommend this.

How do I get the string representation of a variable in python?

There is a famous presentation called “Code Like a Pythonista” that summarizes this situation as “Other languages have ‘variables'” and “Python has ‘names'”

http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables

Answered By: steveha

Answer #7:

I think that names matters if they are the pointers to any object..
no matters if:

foo = 1
bar = foo

I know that foo points to 1 and bar points to the same value 1 into the same memory space.
but supose that I want to create a class with a function that adds a object to it.

Class Bag(object):
   def __init__(self):
       some code here...
   def addItem(self,item):
       self.__dict__[somewaytogetItemName] = item

So, when I instantiate the class bag like below:

newObj1 = Bag()
newObj2 = Bag()
newObj1.addItem(newObj2)I can do this to get an attribute of newObj1:
newObj1.newObj2
Answered By: andrexterz

Answer #8:

If you want an unique instance name for a class, try __repr__() or id(self)

class Some:
    def __init__(self):
        print(self.__repr__())  # = hex(id(self))
        print(id(self))

It will print the memory address of the instance, which is unique.

Answered By: Guillaume Lebreton

Leave a Reply

Your email address will not be published.