The Python Tutorial#Data Structures

Keywords: Python Lambda

The Python Tutorial#Data Structures

5.1 Data Structures

This chapter details some of the previous introductions, and also introduces some new ones.

5.1 More on Lists

List data types have more methods. Here are all the methods for list objects:

  • list.append(x)
    Adding a new item at the end of the list is equivalent to a [len (a):]= [x]

  • list.extend(iterable)
    Adding all items in an iteratable object to extend the list is equivalent to a[len(a):] = iterable

  • list.insert(i, x)
    Insert an item at the specified location. The first parameter is the element index, and the new item is inserted before the index, so a.insert(0, x) is inserted at the top of the list, and a.insert(len(a), x) is equivalent to a.append(x).

  • list.remove(x)
    Remove the first item whose value is x from the list. If X does not exist, the method throws an exception (ValueError exception)

  • list.pop([i])
    Remove the item at the specified location from the list and return it. If no index is specified, a.pop() removes and returns the last item in the list. (The square brackets wrapped in i in the method signature indicate that the parameters are optional, rather than writing a square bracket at this location. This notation is often used in Python Library Reference.

  • list.clear()
    Remove all items from the list, equivalent to del a [:]

  • list.index(x[, start[, end]])
    Returns a 0-based index of the first item with a value of x, if X does not exist ValueError Abnormal.
    The optional parameters start and end are interpreted as slice notation, which is used to restrict the search to a list-specific sublist. The index returned is relative to the full list index, not to the start parameter.

  • list.count(x)
    Number of times x appears in the return list

  • list.sort(key=None, reverse=False)
    Sort all items in the list (parameters are used to customize the sort, see sorted() Get more information)

  • list.reverse()
    Reverse list elements

  • list.copy()
    Returns a shallow copy of the list, equivalent to a [:]

Following are examples of demonstrating the list method:

>>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
>>> fruits.count('apple')
2
>>> fruits.count('tangerine')
0
>>> fruits.index('banana')
3
>>> fruits.index('banana', 4)  # Find next banana starting a position 4
6
>>> fruits.reverse()
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
>>> fruits.append('grape')
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
>>> fruits.sort()
>>> fruits
['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
>>> fruits.pop()
'pear'

Such as insert, reverse, or sort, which only changes the list but does not print the return value, they return the default one. [1] . This is the design principle applicable to Python variable data structures.

5.1.1 Using Lists as Stacks

The list method makes it very easy to use it as a stack, where the last element added to the stack is first released (last in, first out). Appnd () method is used to add elements to the top of the stack, and pop() with no parameters is used to put the top elements out of the stack. Example:

>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]

5.1.2 Using Lists as Queues

It is also possible to use lists as queues, where elements added first are released first (FIFO); however, this is not very efficient. Because adding and removing elements at the end of the list is fast, but inserting or deleting elements at the beginning of the list is slow (because all other elements have to be displaced by one bit).

Specially designed collections.deque Adding and deleting elements at both ends is fast and can be used to implement queues. Example:

>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry")           # Terry arrives
>>> queue.append("Graham")          # Graham arrives
>>> queue.popleft()                 # The first to arrive now leaves
'Eric'
>>> queue.popleft()                 # The second to arrive now leaves
'John'
>>> queue                           # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])

5.1.3 List Comprehensions

List derivation provides a concise way to create lists. Generally, it is used to create new lists, which are the results of operations on other sequences or iterative objects, or to create sub-sequences of elements that satisfy specific conditions.

If you want to create a square list:

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Notice that the variable named x was created (or rewritten) above, and it still exists after the loop ends. Use the following methods to create a square list without any side effects:

squares = list(map(lambda x: x**2, range(10)))

Or, wait for:

squares = [x**2 for x in range(10)]

This approach is more concise and readable.

Following the for clause, the expressions immediately followed by zero or more for clauses or if clauses, plus brackets, constitute the list derivation. The result is a new list whose elements are the results of the for and if clauses in the expression. For example, the following list derivation combines elements that are not equal in two lists:

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Equivalent to:

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Note that the order of for and if statements in the two code segments above is the same.

If the expression is a tuple (x, y) as shown above), it must be parenthesed.

>>> vec = [-4, -2, 0, 2, 4]
>>> # create a new list with the values doubled
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filter the list to exclude negative numbers
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # apply a function to all the elements
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # call a method on each element
>>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> # create a list of 2-tuples like (number, square)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # the tuple must be parenthesized, otherwise an error is raised
>>> [x, x**2 for x in range(6)]
  File "<stdin>", line 1, in <module>
    [x, x**2 for x in range(6)]
               ^
SyntaxError: invalid syntax
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

List derivations can include complex expressions or even nested functions:

>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']

5.1.4 Nested List Comprehensions

The expression at the beginning of a list derivation can be arbitrary, including another list derivation.

Considering the following example, a list containing three lists of 4 lengths implements a matrix of 3x4:

matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
]

The following list derives inverted rows:

>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

As mentioned in the previous section, nested list derivatives are evaluated in the context of the for that follows them, so this example is equivalent to:

>>> transposed = []
>>> for i in range(4):
...     transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

In turn, they are equivalent to:

>>> transposed = []
>>> for i in range(4):
...     # the following 3 lines implement the nested listcomp
...     transposed_row = []
...     for row in matrix:
...         transposed_row.append(row[i])
...     transposed.append(transposed_row)
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

In practice, build-in function should be chosen to compose process statements. In the above use cases zip() Functions are more useful:

>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

See also Unpacking Argument Lists Learn more about the use of * above.

5.2 The del statement

In the case of providing a list index rather than a value, there is a way to remove elements from the list: del Sentence. This is different from the pop() method of the return value. The del statement can also be used to remove parts of the list or to clear the entire list (previously implemented by assigning empty lists to list fragments). Example:

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]

del can also be used to delete entire variables:

>>> del a

After that, an exception is thrown by referring to name a (at least before other values are assigned to name a). More del usage will follow.

5.3 Tuples and Sequences

Lists and strings have many common properties, such as indexing and slicing operations. They are sequential data types (see Sequence Types - list, tuple, range Two kinds. Python is an evolving language, and other sequence types can be added. Tuples are another standard sequence data type.

Tuples contain several comma-separated values, for example:

>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])

Obviously, output tuples are always placed in parentheses so that nested tuples can be parsed correctly; although parentheses are always necessary (if tuples are part of other larger expressions), parentheses are optional for input tuples. You cannot assign a single item to a tuple, but you can create tuples that contain variable objects such as lists.

Although tuples and lists are somewhat similar, they are usually used for different scenarios for different purposes. Tuple is Immutable Often, it contains different types of elements, which can be unpacked (see subsequent chapters) or indexed (or when tuples are Named Tuple It can even be accessed by attributes. The list is variable Usually, the elements are also different types and can be accessed through iteration of lists.

Building tuples with zero or one item is special: an additional strange grammar can be applied in this case. An empty tuple is created by a pair of empty parentheses; an element's tuple is created by a value followed by a comma (it is not enough to put a single value in parentheses). Note: In this case: (1) it is feasible to represent an integer instead of a tuple, and (1,) to represent a tuple. Ugly but effective. Example:

>>> empty = ()
>>> singleton = 'hello',    # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)

Statements t = 12345, 54321,'hello!'are an example of encapsulating tuples: values 12345, 54321 and hello! Are encapsulated in a tuple. Reverse operation is also feasible:

>>> x, y, z = t

It is aptly called sequence unpacking and is suitable for any sequence on the right side of an equal sign. Sequence unpacking requires that the number of variables to be assigned on the left side of the equal sign be the same as the number of elements contained in the sequence. Note that multiple assignments are only a combination of encapsulated tuples and sequence unpacking.

5.4 Set

Python also contains data types that implement collections. A set is an unordered, non-repetitive set of elements. Basic functions include member relationship testing and duplicate entity elimination. Set objects also support mathematical operations such as union, intersection, difference set and symmetric difference set.

You can use curly braces and set() Functions create collections. Keep in mind: To create an empty collection, you must use the set function instead of {}, which is used to create an empty dictionary.

The following is a simple demonstration:

>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket)                      # show that duplicates have been removed
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket                 # fast membership testing
True
>>> 'crabgrass' in basket
False

>>> # Demonstrate set operations on unique letters from two words
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a                                  # unique letters in a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b                              # letters in a but not in b
{'r', 'd', 'b'}
>>> a | b                              # letters in a or b or both
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b                              # letters in both a and b
{'a', 'c'}
>>> a ^ b                              # letters in a or b but not both
{'r', 'd', 'b', 'm', 'z', 'l'}

As with list derivation, Python also supports set derivation:

>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}

5.5 Dictionaries

Another data structure embedded in Python is a dictionary (see Mapping Types - dict ) Dictionaries are called "joint storage" or "joint array" in other languages. Unlike sequences, sequences are indexed by a series of numbers, dictionaries are indexed by keys, which can be of any immutable type; strings and numbers are usually used as keys. Tuples that contain only strings, numbers or other tuples can also be used as keys; tuples that directly or indirectly contain variable objects cannot be used as keys. Because lists can change themselves using index assignment, slice assignment, append() and extend(), lists cannot be used as keys.

The best way to understand a dictionary is to think of it as an unordered set of key-value pairs, in which keys are unique. A pair of curly braces creates an empty dictionary: {}. Placing a comma-separated list of key-value pairs in curly brackets adds an initial key-value pair to the dictionary; this is also the format for dictionary output.

The main operations provided by the dictionary are to store and fetch values using keys. You can use del to delete a key-value pair. If the existing key is used to store the value, the old value associated with the key is rewritten. Using nonexistent keys to get values throws an exception.

Executing list(d.keys()) on the dictionary returns an unordered list of all keys in the dictionary (using sorted(d.keys()) [2] . Use the key in to check if the key exists in the dictionary.

The following are examples of using dictionaries:

>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
>>> list(tel.keys())
['irv', 'guido', 'jack']
>>> sorted(tel.keys())
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
False

dict() The constructor constructs a dictionary directly using a sequence of key-value pairs:

>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}

In addition, dictionary derivation can create a dictionary from any key expression:

>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}

When keys are simple strings, keyword parameters can be used to specify key-value pairs:

>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}

5.6 Looping Techniques

When traversing a dictionary, keys and their corresponding values can be retrieved simultaneously by using items() method.

>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
...     print(k, v)
...
gallahad the pure
robin the brave

When traversing a sequence, use enumerate() Function can retrieve both location index and its corresponding values:

>>> for i, v in enumerate(['tic', 'tac', 'toe']):
...     print(i, v)
...
0 tic
1 tac
2 toe

When traversing two or more sequences at the same time, use zip() Functions can pair elements:

>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
...     print('What is your {0}?  It is {1}.'.format(q, a))
...
What is your name?  It is lancelot.
What is your quest?  It is the holy grail.
What is your favorite color?  It is blue.

When you need to traverse a sequence in reverse order, you first specify a positive sequence, and then call it reversed() Function:

>>> for i in reversed(range(1, 10, 2)):
...     print(i)
...
9
7
5
3
1

When you need to traverse a sequence in a specific order, use sorted() Function returns a new ordered sequence, the original sequence will not change:

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
...     print(f)
...
apple
banana
orange
pear

Sometimes it is necessary to modify the sequence while traversing the sequence to create a new alternative sequence which is simpler and safer:

>>> import math
>>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
>>> filtered_data = []
>>> for value in raw_data:
...     if not math.isnan(value):
...         filtered_data.append(value)
...
>>> filtered_data
[56.2, 51.7, 55.3, 52.5, 47.8]

5.7 More on Conditions

Conditions used in while and if statements can contain arbitrary operators, not just comparison operators.

The comparison operator in and not in checks whether the specified value exists (does not exist) in the sequence. Operators is and is not compare whether two objects are really the same (memory address comparison); these two operators are only important for variable objects like lists. All comparison operators have the same priority and are lower than numeric operators.

The comparison operators can be linked together. For example, a < b = c tests whether b is greater than a and b equals c.

The comparison operator can be used in conjunction with Boolean operators and or, and the result of comparison (or any other Boolean expression) can be negated by not. and,or and not priorities are lower than comparison operators; not has the highest priority and or the lowest priority, so A and not B or C are equivalent to (A and (not B) or C. As always, parentheses can be used to express the desired priority order.

Boolean operators and or are known as short-circuit operators: their parameters are evaluated from left to right, once the result is determined, the evaluation process will stop. For example, if A and C are true and B is false, A and B and C will not evaluate expression C. When used as a general value instead of a Boolean value, the return value of the short circuit operation is the last parameter to be evaluated.

Comparisons or Boolean expressions can be assigned to variables:

>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> non_null = string1 or string2 or string3
>>> non_null
'Trondheim'

Note that in Python, assignment operations cannot occur within expressions as in C. C programmers may complain, but this avoids a common problem in C programs: they may misuse= when they want to express==.

5.8 Comparing Sequences and Other Types

Sequence objects of the same sequence type can be compared with each other. Comparisons use dictionary order: first, compare the first item of two sequences, if they are different, the result of comparison operation can be determined; if they are different, compare the next item in two sequences, and so on, until one of them is exhausted. If the two items being compared are of the same type, the dictionary order is used for recursive comparison. If all items in two sequences are equal, then they are equal. If one sequence is a subsequence of the other, the shorter one is smaller. The dictionary order of strings uses Unicode code code points to sort individual characters numerically.

The following is an example of comparison between sequential objects of the same type:

(1, 2, 3)              < (1, 2, 4)
[1, 2, 3]              < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4)           < (1, 2, 4)
(1, 2)                 < (1, 2, -1)
(1, 2, 3)             == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab'))   < (1, 2, ('abc', 'a'), 4)

Note that it is legal to use < or > to compare different types of objects when there is an appropriate way of comparison between different types of objects. For example, the comparison between mixed number types is based on the value of their numbers, 0 equals 0.0. Otherwise, the interpreter will throw TypeException Exceptions, not random results

Footnotes

[1] Other languages may return the changed object to allow method links, such as D - > insert ("a") > remove ("b") - > sort ();
[2] Calling d.keys() returns a dictionary view object. This supports operations such as membership testing and iteration, but the content is not independent of the original dictionary, but only a view.

Posted by chigley on Mon, 31 Dec 2018 16:45:08 -0800