## Augmented Assignment Operators Using Augmented Assignment Operators provides a shorthand way to edit a variable, then reassign it back to itself (e.g. Instead of coding `i = i + 1`, an augmented assignment operator can be used to perform the same action using shorthand: `i += 1`. ```python i += 1 i -= 1 i *= 1 i /= 1 i %= 1 i += ' world!' # Can be used with strings also. # Can also be used with list replication. person = ['John'] person *= 3 # ['John', 'John', 'John'] ``` ## Lists A *list* is a value that contains multiple other values in an ordered sequence. When referencing the list itself that's called the *list value*. The values inside a list are called *list items*. ```python spam = ['bacon', 'eggs', 'sausage'] ``` *Note: Most of the examples on this page will reference this list.* Indentation doesn't matter inside of lists. The example list can also be written using the following syntax: ```python spam = ['bacon', 'eggs', 'sausage'] ``` ### Access List Items by Index Specifying an index from a list will return that value. ```python spam[0] # 'bacon' ``` A negative index can also be specified. ```python spam[-1] # 'sausage' ``` ### Slicing Slicing a list returns a new list with the specified values `<list>[<start>:<stop>:<step>]` - **start:** The index to start the slice (inclusive). Defaults to 0 if omitted. - **stop:** The index to end the slice (exclusive). Defaults to the end of the list if omitted. - **step:** The increment between indices. Defaults to 1 if omitted. ```python spam[0:2] # ['bacon', 'eggs'] spam[:2] # ['bacon', 'eggs'] spam[1:] # ['eggs', 'sausage'] spam[:] # returns the whole list, ['bacon', 'eggs', 'sausage'] ``` ### Length The `len()` method returns the number of values that are in the list passed. ```python len(spam) # 3 ``` ### Reassign a List Value To reassign a list value, specify it's index and use the assignment operator. ```python spam[1] = 'ham' # ['bacon', 'ham', 'sausage'] spam[1] = spam[0] # ['bacon', 'bacon', sausage'] ``` ### List Concatenation The `+` operator can be used to combine lists. ```python ['A', 'B'] + ['C', 'D'] # ['A', 'B', 'C', 'D'] ``` *Python Tip*: a backslash (\) can be used to split instructions across multiple lines. ```python ['A'] + ['B'] + \ ['C'] + ['D'] # ['A', 'B', 'C', 'D'] ``` ### List Replication The `*` operator can be used to replicate list values. ```python ['A', 'B'] * 2 # ['A', 'B', 'A', 'B'] ``` ### Loop Over a List A `for` loop can be used to perform an action over each index in a list. ```python for i in range(len(spam)): print(spam[i], end='') # baconeggssausage ``` ### IN and NOT IN Operators The `in` and `not in` operators are used to test weather the specified value is located, or not located, within a list. ```python 'ham' in spam # False 'bacon' in spam # True 'bacon' not in spam # False ``` ### Tuple Unpacking *Tuple Unpacking*, also known as the multiple-assignment trick, is a way to assign multiple variables to the values in a list using a single line of code. ```python person = ['John', 42] name, age = person # name = 'John', age = 42 ``` ### List Enumeration An *enumeration* is a complete, ordered listing of all the items in a collection. *List Enumeration* is useful to access both a list's values and indices from within a loop. ```python for index, item in enumerate(spam): print('Index: ' + str(index) + ', Item: ' + item) # Index: 0, Item: bacon # Index: 1, Item: eggs # Index: 2, Item: sausage ``` ### random.choice() `random.choice(<list>)` returns a randomly selected item from a list. ```python import random random.choice(spam) # Will randomly return either 'bacon', 'eggs', or 'sausage' ``` ### random.shuffle() `random.shuffle()` reorders the values within a list. ```python random.shuffle(spam) ``` ### index() `index()` returns the index of the value if found, returns `ValueError` if not found. *Note: If there are multiple instances of the value in the list, only the index of the first instance is returned.* ```python spam.index('bacon') # 0 ``` ### Adding Items to a List #### append() `append()` is used to add values to the end of a list. ```python spam.append('ham') # ['bacon', 'eggs', 'sausage', 'ham'] ``` #### insert() `insert()` is used to add a value to a specific index in a list. ```python spam.insert(1, 'ham') # ['bacon', 'ham', 'eggs', 'sausage'] ``` ### Removing Items from a List #### remove() `remove()` removes a value from a list if found, returns `ValueError` if not found. *Note: If there are multiple instances of the value in a list, only the first instance is removed.* ```python spam.remove('eggs') # ['bacon', 'sausage'] ``` #### del() `del()` removes a value from a list at the specified index. ```python del(spam[1]) # ['bacon', 'sausage'] ``` ### Sorting a List `sort()` sorts the contents of a list. `reverse` is an optional argument. If set to `True`, then list is sorted in reverse. *Note: When sorting, all values in the list must be of the same type, otherwise `TypeError` is returned.* ```python spam.sort() # ['bacon', 'eggs', 'sausage'] spam.sort(reverse=True) # ['sausage', 'eggs', 'bacon'] ``` ### Nested lists Lists can also be nested inside of other lists. ```python spam = [['cat', 'bat'], [10, 20, 30]] spam[0] # ['cat', 'bat'] spam[0][1] #'bat' spam[1][0] # 10 ``` --- ## Mutable vs. Immutable A *mutable* data type allows values to be added, removed, or changed. An *immutable* data type can't be changed. Integers (`int`), Floating-Point Numbers (`float`), Boolean Values (`bool`), and Strings (`str`) are all immutable data types. ```python spam[1] = 'ham' # ['bacon', 'ham', 'sausage'] name = 'Sam' name[0] = 'P' # TypeError ``` ## Tuples Tuples are like lists, but are immutable. Tuples are coded using parentheses, instead of square brackets. ```python person = ('John', 42) ``` *Note: Use a trailing comma for single-value tuples.* ```python type(('John',)) # class 'tuple' type(('John')) # class 'str' ``` ## List and Tuple Type Conversions `list()` converts the parameter to the list type. `tuple()` converts the parameter to tuple type. --- ## Reference vs. Copy ### IDs All Python values have a unique identity (i.e. ID). The `id()` function returns this identifier. ```python id(spam) spam.append('ham') id(spam) # append() modifies the list "in place", so the identifier will remain the same spam = ['pig', 'chicken', 'cow'] id(spam) # During the reassignment, spam no longer references the original list. A new list was created. Therefore, id now displays a different identifier. ``` Python's automatic garbage collector frees up memory by deleting any values that aren't being referred to by any variables. ### References When a variable is assigned to another variable, the variable becomes a reference to the assigned variable. ```python spam # ['bacon', 'eggs', 'sausage'] cheese = spam cheese[1] = 'ham' cheese # ['bacon', 'ham', 'sausage'] spam # ['bacon', 'ham', 'sausage'] ``` However, when a new value of an immutable data type is assigned, the new variable will no longer reference the original. ```python age = 42 newAge = age newAge # 42 age # 42 age = 43 newAge # 42 age # 43 ``` ### Passing Reference When a function is called, the argument values are copied to the parameter variables. This means, with lists and dictionaries, a copy of the reference is used for the parameter. Keep this behavior in mind, as this can lead to confusing bugs. ```python def eggs(someParameter): someParameter.append('Hello') spam = [1, 2, 3] eggs(spam) print(spam) # [1, 2, 3, 'Hello'] ``` ### copy() `copy()` is used to make a duplicate copy of a mutable value, such as a list or dictionary, instead of just a reference. ```python import copy id(spam) cheese = copy.copy(spam) id(cheese) # cheese is different list with different identity cheese[1] = 42 spam # ['A', 'B', 'C', 'D'] cheese # ['A', 42, 'C', 'D'] ``` ### deepcopy() If the list being copied contains sub-lists, `deepcopy()` will copy the sub-lists also.