Module 7/Week 7

Lakukan tugas rumah & ujian kamu dengan baik sekarang menggunakan Quizwiz!

Why are tuples immutable?

1. One reason tuples are immutable is because there are times when an immutable type is required. For example, only immutable types can be used as keys in dictionaries, which is another way of storing and manipulating data. 2. If the elements shouldn't get changed. Using a tuple instead of a list will make sure this doesn't happen.

Tuples syntax (3)

1. Use parentheses to create a new tuple. We can still use square brackets when indexing and slicing a tuple. 2. Only contain one value. 3. Include a trailing comma. i.e., one = ("just me",)

Is operator, ex

> num_1 = 1000 > num_2 = 1000 > num_1 == num_2 # Test whether num_1 and num_2 are equal True > num_1 is num_2 # Test whether num_1 and num_2 refer to the same object False > num_1 = num_2 # Now num_1 and num_2 refer to the same object > num_1 is num_2 True > num_2 = -89 # Make num_2 refer to a different object > num_1 is num_2 False Line 1 (num_1 = 1000) creates an object for the value 1000 and binds the variable num_1 to it. The second line creates another object for the value 1000 and binds the variable num_2 to it. Next we use the == operator to test whether num_1 and num_2 refer to the values that are equal, which they do (True). Then we use the is operator to test whether num_1 and num_2 refer to (are bound to) the same object, which they aren't (False). Next we assign num_1 to num_2 (num_1 = num_2). This rebinds num_1 so that now it refers to the same object that num_2 does. When we test again whether num_1 and num_2 (num_1 is num_2) refer to the same object, which they now do (True). Now there is another assignment statement, which creates an object for the value -89 and rebinds num_2 to refer to that object (num_2 = -89). Now we see that num_1 and num_2 (num_1 is num_2) no longer refer to the same object (False). Assigning -89 to num_2 did not change the object for the value 100, which num_1 still refers to. We cannot change the value of an integer object, because integers are immutable, but we can rebind a variable to a different object.

Ex using lists and mutating

> num_list_1 = [3,17,12] > num_list_2 = num_list_1 # num_list_1 and num_list_2 refer to the same object > num_list_1 is num_list_2 True > num_list_2[0] = 99 # Change the object that num_list_1 and num_list_2 both refer to > num_list_1 [99,17,12] > num_list_1 is num_list_2 True Changing num_list_2 does not result in creating a new object and rebinding num_list_2 to that object. Instead it mutates the existing list object, which num_list_1 and 2 both still refer to. We can see that there is a difference between rebinding a variable and mutating the value that variable refers.

Mutable default arguements

BEWARE: If you use a mutable value as a default argument, a new object won't be created every time the function is called. Instead, a new object will be created the first time the function is called without an argument, and that same object will be used for later calls to the function (that don't have an argument). So if you have a list as a default argument, the same list would be used every time the function is called without that argument. def some_func(my_list=[]): my_list.append(1) return my_list The first time you call it without an argument, it will return [1]. The next time you call it without an argument, it will return [1, 1], then [1, 1, 1], etc. In order to avoid this behavior, do the following instead: def some_func(my_list=None): if my_list is None: (ind) my_list = [] my_list.append(1) return my_list

Mutability and immutability of function arguements

Changing a parameter in a function did not change the value of the variable that was passed in the function call. The reason this happens is because the variable we passed referred to an immutable type. Integers, like tuples, are immutable and cannot be changed. If a variable refers to a list, and we pass that list to a function, then the function can change the actual list that was passed. Lists and objects of user-defined classes are the only mutable types we've looked at so far - all the others are immutable. def square_val(val): val[0] = val[0] * val[0] print(val) num_list = [8] square_val(num_list) print(num_list) >[64] >[64] Here we see that the variable num_list got changed by the function we passed it to. The function could have changed the list in other ways such as adding or removing elements, but I wanted to show an example very similar to the one I showed in the page on functions, only using a list instead of an integer.

Immutable collections of mutable objections

If you have a tuple that contains mutable objects, the tuple itself is immutable because you can't change which objects it contains, however the mutable objects it contains can still be mutated.

Deep copy

Is an entirely separate copy (no shared sub-elements or sub-sub-elements). We can make a deep copy by making a copy of any sublist (or other mutable sub-elements): > copied_list = list(original_list) > copied_list[1] = list(original_list[1])

3. When does rebinding of a variable happen?

It happens when a new value is assigned to it. For example: zip_code = '97331'zip_code = '98225' The first line creates a string object with the value '97331' and binds zip_code to that object. The second line creates a new string object with the value '98225' and rebinds zip_code to that new object.

1. Is it possible to have variables be equal, but not refer to the same object? Is it possible to have variables refer to the same object, but not be equal? Explain both answers.

It is possible to have variables be equal, but not refer to the same object. For example, you can have num_1 referencing an object with the value 7, and num_2 referencing a different object with the value 7. It's not possible to have variables refer to the same object, but not be equal. For example, if num_1 and num_2 both reference the same object that has a value of -3, then num_1 and num_2 will be equal.

2. If nums_1 and nums_2 refer to the same list object, and you delete the first element of nums_1, then that affects nums_2, because they're the same list. Why is this not true if nums_1 and nums_2 refer to the same tuple object?

It's because lists are a mutable type, but tuples are an immutable type.

Tuples immutability

Lists are mutable and tuples are immutable - AKA, you can change a list but you can't change a tuple.

1. Does the following program contradict the idea that tuples are immutable? Why or why not? def tuple_madness(tup):return tup[1:]

No; tuple_madness returns a new tuple that contains the same items in tup except the first. tup is not modified.

.append (method notation) and del (operator notation)

We can append items to the end of a list using .append. > vocab_words = [] > vocab_words [] > vocab_words.append("usagi") > vocab_words.append("inazuma") > vocab_words.append("hebi") > vocab_words.append("kitsune") > vocab_words [usagi, inazuma, hebi, kitsune] We can delete items using del at the beginning of a list. > del vocab_words[2] > vocab_words [usagi, inazuma]

Tuples

Similar to lists but differ in syntax and that tuples are immutable.

Mutating a list with indexing

We can assign a new value to an existing element of a list: members = ["Tommy", "Johnny", "Joey", "Dee Dee"] > members ['Tommy', 'Johnny', 'Joey', 'Dee Dee'] > members[0] = "Marky" >members ['Marky', 'Johnny', 'Joey', 'Dee Dee']

Automatic sharing

Sometimes Python is able to figure out that it can save memory by automatically making variables refer to the same object. > num_1 = 5 > num_2 = 5 > num_1 is num_2 True > name_1 = "Betty" > name_2 = "Betty" > name_1 is name_2 True This only happens with equal immutable values, so it can't affect your code's results.

Tuple unpacking

Syntactical shortcuts for assigning the values of a tuple to variables: some_tuple = (1,2,3) num_1,num_2,num_3 = some_tuple The second line assigns the first, second, and third values of the tuple to num_1, num_2, and num_3 respectively. You can use tuple unpacking to swap the values of two variables without using a third variable as a temporary place holder. num_1, num_2 = num_2, num_1

Is operator

Used to tell if two or more variables refer to the same object.

Shallow copies vs deep copies - shallow copies

We can make a copy of a list like this: > original_list = [1, [1,2,3]] > copied_list = list(original_list) copied_list now holds a copy of original_list but it's just a shallow copy. > original_list is copied_list # False > original_list[0] is copied_list[0] # True > original_list[1] is copied_list[1] # True Although original_list and copied_list refer to different objects, the elements of original_list and the elements of copied_list refer to the same objects. If you mutate the list referenced by object_list[1] and then print copied_list: > original_list[1][0] = 99 > copied_list [1, [99, 2, 3]] If you enter, we see that copied_list hasn't changed. That's because we're not mutating the object referred to by original_list[0] (its an int, and ints are immutable). Instead, we are rebinding original_list[0] to a new int object. > original_list[0] = 5 > print(original_list) [5, [99, 2, 3]] > print(copied_list) [1, [99, 2, 3]] We are able to mutate the object referred to by original_list[1] because it is a list and lists are mutable. We can rebind original_list like: > original_list[1] = [2,4,6,8]

Mutating a list with slicing

We can slice: birds = ["starling", "blue jay", "mockingbird", "ostrich", "cuckoo"] > birds[1:3] = ["robin", "chickadee"] > birds ['starling', 'robin', 'chickadee', 'ostrich', 'cuckoo'] The number of elements being assigned can be different than the size of the slice being replaced. birds = ["starling", "blue jay", "mockingbird", "ostrich", "cuckoo"] > birds[1:3] = ["hummingbird", "wren", "emu", "penguin"] >birds ['starling', 'hummingbird', 'wren', 'emu', 'penguin', 'ostrich', 'cuckoo'] > birds[3:6] = ["cassowary"] >birds ['starling', 'blue jay', 'mockingbird', 'cassowary'] > birds[1:1] = ["kiwi", "big bird"] >birds ['starling', 'kiwi', 'bigbird', 'blue jay', 'mockingbird', 'ostrich', 'cuckoo'] > birds[2:3] = [] >birds ['starling', 'blue jay', 'ostrich', 'cuckoo']

Making a copy of a list with [:] or list( )

birds = ["starling", "blue jay", "mockingbird", "ostrich", "cuckoo"] >birds_copy_1 = birds[:] >birds_copy_1 = ["starling", "blue jay", "mockingbird", "ostrich", "cuckoo"] > birds_copy_2 = list(birds) > birds_copy_2 ['starling', 'blue jay', 'mockingbird', 'ostrich', 'cuckoo']

3. Write a function named delete_last that takes as a parameter a list and removes the last element from that list. It should not return anything - it should mutate the original list. For example, if the list passed to the function is [7, "joe", "apple", 9.81, False], then after calling the function, the list should be [7, "joe", "apple", 9.81].

def delete_last(list_1): del list_1[4] return list_1 list_1 = [7, "joe", "apple", 9.81, False] answer = delete_last(list_1) print(answer)

2. Write a function named insert_front that takes as a parameter a list and a value to add at the front of the list. It should not return anything - it should mutate the original list. For example, if the arguments passed to the function are [9, -55, 37] and "bob", then after calling the function, the list should now be ["bob", 9, -55, 37].

def insert_font(list_1, value_1): list_1[0:0] = [value_1] def insert_font(list_1, value_1): list_1[0:0] = value_1 return list_1 list_1 = [9,-55,37] value_1 = ["Bob"] answer = insert_font(list_1, value_1) print(answer)

Changing parameters - mutating values ex 1

def square_val(val): val = val * val print(val) num = 8 square_val(num) print(num) >64 (val) >8 (num) We pass num to function, square_val, and val gets bound to the same object as num. Then the line, val = val * val creates a new object for the value 64, and rebinds val to that object. At this point, num and val no longer refer to the same object. This is why num doesn't show any changes after the function call.

Changing parameters - mutating values ex 2

def square_val(val): val[0] = val[0] * val[0] print(val) num_list = [8] square_val(num_list) print(num_list) >[64] >[64] We pass num_list to the function, square_val, and val gets bound to the same object as num_list. Then the line, val[0] = val[0] * val[0], mutates the list that both num_list and val refers. This is why num_list shows a change after the function call.

Ex using lists

num_list_1 = [2,9,7] num_list_2 = [2,9,7] > num_list_1 == num_list_2 # Tests if equal True > num_list_1 is num_list_2 # Tests if they refer to the same object False > num_list_1 = num_list_2 # Now they refer to the same object > num_list_1 is num_list_2 True > num_list_2 = [23,-1,19] > num_list_1 is num_list_2 False In this example, being mutable does not seem to make a difference.

If you need a function to mutate a value

then that value needs to be a mutable type. Note that in Python.a variable does not have a type - its the value it references that has a type, and that type determines whether the value is mutable or immutable.


Set pelajaran terkait

Google for Education Docs & Drive

View Set

ASVAB Word Knowledge Practice Test 2020

View Set

Chapter 24: The Respiratory System - Respiratory Muscles and Pulmonary Ventilation

View Set

Multiple Choice and True or False Rules of the Road

View Set