qwwqwwq
qwwqwwq

Reputation: 7309

Introspection to Determine Originally Bound Variable of an Instance

Is there anyway to determine the variable to which an instance was originally bound?

With a function we can do this:

def f():
    pass
print f.__name__
>> f
g = f
print g.__name__
>> f

What I want is:

class c:
    pass

mything = c()
print mything.__name__
>> mything

The reason I want this is for more intuitive logging/error messages for an API I'm writing.. I.e. it would be nice to have

print mything
>> instance of c originally bound to 'mything'

Instead of the usual:

print mything
>> <__main__.c instance at 0x7fb7994b25a8>

And (I think?) would be nice to not make people explicitly supply a __name__ attribute in __init__ all the time..

Is this possible? advisable?

Upvotes: 1

Views: 79

Answers (3)

qwwqwwq
qwwqwwq

Reputation: 7309

This is a hackish way I found to do this, for posterity's sake:

def find_global_var_name( target_obj ):
    for name, obj in globals().iteritems():
        if id(obj) == id(target_object):
            return name

Assumes a globally defined variable, which is in line with my usecase, I'm not going to use it though since sentiment seems overwhelmingly negative about this whole thing..

Upvotes: 0

user1129665
user1129665

Reputation:

You want for example something like this (the function example confuses me):

class Foo(object):
    # something here
    pass

a = Foo()
b = Foo()
c = Foo()

print a.__name # a
print b.__name # b
print c.__name # c

? if so, no that is not possible. This information cannot be carried within the instance. Many Instance can point to the same instance like here:

>>> class Foo(object):
...     pass
...
>>>
>>> a = Foo()
>>> b = a
>>> c = b
>>>
>>> print a
<__main__.Foo object at 0x01765B70>
>>> print b
<__main__.Foo object at 0x01765B70>
>>> print c
<__main__.Foo object at 0x01765B70>
>>>

They all the same, which instance name to carry, go the point? another issue is here:

class Foo(object):
    pass

a = [Foo(), Foo(), Foo()]

The only possible solution I can think of is to tag the instance on initialization:

>>> class Foo(object):
...     def __init__(self, name):
...         self.__name__ = name
...
>>> a = Foo('a')
>>> b = Foo('b')
>>> c = Foo('c')
>>>
>>> a.__name__
'a'
>>> b.__name__
'b'
>>> c.__name__
'c'
>>>

Upvotes: 2

user2357112
user2357112

Reputation: 280485

There's no way, and if there were a way, it wouldn't be as useful as you think. When you define a function, you give it a name, and most references to the function will use the name. On the other hand, other objects tend not to be tied as tightly to a single name.

def factory_function(parameter):
    obj = Thing(parameter)
    obj.preprocess_somehow()
    return obj

game_window = factory_function(parameter)
menu_screen = factory_function(parameter)
subscreens = [factory_function(parameter) for parameter in params]

The most interesting names for the objects here are game_window, menu_screen, and subscreens, but the "first variable" game_window and menu_screen are bound to is either obj or something earlier, perhaps self or some C-level variable in an allocator function. The items of subscreens don't even have useful individual names.

Upvotes: 1

Related Questions