Python -- list and tuple, which one do you use?

Posted by LonelyPixel on Wed, 27 Oct 2021 06:15:28 +0200

List and tuple basis

First, we need to understand the most basic concepts. What are lists and tuples?

In fact, lists and tuples are an ordered collection that can place any data type.

In most programming languages, the data types of collections must be consistent. However, there is no such requirement for Python lists and tuples:

l = [1, 2, 'hello', 'world'] # The list contains both int and string elements
l
[1, 2, 'hello', 'world']

tup = ('jason', 22) # Tuples contain both int and string elements
tup
('jason', 22)

Secondly, we must master their differences.

  • The list is dynamic and its length is not fixed. You can add, delete or change elements (mutable) at will.

  • Tuples are static, with fixed length and size, and cannot be added, deleted or immutable.

In the following example, we create a list and a tuple respectively. As you can see, for the list, we can easily change the last element from 4 to 40; However, if you do the same for tuples, Python will report an error because tuples are immutable.

l = [1, 2, 3, 4]
l[3] = 40 # Like many languages, the index in python also starts from 0, and l[3] represents the fourth element of the access list
l
[1, 2, 3, 40]

tup = (1, 2, 3, 4)
tup[3] = 40
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment

But what if you want to make any "changes" to existing tuples? Then you can only reopen a piece of memory and create a new tuple.

For example, in the following example, we want to add an element 5 to the tuple. In fact, we create a new tuple and fill in the values of the original two tuples in turn.

For the list, because it is dynamic, we just need to add the corresponding element at the end of the list. After the following operations, the elements in the original list will be modified without creating a new list.

tup = (1, 2, 3, 4)
new_tup = tup + (5, ) # Create a new tuple new_tup, and fill in the values of the original tuple in turn
new _tup
(1, 2, 3, 4, 5)

l = [1, 2, 3, 4]
l.append(5) # Add element 5 to the end of the original list
l
[1, 2, 3, 4, 5]

Through the above examples, I believe you must have mastered the basic concepts of lists and tuples. Next, let's look at some basic operations and considerations for lists and tuples.

First, unlike other languages, lists and tuples in Python support negative indexes, - 1 for the last element, - 2 for the penultimate element, and so on.

l = [1, 2, 3, 4]
l[-1]
4

tup = (1, 2, 3, 4)
tup[-1]
4

In addition to basic initialization and indexing, lists and tuples support slicing operations:

l = [1, 2, 3, 4]
l[1:3] # Returns a sublist with indexes from 1 to 2 in the list
[2, 3]

tup = (1, 2, 3, 4)
tup[1:3] # Returns a child tuple with an index from 1 to 2 in a tuple
(2, 3) 

In addition, lists and tuples can be nested at will:

l = [[1, 2, 3], [4, 5]] # Each element of the list is also a list

tup = ((1, 2, 3), (4, 5, 6)) # Each element of a tuple is also a tuple
 Of course, both can also be passed list()and tuple()Function conversion:

list((1, 2, 3))
[1, 2, 3]

tuple([1, 2, 3])
(1, 2, 3)

Finally, let's look at some built-in functions commonly used in lists and tuples:

l = [3, 2, 3, 7, 8, 1]
l.count(3) 
2
l.index(7)
3
l.reverse()
l
[1, 8, 7, 3, 2, 3]
l.sort()
l
[1, 2, 3, 3, 7, 8]

tup = (3, 2, 3, 7, 8, 1)
tup.count(3)
2
tup.index(7)
3
list(reversed(tup))
[1, 8, 7, 3, 2, 3]
sorted(tup)
[1, 2, 3, 3, 7, 8]

Here I briefly explain the meaning of these functions.

  • count(item) indicates the number of occurrences of item in the statistical list / tuple.

  • index(item) indicates the index of the first occurrence of item in the returned list / tuple.

  • list.reverse() and list.sort() represent in-situ inversion of the list and sorting, respectively (note that tuples do not have these two built-in functions).

  • reversed() and sorted() also indicate reversing and sorting the list / tuple. reversed() returns an inverted iterator (the above example uses the list() function to convert it into a list); sorted() returns a new ordered list.

Differences in the storage of lists and tuples

As mentioned earlier, the most important difference between lists and tuples is that lists are dynamic and variable, while tuples are static and immutable. Such differences are bound to affect the storage methods of the two. We can see the following examples:

l = [1, 2, 3]
l.__sizeof__()
64
tup = (1, 2, 3)
tup.__sizeof__()
48

You can see that for lists and tuples, we put the same elements, but the storage space of tuples is 16 bytes less than that of lists. Why?

In fact, because the list is dynamic, it needs to store pointers to point to the corresponding elements (8 bytes for int type in the above example). In addition, because the list is variable, it needs to store the allocated length (8 bytes) in addition, so that the use of list space can be tracked in real time. When the space is insufficient, additional space can be allocated in time.

l = []
l.__sizeof__() // The storage space of the empty list is 40 bytes
40
l.append(1)
l.__sizeof__() 
72 // After adding element 1, the list allocates space for 4 elements (72 - 40) / 8 = 4
l.append(2) 
l.__sizeof__()
72 // Since space has been allocated before, element 2 is added and the list space remains unchanged
l.append(3)
l.__sizeof__() 
72 // ditto
l.append(4)
l.__sizeof__() 
72 // ditto
l.append(5)
l.__sizeof__() 
104 // After adding element 5, there is not enough space in the list, so an additional space for storing 4 elements is allocated

The above example roughly describes the process of list space allocation. We can see that in order to reduce the overhead of space allocation during each addition / deletion operation, Python allocates more space each time. This mechanism ensures the efficiency of its operation: the time complexity of addition / deletion is O(1).

But for tuples, the situation is different. The tuple length is fixed, and the elements are immutable, so the storage space is fixed.

After looking at the previous analysis, you may think that this difference is negligible. But imagine that if the number of list and tuple storage elements is 100 million, billion or even greater, can you still ignore this difference?

Performance of lists and tuples

By studying the differences between the storage methods of lists and tuples, we can conclude that tuples are more lightweight than lists, so in general, the performance speed of tuples is slightly better than that of lists.

In addition, Python will do some resource caching for static data in the background. Generally speaking, due to the existence of garbage collection mechanism, if some variables are not used, Python will recycle the memory occupied by them and return it to the operating system for use by other variables or other applications.

However, for some static variables, such as tuples, if they are not used and take up little space, Python will temporarily cache this part of memory. In this way, the next time we create tuples of the same size, Python can no longer send requests to the operating system to find memory, but can directly allocate the previously cached memory space, which can greatly speed up the process The running speed of the sequence.

The following example is to calculate the time required to initialize a list and tuple of the same element respectively. We can see that the initialization speed of tuple is 5 times faster than that of list.

python3 -m timeit 'x=(1,2,3,4,5,6)'
20000000 loops, best of 5: 9.97 nsec per loop
python3 -m timeit 'x=[1,2,3,4,5,6]'
5000000 loops, best of 5: 50.1 nsec per loop

However, if it is an index operation, the speed difference between the two is very small and almost negligible.

python3 -m timeit -s 'x=[1,2,3,4,5,6]' 'y=x[3]'
10000000 loops, best of 5: 22.2 nsec per loop
python3 -m timeit -s 'x=(1,2,3,4,5,6)' 'y=x[3]'
10000000 loops, best of 5: 21.9 nsec per loop

Of course, if you want to add, delete or change elements, the list is obviously better. The reason you must know now is that for tuples, you have to create a new tuple.

Usage scenarios for lists and tuples

So which one do lists and tuples use? According to the characteristics mentioned above, we will analyze the specific situation.

  1. If the stored data and quantity remain unchanged, for example, if you have a function that needs to return the longitude and latitude of a location, and then directly transmit it to the front-end rendering, tuples are certainly more appropriate.
def get_location():
    ..... 
    return (longitude, latitude)
  1. If the stored data or quantity is variable, for example, a log function on the social platform is to count which users' posts a user has read in a week, then a list is more appropriate.
viewer_owner_id_list = [] # Each element records the IDs of all owner s that the viewer has seen in a week
records = queryDB(viewer_id) # Index the database and get the logs of a viewer within a week
for record in records:
    viewer_owner_id_list.append(record.id)

summary

We talked a lot about lists and tuples today. Finally, let's summarize what you must master.

In general, lists and tuples are ordered and can store collections of any data type. The main differences are the following two points.

  • The list is dynamic and variable in length. You can add, delete or change elements at will. The storage space of the list is slightly larger than the tuple, and the performance is slightly inferior to the tuple.

  • Tuples are static with fixed length and size. You cannot add, delete or change elements. Tuples are lighter than lists and have slightly better performance.

Thinking questions

  1. To create an empty list, we can use the following A and B methods. What is the difference in efficiency? Which should we give priority to? You can tell me your reasons.
# Create an empty list
# option A
empty_list = list()

# option B
empty_list = []
  1. In your daily study and work, under what circumstances do you use lists or tuples? Welcome to share with me.

Topics: Python Back-end