Vin Breau
Vin Breau

Reputation: 279

Better understanding of __str__ usage

I'm trying to better understand the proper usage of the __str__ function. Let's say I have a very simple class called Character for use in a game that looks like this:

class Character(object):
""" A game character. """
def __init__(self, name):
    self.name = name
    self.poisoned = False
    self.strength = random.randrange(10, 20)
    self.max_strength = self.strength
    self.dexterity = random.randrange(10, 20)
    self.max_dexterity = self.dexterity
    self.hit_points = 100
    self.spell_points = 100
    self.weapon = []
    self.spell = []
    self.items = []
    self.aura = []
    self.xp = 0

Prior to learning about the __str__ function, I would have defined a method of the class called print_stats(self) that would print the character stats via Character.print_stats(). After learning about __str__ though it seemed like this was a function for defining and displaying the statistics of an object, similar to what I would do with print_stats(self)... but in playing with it and learning that the returned value must be a string and not contain integers, it appears my assumption is wrong.

So now my question is what are some examples of good usage of the __str__? Would the example I provide benefit from using that function?

Upvotes: 5

Views: 5317

Answers (5)

mgilson
mgilson

Reputation: 310237

__str__ exists so that you can get a string representation of your object. Note that the builtin print function/statement calls str implicitly:

print 1

is exactly the same as:

print str(1)

which is the same as:

print (1).__str__()

because print calls __str__ implicitly.


Now to your class -- The most natural thing to do is if you would have written:

print self.foo,self.bar,self.baz

You could define __str__ as:

def __str__(self):
    return " ".join(str(x) for x in (self.foo,self.bar,self.baz))

Now to print your character's stats, you'd just do:

print character  #same as `print str(character)` :)

Usually this is a little limited, so there exists string formatting via .format (or old "sprintf" style formatting using the % operator).

def __str__(self):
    return "my {foo} went to the {baz} to buy a {bar}".format(foo=self.foo,
                                                              baz=self.baz,
                                                              bar=self.bar)

Upvotes: 3

Silas Ray
Silas Ray

Reputation: 26160

In basic use cases, __str__() and a method like print_stats() can pretty safely be interchanged. However, especially for something like a character in a game, you might want to go with print_stats(), as you won't be able to refactor __str__() to do something like print the data to the screen (in the context of a graphical desktop or web application), or to take arguments, which could prove useful for things like this.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1124858

Printing stats is a fine use of __str__(). Simply use string formatting to return a single string value:

def __str__(self):
    return ('Name: {name}\n'
        'Poisoned: {poisoned}\n'
        # etc.
    ).format(**self.__dict__)

Upvotes: 9

Thomas
Thomas

Reputation: 182073

The return value has to be a string, but it can be any string, including one that contains the string representation of integers. A simple example:

def __str__(self):
  return "%s (strength: %i)" % (self.name, self.strength)

This might return something like "Arthur (strength: 42)".

Upvotes: 1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 799450

def __str__(self):
  return 'Name: %s, Hit points: %d' % (self.name, self.hit_points)

Upvotes: 1

Related Questions