10

I understand that you should never use variable names within the program, but I am using is strictly for debug purposes and would like to convey the name of the variable to the user for readability.

I have a file like this:

class MyClass(object):
    def __init__(self):
        pass

    def foo(msg=""):
        debug("Called from the %s instance.") #quazi-print function that only prints when a DEBUG variable is True.
        print(msg)

m = MyClass()
m.foo("Test")

I would like to retrieve the m instance variable name from within the class itself. Though this is merely an example file, I am using it to convey to the user that a raw socket has been created at a certain attribute within an instance variable, and would like to show where it is (i.e. New socket at m.socket)

Is this feasible with Python?

martineau
  • 119,623
  • 25
  • 170
  • 301
Goodies
  • 4,439
  • 3
  • 31
  • 57
  • Even for debug purposes, it will be confusing if the user has multiple references to the object. Better to have an explicit name for it (perhaps specified by the user when turning on debugging for a particular object). – BrenBarn Aug 23 '15 at 05:17
  • 3
    It's somewhat feasible, but you have to search all the namespaces that `m` might have been defined in, to look for a binding of it. – Patrick Maupin Aug 23 '15 at 05:17
  • what is the name of instance in `print(MyClass())` – Daniel Aug 23 '15 at 11:02
  • 2
    This is pretty late but I just ran across this from Google: this is actually _not_ a duplicate since the answer referred to above returns the name of the _class_ (here `"MyClass"`). What we're looking for here is the name of the _variable_ referring to a specific instance of a class (here: `'m'`). Anyone able to remove the "duplicate" marker? Anyone know the answer (haven't found it yet). – Jonas Sep 06 '17 at 12:41

3 Answers3

7

You could look in the instance's globals dictionary and find the item that has its self as a value.

class Foo(object):
    def bar(self):
        return [k for k,v in globals().items() if v is self]
    def bah(self):
        d = {v:k for k,v in globals().items()}
        return d[self]

f = Foo()
g = Foo()

print f.bar(), g.bar()
print f.bah(), g.bah()

>>> 
['f'] ['g']
f g
>>> 
wwii
  • 23,232
  • 7
  • 37
  • 77
  • 2
    So, this won't work if the variable is not global, correct? Would there be any way of avoiding that? Will this raise an error if it is not global? – Goodies Aug 23 '15 at 05:26
  • @Goodies, The instance name should always be in its outer scope which is what ```globals()``` produces. -At least I think, perhaps someone will chime in. – wwii Aug 23 '15 at 05:29
  • 3
    @Goodies Hmmm, if you create the instance in a function, it isn't in ```globals``` – wwii Aug 23 '15 at 05:37
4

Here's a really silly way to do it, if you don't mind the program exiting at that point: add this line to foo():

print undefined_variable

And when you get there, you get a stack trace like this:

Traceback (most recent call last): File "test.py", line 15, in <module> m.foo("Test") File "test.py", line 11, in foo print undefined_variable NameError: global name 'undefined_variable' is not defined

...which tells you that the name of the variable that called it was 'm' :)

(You might be able to do something like this using the traceback module, without killing the program. I've tried a few ways, but haven't managed to get it to include the m.foo() line in the output.)

Felix
  • 433
  • 4
  • 8
  • 2
    I'm not up-voting because it's useful; I'm up-voting because it's clever. – Goodies Aug 23 '15 at 06:09
  • you should write `raise Exception()` instead of the print. – Daniel Aug 23 '15 at 11:00
  • Yeah, I tried a `try ... raise ... except: print (various things from the traceback module)`, but I couldn't find any backtrace objects that included the `m.foo()` line. Mind you, I didn't try very hard -- there may well be one :) – Felix Aug 23 '15 at 17:28
-2

Yes. To get all members of a class, you can use the built in keyword "dir". It will list all the methods and variables in your class. If you use proper naming conversions, you should be able to tell which names are variables and which are methods. Dir returns a list of strings.

class Man():
    def __init__(self):
        self.name = "Bob"
        self.color = "White"
m = Man()
    print dir(m)

This will print out:

['doc', 'init', 'module', 'color', 'name']

Are color and name not the instances variable names of this class?

bud
  • 485
  • 6
  • 22