avatarDeck451

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

6220

Abstract

class="hljs-string">f"element index <span class="hljs-subst">{index}</span> has the value of: <span class="hljs-subst">{element}</span>"</span>)</pre></div><div id="c5d1"><pre><span class="hljs-variable">for</span> <span class="hljs-variable">element</span> <span class="hljs-variable"><span class="hljs-keyword">in</span></span> <span class="hljs-variable">my_tuple</span>: <span class="hljs-function"><span class="hljs-title">print</span>(<span class="hljs-variable">f</span><span class="hljs-string">"{element}"</span>)</span></pre></div><div id="d9f0"><pre><span class="hljs-attribute">Output</span>: <span class="hljs-attribute">element</span> index <span class="hljs-number">0</span> has the value of: <span class="hljs-number">1</span> <span class="hljs-attribute">element</span> index <span class="hljs-number">1</span> has the value of: <span class="hljs-number">2</span> <span class="hljs-attribute">element</span> index <span class="hljs-number">2</span> has the value of: <span class="hljs-number">3</span> <span class="hljs-attribute">1</span> <span class="hljs-attribute">2</span> <span class="hljs-attribute">3</span></pre></div><h2 id="203b">Tuple shallow copying</h2><p id="e274">Because a tuple is immutable, there is absolutely no reason for Python to create another copy of it. This is why the shallow copying mechanisms yield different results in the case of tuples as opposed to lists. More specifically, we’ll see that the copying mechanisms in the case of tuples will lead to multiple variables pointing to the same tuple object in memory.</p><div id="d16a"><pre><span class="hljs-comment"># shallow copy via slicing</span></pre></div><div id="4029"><pre><span class="hljs-attr">my_tuple</span> = (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-attr">my_second_tuple</span> = my_tuple[:]</pre></div><div id="161e"><pre><span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-built_in">id</span>(my_tuple)}</span>: <span class="hljs-subst">{my_tuple}</span>"</span>) <span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-built_in">id</span>(my_second_tuple)}</span>: <span class="hljs-subst">{my_second_tuple}</span>"</span>)</pre></div><div id="3adf"><pre># shallow <span class="hljs-keyword">copy</span> - <span class="hljs-keyword">using</span> <span class="hljs-keyword">tuple</span>()</pre></div><div id="0e1f"><pre><span class="hljs-attribute">my_tuple</span> = (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>) <span class="hljs-attribute">my_second_tuple</span> = tuple(my_tuple)</pre></div><div id="6d0e"><pre><span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-built_in">id</span>(my_tuple)}</span>: <span class="hljs-subst">{my_tuple}</span>"</span>) <span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-built_in">id</span>(my_second_tuple)}</span>: <span class="hljs-subst">{my_second_tuple}</span>"</span>)</pre></div><div id="6d6e"><pre># shallow <span class="hljs-keyword">copy</span> - <span class="hljs-keyword">using</span> <span class="hljs-keyword">copy</span>.<span class="hljs-keyword">copy</span>() <span class="hljs-keyword">import</span> <span class="hljs-keyword">copy</span></pre></div><div id="adb0"><pre><span class="hljs-attribute">my_tuple</span> = (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>) <span class="hljs-attribute">my_second_tuple</span> = copy.copy(my_tuple)</pre></div><div id="f313"><pre><span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-built_in">id</span>(my_tuple)}</span>: <span class="hljs-subst">{my_tuple}</span>"</span>) <span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-built_in">id</span>(my_second_tuple)}</span>: <span class="hljs-subst">{my_second_tuple}</span>"</span>)</pre></div><div id="71cf"><pre><span class="hljs-attribute">Output</span>: <span class="hljs-attribute">139801960279616</span>: (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-attribute">139801960279616</span>: (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-attribute">139801960767552</span>: (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>) <span class="hljs-attribute">139801960767552</span>: (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>) <span class="hljs-attribute">140188066853728</span>: (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>) <span class="hljs-attribute">140188066853728</span>: (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>)</pre></div><p id="45c7">All three approaches yield similar results, as both variables point to the very same tuple object in memory. Altering one of them by concatenating it with another tuple will change that tuple’s id, since tuples are immutable and altering them is actually Python creating a new tuple having the new value(s).</p><h2 id="259e">Tuple deep copying</h2><p id="bc52">As previously stated in <a href="https://readmedium.com/python-up-your-code-lists-part-ii-shallow-copy-vs-deep-copy-795001855101">this</a> article, deep copying is really just a recursive shallow copying process:</p><div id="dbbf"><pre><span clas

Options

s="hljs-keyword">import</span> copy</pre></div><div id="3f62"><pre><span class="hljs-attr">my_tuple</span> = ([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]) <span class="hljs-attr">my_second_tuple</span> = copy.deepcopy(my_tuple)</pre></div><div id="5c78"><pre><span class="hljs-comment"># can't alter tuple elements like my_tuple[0]</span> <span class="hljs-comment"># but can alter my_tuple[0][1], since my_tuple[0] is a list</span> <span class="hljs-attribute">my_tuple</span>[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>] = <span class="hljs-number">7</span></pre></div><div id="4c36"><pre><span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-built_in">id</span>(my_tuple)}</span>: <span class="hljs-subst">{my_tuple}</span>"</span>) <span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-built_in">id</span>(my_second_tuple)}</span>: <span class="hljs-subst">{my_second_tuple}</span>"</span>)</pre></div><div id="f0c9"><pre>Output: 140557489187968: (<span class="hljs-comment">[1, 7, 3]</span>, <span class="hljs-comment">[4, 5, 6]</span>) 140557489324928: (<span class="hljs-comment">[1, 2, 3]</span>, <span class="hljs-comment">[4, 5, 6]</span>)</pre></div><p id="cb1a">Separate entities is what we were going for and <code>copy.deepcopy()</code> accomplishes this, so that the change we made in one of the lists will not reflect in the second tuple object.</p><h2 id="0592">Count occurrences of element in a tuple</h2><p id="d61b">Since tuples are ordered, they do allow, like lists, duplicate elements. We can count the occurrences of one given element in a given tuple like this:</p><div id="30cd"><pre><span class="hljs-attribute">my_tuple</span> = (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">1</span>) <span class="hljs-attribute">occurrences</span> = my_tuple.count(<span class="hljs-number">1</span>) <span class="hljs-attribute">print</span>(occurrences)</pre></div><div id="0fd2"><pre><span class="hljs-symbol">Output:</span> <span class="hljs-number">2</span></pre></div><p id="01bd">Should we try to count the occurrences of, say, 5, which is an element that doesn’t exist in the given tuple, we’d simply get 0.</p><h2 id="d20e">Get element position in the tuple</h2><p id="52a4">Again, because tuples are ordered, we sometimes may want to get a certain element’s position (index). Calling the <code>index()</code> method on a non-existent element will get us a <code>ValueError</code> thrown:</p><div id="f75b"><pre><span class="hljs-attribute">my_tuple</span> = (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-attribute">position</span> = my_tuple.index(<span class="hljs-number">1</span>) <span class="hljs-attribute">print</span>(position) <span class="hljs-attribute">position_error</span> = my_tuple.index(<span class="hljs-number">4</span>)</pre></div><div id="c599"><pre><span class="hljs-keyword">Output</span>: 0 Traceback (most recent <span class="hljs-keyword">call</span> last): ... position_error = my_tuple.<span class="hljs-meta">index</span>(4) ValueError: tuple.<span class="hljs-meta">index</span>(<span class="hljs-keyword">x</span>): <span class="hljs-keyword">x</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> tuple</pre></div><h2 id="9311">Tuple concatenation</h2><p id="f2db">Similar to <code>list.extend()</code> — check <a href="https://readmedium.com/python-up-your-code-lists-part-iii-5ae633f8ec4e">this</a> article — we sometimes may find ourselves in the situation where we’d want to extend a given tuple:</p><div id="be6a"><pre>my_tuple = (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-built_in">id</span>(my_tuple)}</span> <span class="hljs-subst">{my_tuple}</span>"</span>) my_tuple += (<span class="hljs-number">4</span>,) <span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{<span class="hljs-built_in">id</span>(my_tuple)}</span> <span class="hljs-subst">{my_tuple}</span>"</span>)</pre></div><div id="05a1"><pre><span class="hljs-attribute">Output</span>: <span class="hljs-attribute">139871299530560</span> (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-attribute">139871299526064</span> (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>)</pre></div><p id="2d6f">But, as you’ve probably already figured it out, altering a tuple — an immutable object — makes Python create a new tuple object, that will contain the newly modified value(s).</p><p id="9cfb">It’s always a good idea to keep track of what’s going on under the hood, as things will become even clearer and we’ll be able to make more sense of everything. It’s just a question of effort on our part. And with the rewards far outweighing the costs, there’s but one direction: forward.</p><p id="a0fd">Having wrapped up what should seem like a very brief crash course on Python tuples, I invite you to start digging over the Net for more information on and best practices in using tuples in Python projects! Stay safe and happy coding!</p><p id="7677"><i>More content at <a href="https://plainenglish.io/"><b>PlainEnglish.io</b></a>. Sign up for our <a href="http://newsletter.plainenglish.io/"><b>free weekly newsletter</b></a>. Follow us on <a href="https://twitter.com/inPlainEngHQ"><b>Twitter</b></a> and <a href="https://www.linkedin.com/company/inplainenglish/"><b>LinkedIn</b></a>. Join our <a href="https://discord.gg/GtDtUAvyhW"><b>community Discord</b></a>.</i></p></article></body>

Up Your Coding Skills with Python: Tuples

Learn about Tuples and the operations that you can perform on tuples in Python.

Photo by fabio on Unsplash

Tuples in Python are collections of objects, quite similar to lists in that they are both ordered (each element has its very own precisely determined position in the tuple) and, as a direct consequence, can both hold duplicate values. The resemblances stop here, as tuples are immutable, as opposed to the lists, which are, as we’ve come to know, mutable. This means that we can’t change its contents/value without Python building a completely different tuple containing the new contents/value.

Creating a new tuple

# a new empty tuple
my_empty_tuple = ()
# print it out
print(my_empty_tuple)
# a new empty tuple
my_second_empty_tuple = tuple()
# print it out
print(my_second_empty_tuple)
Output:
()
()

Creating a new, empty tuple can be done either by using(), or via my_tuple = tuple().

There is a syntax quirk we need to be careful about when dealing with tuples:

# create a tuple containing one single element - the wrong way
my_tuple = ("Test")
# print the object's type and contents
print(f"{type(my_tuple)}: {my_tuple}")
# create a tuple containing one single element - the right way
my_tuple = ("Test",)
# print the object's type and contents
print(f"{type(my_tuple)}: {my_tuple}")
Output:
<class 'str'>: Test
<class 'tuple'>: ('Test',)

The difference a simple comma can make in this case can be a very big one. When we need to have a one-element tuple, it’s imperative that we pay close attention to this little detail that can otherwise generate unwanted bugs.

Changing a tuple element’s value

We already know tuples are immutable. Their elements may not be immutable — lists would be an example — and so it might be a good idea to check the deep-vs-shallow-copy article I wrote on lists.

# create a new tuple
my_tuple = (1, 2, 3)
# print the object's type and contents
print(f"{id(my_tuple)}: {my_tuple}")
# attempt to alter an element
my_tuple[0] = 4
Output:
139733868523200: (1, 2, 3)
Traceback (most recent call last):
  ...
    my_tuple[0] = 4
TypeError: 'tuple' object does not support item assignment

As said before, tuples are immutable. We can’t change its contents via item assignment.

Iterating through a tuple

Very straightforward, this one’s achieved just as if we were using lists, since tuples are also ordered:

# iterate through the tuple's elements
my_tuple = (1, 2, 3)
for index, element in enumerate(my_tuple):
    print(f"element index {index} has the value of: {element}")
for element in my_tuple:
    print(f"{element}")
Output:
element index 0 has the value of: 1
element index 1 has the value of: 2
element index 2 has the value of: 3
1
2
3

Tuple shallow copying

Because a tuple is immutable, there is absolutely no reason for Python to create another copy of it. This is why the shallow copying mechanisms yield different results in the case of tuples as opposed to lists. More specifically, we’ll see that the copying mechanisms in the case of tuples will lead to multiple variables pointing to the same tuple object in memory.

# shallow copy via slicing
my_tuple = (1, 2, 3)
my_second_tuple = my_tuple[:]
print(f"{id(my_tuple)}: {my_tuple}")
print(f"{id(my_second_tuple)}: {my_second_tuple}")
# shallow copy - using tuple()
my_tuple = (1, 2, 3, 4)
my_second_tuple = tuple(my_tuple)
print(f"{id(my_tuple)}: {my_tuple}")
print(f"{id(my_second_tuple)}: {my_second_tuple}")
# shallow copy - using copy.copy()
import copy
my_tuple = (1, 2, 3, 4, 5)
my_second_tuple = copy.copy(my_tuple)
print(f"{id(my_tuple)}: {my_tuple}")
print(f"{id(my_second_tuple)}: {my_second_tuple}")
Output:
139801960279616: (1, 2, 3)
139801960279616: (1, 2, 3)
139801960767552: (1, 2, 3, 4)
139801960767552: (1, 2, 3, 4)
140188066853728: (1, 2, 3, 4, 5)
140188066853728: (1, 2, 3, 4, 5)

All three approaches yield similar results, as both variables point to the very same tuple object in memory. Altering one of them by concatenating it with another tuple will change that tuple’s id, since tuples are immutable and altering them is actually Python creating a new tuple having the new value(s).

Tuple deep copying

As previously stated in this article, deep copying is really just a recursive shallow copying process:

import copy
my_tuple = ([1, 2, 3], [4, 5, 6])
my_second_tuple = copy.deepcopy(my_tuple)
# can't alter tuple elements like my_tuple[0]
# but can alter my_tuple[0][1], since my_tuple[0] is a list
my_tuple[0][1] = 7
print(f"{id(my_tuple)}: {my_tuple}")
print(f"{id(my_second_tuple)}: {my_second_tuple}")
Output:
140557489187968: ([1, 7, 3], [4, 5, 6])
140557489324928: ([1, 2, 3], [4, 5, 6])

Separate entities is what we were going for and copy.deepcopy() accomplishes this, so that the change we made in one of the lists will not reflect in the second tuple object.

Count occurrences of element in a tuple

Since tuples are ordered, they do allow, like lists, duplicate elements. We can count the occurrences of one given element in a given tuple like this:

my_tuple = (1, 2, 3, 1)
occurrences = my_tuple.count(1)
print(occurrences)
Output:
2

Should we try to count the occurrences of, say, 5, which is an element that doesn’t exist in the given tuple, we’d simply get 0.

Get element position in the tuple

Again, because tuples are ordered, we sometimes may want to get a certain element’s position (index). Calling the index() method on a non-existent element will get us a ValueError thrown:

my_tuple = (1, 2, 3)
position = my_tuple.index(1)
print(position)
position_error = my_tuple.index(4)
Output:
0
Traceback (most recent call last):
...
    position_error = my_tuple.index(4)
ValueError: tuple.index(x): x not in tuple

Tuple concatenation

Similar to list.extend() — check this article — we sometimes may find ourselves in the situation where we’d want to extend a given tuple:

my_tuple = (1, 2, 3)
print(f"{id(my_tuple)} {my_tuple}")
my_tuple += (4,)
print(f"{id(my_tuple)} {my_tuple}")
Output:
139871299530560 (1, 2, 3)
139871299526064 (1, 2, 3, 4)

But, as you’ve probably already figured it out, altering a tuple — an immutable object — makes Python create a new tuple object, that will contain the newly modified value(s).

It’s always a good idea to keep track of what’s going on under the hood, as things will become even clearer and we’ll be able to make more sense of everything. It’s just a question of effort on our part. And with the rewards far outweighing the costs, there’s but one direction: forward.

Having wrapped up what should seem like a very brief crash course on Python tuples, I invite you to start digging over the Net for more information on and best practices in using tuples in Python projects! Stay safe and happy coding!

More content at PlainEnglish.io. Sign up for our free weekly newsletter. Follow us on Twitter and LinkedIn. Join our community Discord.

Python
Programming
Coding
Tutorial
Tuples
Recommended from ReadMedium