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
David Yao
116 PointsSo what does setattr() and getattr() actually do?
In reference to the code in this thread:
I'm wondering exactly is the purpose of this part of the code:
class Contact(object):
def __init__(self, match):
for key, value in match.groupdict().items():
setattr(self, key, value)
def __str__(self):
return '\n'.join(
sorted(
["\t{}: {}".format(
key, val
) for key, val in self.__dict__.items()]))
In python documentation: it says that setattr(x, 'foobar', 123) is the same as x.foobar = 123.
So why when I substitute setattr(self, key, value) for self.key = value, the code behaves differently?
[MOD: fixed formatting -cf]
3 Answers
Chris Freeman
Treehouse Moderator 68,468 PointsAs stated in the docs, setattr() is the counterpart of getattr(). The arguments are an object, a string and an arbitrary value. The string may name an existing attribute or a new attribute. The function assigns the value to the attribute, provided the object allows it. For example, setattr(x, 'foobar', 123) is equivalent to x.foobar = 123.
setattr() can be used when the name of the attribute you wish to set is contained in a variable.. Say you have a set of keyword variables you wish to add to an object as attributes. If the name of the attribute you are trying to set is in held in a variable, then x.variable_name = "some value" won't work, but instead it will set the attribute name to literally "variable_name".
You can loop through kwargs and add them using setattr() without having to know the precise names of the keywords:
$ ipython3
Python 3.4.0 (default, Jun 19 2015, 14:20:21)
Type "copyright", "credits" or "license" for more information.
IPython 1.2.1 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: class myobj():
...: pass
...:
In [2]: kwargs = {'username': "snakeherder", 'email': "sherder@example.com"}
In [3]: for key, value in kwargs.items():
...: setattr(myobj, key, value)
...:
In [4]: myobj.username
Out[4]: 'snakeherder'
In [5]: myobj.email
Out[5]: 'sherder@example.com'
From the docs: getattr(object, name[, default]) Returns the value of the named attribute of object. name must be a string. If the string is the name of one of the object’s attributes, the result is the value of that attribute. For example, getattr(x, 'foobar') is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.
The same case as above, when the attribute name is in a variable, trying to access x.variable_name won't work.
Using getattr(x, 'foobar') instead of x.foobar has the advantage of being able to specify a default. This prevents an error when looking up an attribute that may not exist. For example,
username = getattr(user, 'username', None)
if username:
# do something
This is easier to read then having to wrap code in a try statement:
try:
username = user.username
except AttributeError:
username = None
else:
# do something
Digging specifically into your example code:
class Contact(object):
def __init__(self, match):
'''Initialize an instance using contents of 'match'
match is an 're.match()' object
match.groupdict() is a dict of successful matches
'''
# unpack each dict itemin to key:value pair
for key, value in match.groupdict().items():
# set the attribute 'key' to 'value
setattr(self, key, value)
def __str__(self):
'''Instance string method.
Returns a string of attributes in the form "key: value".
The string is constructed by generating a list of strings
where each string is in the form "key: value". The 'key',
'value'attributes are generated by unpacking the output
the '__dict__.items()' method which lists all attributes
in a (key, value) tuple. This list of strings is then sorted
then joined together using a newline character to form
a multi-line string.
'''
return '\n'.join(
sorted(
["\t{}: {}".format(
key, val
) for key, val in self.__dict__.items()]))
James Gill
Courses Plus Student 34,936 PointsI'd like to suggest adding a key bit of explanation to this course: how to display/see the values that are collected using setattr. It's not obvious at all in the Python documentation, and is easy to misunderstand. This could be as simple as "To see the values that were set via **kwargs and setattr(), use ...." and provide an example. For a beginner, setattr does some opaque magic that it's not obvious how to see inside of.
Chris Freeman
Treehouse Moderator 68,468 PointsAFAIK there isn't a mechanical to tell how an attribute was set. Using setattr() vs self.variable = value or whether it was done during instantiation within the __init__ method vs post-initialization through direct attribute assignment.
To see all the all object attributes use dir(object)
To see the attributes and their values use object.__dict__
Was there something else you had in mind?
Name:GoogleSearch orJonathan Sum
5,039 PointsChris Freeman ,Don't you feel our python teacher ,which Mr Love, doesn't really explain it in more detail. He just explain some "key part" within few second ,such as setattr. It is just like he writes his code and doesn't really explain everything.
Chris Freeman
Treehouse Moderator 68,468 PointsIn support of Kenneth Love, choosing how much detail to provide is a delicate balance. Good books on Python span over 1600 pages. Many times Kenneth has to settle for a basic introduction of a concept or a simple mention. The Community forum and Teacher's notes beneath the videos are a great way to dig deeper into topics. Often searching the existing posts may provide the direction needed to go as far as you wish into details.
David Yao
116 PointsDavid Yao
116 PointsThis doesn't wholly address my question in regards to that specific example, but it is enough for me to kind of put the pieces together and understand it a bit better now. Thank you. Now, in addition in regards to piece of code I past above:
self.__dict__.itemsDoes this essentially refer to the object's attributes? If so that would make sense why
setattr()was used in conjunction with the dict magic method here. If you can add any more info regarding, this that would be extremely helpfulChris Freeman
Treehouse Moderator 68,468 PointsChris Freeman
Treehouse Moderator 68,468 PointsAnswer updated to include your code question.
self.__dict__refers to an object's namespace, and all the references within it, in a dict format. Which is to say: all it's attributes..items()is the regulardictmethod to return tuples of (key, value) pairs for all of the items in a dictionary.Combined together,
self.__dict__.items()returns all of an objects attributes in (key, value) pairs.I'd be happy to elaborate further if needed.