0

I have this code, with the desired output "The value is Bar and the name is b."

class myClass:
    def __init__(self, value):
        self.value = value

b = myClass("Bar")

def foo(var):
    true_name = str(var)
    print("The value is %s and the name is %s" % (var.value, true_name))

foo(b)

However, this prints The value is Bar and the name is <__main__.myClass object at 0x000000187E979550>, which is less useful to me.

Now, I know the problems with trying to get the true name of a variable in Python. However, I don't need to do any fancy introspection; I just want to convert the actual letters typed between the parentheses of foo( ) and print that.

To me, this sounds like a simple thing that would be useful in debugging and examining my code, so I can tell exactly what object did a thing. Am I making a fundamental error in my assumptions, and this is a terrible idea?

Community
  • 1
  • 1
Somatic
  • 193
  • 7
  • There's no easy way to do what you want. Variable names are not data, you should not need to know them. If you want your objects to have names, make "name" an attribute or something. – Blckknght Jan 17 '16 at 00:02
  • 1
    You never mentioned how you're calling `foo`. What is `var` in that particular call? – TigerhawkT3 Jan 17 '16 at 00:05
  • @TigerhawkT3: fixed! `var` is `b`, so `foo(b)` – Somatic Jan 17 '16 at 00:07
  • Are you trying to get the output, then, to be `The value is Bar and the name is b`? – TigerhawkT3 Jan 17 '16 at 00:08
  • @Blckknght: It seems to me that variable names like `Player` or `Inventory` would be more convenient to work with than `<__main__.myClass object at 0x0000005D8BB69550>`. While objects generally do have a `.name` attribute, having an easy-to-remember variable name makes my life easier when I'm debugging. – Somatic Jan 17 '16 at 00:09
  • 1
    @TigerhawkT3: Yes. I put the desired output at the top of the question, in case you missed it. – Somatic Jan 17 '16 at 00:10
  • 1
    If you want a human friendly way to output a value, write a `__str__` or `__repr__` method for its class. Don't confuse an object with its variable name, they're not the same thing. An object may have one name, but it may also have none (as in `foo(MyClass("Bar"))`) or more than one, as in `a = b = MyClass("Bar")`). – Blckknght Jan 17 '16 at 00:35

1 Answers1

1

The easiest way to do this is by simply passing the desired "true name" in along with the actual reference:

def foo(var):
    var, true_name = var
    print("The value is %s and the name is %s" % (var.value, true_name))

foo((b, 'b'))

Of course, this does not guarantee that true_name matches the passed reference name, but it's a much shorter and clearer way of not guaranteeing it than possibly-fragile hacks that may or may not work.

If you just want something more readable than <__main__.myClass object at 0x000000187E979550>, you should define a __str__ method in your class and then simply print the instance. You won't even need a separate foo function anymore. You can also define a __repr__ method for the precise representation (which is the string that you would enter into the interpreter to produce an equivalent object):

class myClass:
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return 'myClass with a value of {}'.format(self.value)
    def __repr__(self):
        return "myClass({})".format(repr(self.value))

Result:

>>> b = myClass("Bar")
>>> print(b)
myClass with a value of Bar
>>> b
myClass('Bar')
Community
  • 1
  • 1
TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97