views:

218

answers:

4

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"
+1  A: 

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

THC4k
Right, but the fact of the matter is that I don't want the values themselves, but the name pointing to them as a string.
Akoi Meexx
The fact of the matter is that in THC4k's example, TheMagicObjet() has 2 names pointing to it, 'a' and 'b' - which one do you want?
Paul McGuire
What are the names of the objects in this list: `L = [TheMagicObjet() for x in xrange(10)]` ?
kaizer.se
+4  A: 

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
Jonathan Feinberg
Liked this answer best, since I'm already aware that there aren't true variables in Python(there really should still be a way to grab the name bound to an instance, but that's another argument for another day I guess). It's logical that it wouldn't have the name bound to the instance, so I guess for the time being I'll just require 'def_name' instead of 'def_name=None'
Akoi Meexx
There is no such thing as a "variable" by your definition. In what language can some object be bound to only one name?
Jonathan Feinberg
+2  A: 

In Python, there really isn't any such thing as a "variable". What Python really has are "names" which can have objects bound to them. 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.

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.

http://stackoverflow.com/questions/1665833/how-do-i-get-the-string-representation-of-a-variable-in-python/1665916#1665916

steveha
+3  A: 

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.

unutbu
Woah, this is so roundabout, it almost cries out "You are not supposed to do this!" :)
shylent
First it's called a hack, then roundabout,... pretty soon it'll be called an idiom :)
unutbu