Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Object-Oriented Python Advanced Objects Controlling Conversion

Keith Griffin
Keith Griffin
4,833 Points

Why am I not getting the "Thief: Keith" output?

class Character: def init(self, name = "", **kwargs): if not name: raise ValueError("Name is required") self.name = name

    for key, value in kwargs.items():
        setattr(self, key, value)

def __str__(self):
    return "{}: {}".format(self.__class__,__name__, self.name)

from thieves import Thief

Keith = Thief(name = "Keith" , sneaky = True) print(Keith.agile) print(Keith.sneaky) print(Keith.hide(7))

Hi Keith, I am honestly in the same boat as you. This series is very difficult to me. I get the sense that the author is very knowledgeable but the example is difficult for a beginner like myself in my opinion. Anyway from my understanding, self.class.name will return the name of the class from which the instance is run. and self.name will return the name assigned to the instance. I could be wrong.

So i've noticed you have a typo in your __str__ method:

def __str__(self):
    # replace comma (,) with dot (.) after __class__
    return "{}: {}".format(self.__class__.__name__, self.name)

Below I'm explaining for other commenters:

Methods that are surrounded with double underscores are mainly used for internal processes so you should only overwrite them if you know what you are doing.

In the case of __class__ it just returns the class of an object, and that object is self in this case. However, the class will be returned in a weird format. The __name__ method will take the class with the weird format and find the name it was defined with. This will give a nice output, as needed. Beware that the self.name is different from self.__name__. The first will fetch the attribute 'name' from the instance, while the __name__ will give an error. Hopefully the below examples will help:

# define simple class
 class Thief:
    # add attribute 'name'
    name = 'keith'

# create instance of Thief. Place object on variable k
k = Thief()

# print k object's name:
print(k.name)
# keith

print(k.__name__)
# AttributeError: no such attribute

print(k.__class__)
# <class '__main__.Thief'>

print(k.__class__.__name__)
# Thief

print(Thief.__name__)
# Thief

So using self.__class__.__name__ is just another way to get the name of the class in a 'loosely coupled' fashion whereas self.name just gets the attribute name

Hope this helps

1 Answer

Malte Niepel
Malte Niepel
19,212 Points

First up, there is a print statement missing in the workspace of this video. So, if you add the first print statement from my example to play.py then you should see Thief: Keith. The reason we see the name now instead of the description where the instance of the object is saved is because of the magic method str, which gives us a

nicely printable string representation of an object.

from thieves import Thief

kenneth = Thief(name="Keith", sneaky=False)
print(kenneth)
print(kenneth.sneaky)
print(kenneth.agile)
print(kenneth.hide(8))