# Python AttributeError: 'tuple' object has no attribute

AttributeError: 'tuple' object has no attribute

Learn Data Science with



This error occurs when attempting to access the values of a tuple incorrectly.

Functions that return multiple variables will output the results in a tuple, so we cannot use dot-access to retrieve the values.

## Example 1

For example, let's create a simple function that returns two values:

def create_tuple():
val_1 = 5
val_2 = 10
return val_1, val_2

Learn Data Science with



If we call the function and attempt to access the tuple's elements with dot-access, i.e. as an attribute, we will see the error:

val_1 = create_tuple().val_1

Learn Data Science with


Out:
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-2f0480fa9e27> in <module>
----> 1 val_1 = create_tuple().val_1

AttributeError: 'tuple' object has no attribute 'val_1'

Learn Data Science with



As we can see from the error message, the attribute val_1 does not exists for the tuple.

### What's an attribute?

What does the error mean by attribute? An example of an attribute would be class variables. For example, say we have a simple Tree class:

class Tree:
def __init__(self, kind):
self.kind = kind  # kind is an attribute

new_tree = Tree('pine')

print(new_tree.kind)  # kind is dot-accessible

Learn Data Science with


Out:
pine

Learn Data Science with



We can see in this example that kind is an attribute of the Tree class, and we can access it with a dot.

In contrast, to correctly access the tuple's value, we need to use an index:

result = create_tuple()
val_1 = result[0]
val_2 = result[1]

print(val_1, val_2)

Learn Data Science with


Out:
5 10

Learn Data Science with



Or, alternatively, by using tuple unpacking:

val_1, val_2 = create_tuple()
print(val_1, val_2)

Learn Data Science with


Out:
5 10

Learn Data Science with



Often this error occurs when using an external library where you didn't know a function returned a tuple. We'll describe examples of this below.

If you create your own function and want your return value to have dot-access, you can use a namedtuple or a class.

## Cause 1: Treating Tuple Values as Named Attributes

As mentioned previously, any function which returns multiple values will output them as a tuple-type by default, which cannot be dot-accessed.

To demonstrate this, let's write a small function called perform_calculations that takes two numbers and outputs values for their sum, product, and quotient:

def perform_calculations(a, b):
mult = a * b
div = a / b

perform_calculations(4, 2)

Learn Data Science with


Out:
(6, 8, 2.0)

Learn Data Science with



Python packs function outputs into a tuple, as shown by the parentheses containing the sequence. We know that one of the function's outputs is the product of the two numbers, so let's try and access that:

results = perform_calculations(4, 2)

print(results.mult)

Learn Data Science with


Out:
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-17-475c1deeb55f> in <module>
1 results = perform_calculations(4, 2)
2
----> 3 print(results.mult)

AttributeError: 'tuple' object has no attribute 'mult'

Learn Data Science with



Our results variable is a tuple, so we can't access specific values in the manner shown above.

### Solution

One way of assigning tuple values to variables is to unpack the tuple:

results = perform_calculations(4, 2)

print(mult)

Learn Data Science with


Out:
8

Learn Data Science with



The solution shows that tuple values need to be unpacked and assigned to variables before directly accessing them. Note that we can unpack our function output straight into add, mult, and div, without having to use results as a go-between:

add, mult, div = perform_calculations(5, 7)

print(add)

Learn Data Science with


Out:
12

Learn Data Science with



This article contains a few more examples of unpacking functions and lists.

We could also use indices to reference specific tuple values:

mult = perform_calculations(5, 7)[1]

print(mult)

Learn Data Science with


Out:
35

Learn Data Science with



Optionally, if you would like to have dot-access to elements, you can use a namedtuple like so:

from collections import namedtuple

Calculations = namedtuple('Calculations', ['add', 'mult', 'div'])

def perform_calculations(a, b):
c = Calculations(
mult=a * b,
div=a / b
)
return c

r = perform_calculations(5, 7)

print(r.mult)

Learn Data Science with


Out:
35

Learn Data Science with



Similarly, this could be accomplished by using a class.

We've been using a function we created in these examples, but this error often shows up when using third-party libraries, like in the following section.

## Cause 2: Not Unpacking iterrows()

This error is seen frequently while using the pandas iterrows() DataFrame method.

Let's take another look at the Iris dataset used in the introduction, iterating through the first three rows of the dataframe using iterrows().

Initially, you might assume iterrows() would return a dot-accessible DataFrame row. Let's try:

# import the dataset and limit to three rows

for row in df.iterrows():
print(row.sepal_length)

Learn Data Science with


Out:
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-27-e52734937d9f> in <module>
3
4 for row in df.iterrows():
----> 5     print(row.sepal_length)

AttributeError: 'tuple' object has no attribute 'sepal_length'

Learn Data Science with



We can see row is a tuple, so let's print the rows to examine how to unpack them:

for row in df.iterrows():
print(row, '\n')

Learn Data Science with


Out:
(0, sepal_length       5.1
sepal_width        3.5
petal_length       1.4
petal_width        0.2
species         setosa
Name: 0, dtype: object)

(1, sepal_length       4.9
sepal_width          3
petal_length       1.4
petal_width        0.2
species         setosa
Name: 1, dtype: object)

(2, sepal_length       4.7
sepal_width        3.2
petal_length       1.3
petal_width        0.2
species         setosa
Name: 2, dtype: object)

Learn Data Science with



We can see iterrows() generates a tuple that looks like (index, row contents).

### Solution

As a result, trying to access specific row features without unpacking them first will throw an error. We need to unpack each row like so:

for i, row in df.iterrows():
print(f'index: {i}, sepal_length: {row.sepal_length}')

Learn Data Science with


Out:
index: 0, sepal_length: 5.1
index: 1, sepal_length: 4.9
index: 2, sepal_length: 4.7

Learn Data Science with



Alternatively, you could specify that you're only interested in the second value of the tuple using indices, which would prevent you from needing to unpack the tuple.

For example, we could index the iterrows() output as follows:

for row_tuple in df.iterrows():
# [1] is used to select the second value in the tuple
print(row_tuple[1].sepal_length)

Learn Data Science with


Out:
5.1
4.9
4.7

Learn Data Science with



The two solutions effectively do the same thing, but developers use the first approach more commonly as it is slightly more readable. Furthermore, you can throw away the index with an underscore if you don't need it:

for _, row in df.iterrows():
print(row.sepal_length)

Learn Data Science with


Out:
5.1
4.9
4.7

Learn Data Science with



The underscore conveys to readers of your code that you intend not to use the index value.

## Summary

The error AttributeError: 'tuple' object has no attribute is caused when treating the values within a tuple as named attributes. The error also occurs very frequently when using iterrows(), hence the big focus on avoiding the error in that case.

It's important to remember that any functions returning multiple values will automatically store the outputs in a tuple, which could also potentially cause this error to come up. Luckily, the error is pretty easy to avoid in most cases by unpacking the tuple first, assigning the values to variables. Alternatively, using indices to index a tuple is also a viable solution.

### Meet the Authors

Alfie graduated with a Master's degree in Mechanical Engineering from University College London. He's currently working as Data Scientist at Square Enix. Find him on LinkedIn.