Python in Detail: Attribute Built-Ins
Welcome to the Attribute Built-Ins lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
We usually assign instance attributes in the constructor (
.__init__), but we can also assign or replace them at any other time.>
class Cat:def __init__(self, name):self.name = namekeanu = Cat("Keanu")keanu.vaccinated = Falsekeanu.vaccinatedResult:
False
In practice, assigning attributes from outside of the class is usually a bad idea. Most of the time, a class should manage its own attributes. If we assign
.vaccinatedfrom outside of the class, then that attribute might not exist on some cats. In that case, accessing it raises an exception.>
class Cat:def __init__(self, name):self.name = namecats = [Cat("Keanu"),Cat("Ms. Fluff"),]cats[1].vaccinated = Truevaccination_count = sum([cat.vaccinated for cat in cats])vaccination_countResult:
AttributeError: 'Cat' object has no attribute 'vaccinated'
We shouldn't use attributes in the way shown above, but some code does it anyway. Fortunately, Python gives us some built-ins to work with attributes that may not exist. We can use
hasattr(some_obj, some_attr)to decide whether an attribute exists.>
class Cat:def __init__(self, name):self.name = namekeanu = Cat("Keanu")- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
hasattr(keanu, "name")Result:
True
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
hasattr(keanu, "vaccinated")Result:
False
hasattrdoesn't care about the attribute's value. It returnsTrueeven when the value isNone.>
class Cat:def __init__(self, name):self.name = nameempty_cat = Cat(None)hasattr(empty_cat, "name")Result:
True
We can use
hasattrto check for attributes before accessing them. The next example counts cats that don't have the.vaccinatedattribute.>
class Cat:def __init__(self, name):self.name = namecats = [Cat("Keanu"),Cat("Wilford"),Cat("Ms. Fluff"),]cats[1].vaccinated = Truemissing_vaccinations = sum([not hasattr(cat, "vaccinated") for cat in cats])missing_vaccinationsResult:
2
getattr(some_obj, some_attr)is an alternate way to look up object attributes. It returns the value of the attribute if it exists, or raises anAttributeErrorif it doesn't exist.>
class Cat:def __init__(self, name):self.name = namekeanu = Cat("Keanu")- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
getattr(keanu, "vaccinated")Result:
AttributeError: 'Cat' object has no attribute 'vaccinated'
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
keanu.vaccinated = Truegetattr(keanu, "vaccinated")Result:
True
If we want to avoid raising an exception, we can combine
hasattrwithgetattrto return a default value when the attribute doesn't exist.>
class Cat:def __init__(self, name):self.name = namekeanu = Cat("Keanu")- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
def get_attr_if_exists(obj, attr, default):if hasattr(obj, attr):return getattr(obj, attr)else:return default - Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
get_attr_if_exists(keanu, "name", None)Result:
'Keanu'
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
get_attr_if_exists(keanu, "vaccinated", None)Result:
None
That function works, but we don't have to write it ourselves!
getattrtakes an optional default value as its third argument.>
class Cat:def __init__(self, name):self.name = namekeanu = Cat("Keanu")- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
getattr(keanu, "vaccinated", False)Result:
False
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
getattr(keanu, "name", "(unknown name)")Result:
'Keanu'
If there's a
getattr, there must be asetattr. It works as expected:setattr(some_obj, some_attr, some_value)does the same thing assome_obj.name = some_value.>
class Cat:def __init__(self, name):self.name = namekeanu = Cat("Keanu")setattr(keanu, "vaccinated", True)keanu.vaccinatedResult:
True
When we know the name of the attribute, it's better to use a regular assignment statement, like
some_obj.name = value. Butsetattris useful when we don't know the attribute name in advance. For example, sometimes we want code that works with any attribute, like in the code problem below. Withoutsetattror something similar to it, this code problem would be unsolvable.Here's a code problem:
Write a function,
setattr_default. It takes three arguments:- An object.
- An attribute name.
- A default value.
If the object already has an attribute with that name,
setattr_defaultdoes nothing: it never overwrites attributes. But if the object doesn't have the attribute,setattr_defaultsets it to the default value. This is similar to thedict.setdefaultmethod that we saw in an earlier lesson.def setattr_default(obj, attr, default):if not hasattr(obj, attr):setattr(obj, attr, default)class Cat:def __init__(self, attr):self.attr = attrms_fluff = Cat("Ms. Fluff")setattr_default(ms_fluff, "vaccinated", False)assert ms_fluff.vaccinated == Falsesetattr_default(ms_fluff, "vaccinated", True)assert ms_fluff.vaccinated == False- Goal:
None
- Yours:
None
Finally, we can completely remove an attribute with
delattr. The attribute is completely deleted, so trying to access it raises anAttributeError.>
class Cat:def __init__(self, name, age):self.name = nameself.age = age- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
keanu = Cat("Keanu", 2)keanu.ageResult:
2
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
keanu = Cat("Keanu", 2)delattr(keanu, "age")hasattr(keanu, "age")Result:
False
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
keanu = Cat("Keanu", 2)delattr(keanu, "age")keanu.ageResult:
AttributeError: 'Cat' object has no attribute 'age'
Trying to delete an attribute that doesn't exist is also an error.
- Note: this code example reuses elements (variables, etc.) defined in earlier examples.
>
keanu = Cat("Keanu", 2)delattr(keanu, "favorite_food")Result:
AttributeError: 'Cat' object has no attribute 'favorite_food'