Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
1 INTRO2CS Tirgul 4 What we will cover today? 2 Sequences - reminder Tuples Mutable and Immutable Aliasing Shallow and Deepcopy Function Variables README(1) 3 README(s) are simple They are used everywhere (academy and the market) They are there for the future readers of the code In intro we ask you for quite a simple README README(2) 4 cs username ID real name Those are my friends that I consulted with regarding the ex Edit the name of the ex and its number This is how to run my program from a terminal Fill here a general description of your program - This program computes the expected time of end of the world - It does it based on the Algorithm developed by the Nostradamus - I preferred this implementation, since the Hollywood algorithm is boring and too long List of submitted files If needed so (not obligatory) Reminder - Sequences (1) 5 The most basic data structure in Python is the sequence. Each element of a sequence is assigned a number its position or index. The first index is zero, the second index is one, and so on. Sequences (2) 6 Python has several types of sequences, for example: list, tuple, str, range. All share the following features: • Each sequence contains a finite number of elements. • The elements are arranged in some order in the sequence. • It is possible to iterate over the elements in the sequence, according to their order. • It is also possible to check if an element is in a sequence. Sequences (3) 7 There are certain things you can do with all sequence types. These operations include indexing, slicing, adding, multiplying, and checking for membership. In addition, Python has built-in functions for finding the length of a sequence and for finding its largest and smallest elements, as we will see later. Casting empty sequences is always false 8 bool (0) == False bool (0.0) == False bool ("") == False bool ([]) == False enumerate 9 Enumerate returns a couple containing a count (from start which defaults to 0) and the values obtained from iterating over sequence. Share the advantages of both: for i in range(len(lst)): for item in lst: Enumerate(2) 10 Enumerate returns a couple containing a count (from start which defaults to 0) and the values obtained from iterating over sequence. >>> seasons = ['Spring', 'Summer ', 'Fall', 'Winter'] >>> for (i, season) in enumerate(seasons): ... print ("index: ", i, ", value: ", season) index: index: index: index: 0, value: 1, value: 2, value: 3, value: Spring Summer Fall Winter Mutable and Immutable 11 The value of some objects can be changed. Objects whose value can be changed are said to be mutable; objects whose value is unchangeable once they are created are called immutable. An object’s mutability is determined by its type; for instance, numbers, strings, ranges and tuples are immutable, while lists are mutable. Python Tuples 12 A tuple is a sequence of immutable Python objects. Tuples are sequences, just like lists. The only differences are that tuples can't be changed i.e., tuples are immutable, and tuples use parentheses instead of square brackets in lists. Creating a tuple (1) 13 Creating a tuple is as simple as putting different commaseparated values and optionally you can put these commaseparated values between parentheses also. For example: >>> tup1 = ('physics', 'chemistry', 1997, 2000) >>> tup2 = (1,2,3,4,5) >>> tup3 = "a", "b", "c", "d", "e" >>> print(tup1) ('physics', 'chemistry', 1997, 2000) >>> print(tup2) (1, 2, 3, 4, 5) >>> print(tup3) ('a', 'b', 'c', 'd', 'e') Creating a tuple (2) 14 The empty tuple is written as two parentheses containing nothing: >>> tup1 = () >>> print(tup1) () To write a tuple containing a single value you have to include a comma, even though there is only one value: >>> tup1 = (50,) >>> tup1 (50,) Accessing Values in Tuples 15 Like string indices, tuple indices start at 0, and tuples can be sliced, concatenated and so on. To access values in tuple, use the square brackets for slicing along with the index or indices to obtain value available at that index. >>> tup1 = ('physics', 'chemistry', 1997, 2000) >>> tup2 = (1, 2, 3, 4, 5, 6, 7) >>> print ("tup1[0]: ",tup1[0]) tup1[0]: physics >>> print ("tup2[1:5]: ",tup2[1:5]) tup2[1:5]: (2, 3, 4, 5) Updating Tuples – impossible 16 Tuples are immutable which means you cannot update or change the values of tuple elements. >>>tup1 = (12, 34.56) >>>tup2 = ('abc', 'xyz' ) >>>tup1[0] = 100 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment However, new assignments are always legal! 17 Creating a new tuple (or any new mutable item) is always legal: >>>tup1 = (12, 34.56) >>>tup2 = ('abc', 'xyz') >>>tup3 = tup1 + tup2 >>>tup3 (12, 34.56, 'abc', 'xyz') Delete Tuple Elements (1) 18 Removing individual tuple elements is not possible. There is, of course, nothing wrong with putting together another tuple with the undesired elements discarded. To explicitly remove an entire tuple, just use the del statement. >>>tup1 = (12, 34.56, 'abc', 'xyz') >>> del tup1[1] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object doesn't support item deletion >>> del tup1 >>>tup1 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'tup1' is not defined Basic Tuples Operations 19 Tuples respond to the + and * operators much like strings; they mean concatenation and repetition here too. In fact, tuples respond to all of the general sequence operations we used on strings. Python Expression Results len((1, 2, 3)) 3 (1, 2, 3) + (4, 5, 6) (1, 2, 3, 4, 5, 6) Description Length Concatenation ('Hi!',) * 4 ('Hi!', 'Hi!', 'Hi!', 'Hi!') Repetition 3 in (1, 2, 3) True Membership for x in (1, 2, 3): print x, 123 Iteration Indexing and Slicing 20 Because tuples are sequences, indexing and slicing work the same way for tuples as they do for strings. Assuming following input: Python Expression Results Explanation L[2] 'SPAM!' Offsets start at zero L[-2] 'Spam' Negative: count from the right L[1:] ['Spam', 'SPAM!'] Slicing fetches sections Built-in Tuple Functions 21 len(tuple) Gives the total length of the tuple. max(tuple) Returns item from the tuple with max value. min(tuple) Returns item from the tuple with min value. tuple(seq) Converts a list into tuple. No Enclosing Delimiters (1) 22 Any set of multiple objects, comma-separated, written without identifying symbols (i.e., brackets for lists, parentheses for tuples, etc.), default to tuples. x, y == 1, 2 is exactly the same as x, y = (1, 2) >>> a = 'abc', -4.2322e37, 18+6.6j, 'xyz' >>> print(a) ('abc', -4.2322e+37, (18+6.6j), 'xyz') >>> type(a) <class 'tuple'> No Enclosing Delimiters (2) 23 An example in python shell: >>> x, y = 1, 2 >>> x, y (1, 2) >>> type(_) <class 'tuple'> Underscore (‘_’) gets the last answer in the python shell Function returns multiple variables? Also a tuple 24 We saw previously that we may return few variables from a functions Actually python returns only one variable - A tuple! >>> def foo(): ... return 3, 4 >>> type(foo) <class ‘function'> >>> type(foo()) <class 'tuple'> >>> type(foo()[0]) <class 'int'> Mutable and Immutable types 25 object Mutable or Immutable? numbers Immutable string Immutable range Immutable tuple Immutable lists mutable Immutable/Mutable containers – a comment 26 Objects within an immutable object can be mutable And vice versa! >>> tup1 = (1, 2, [3, 4, 5]) >>> tup1[0] = 3 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> tup1[2][0] = 6 >>> tup1 (1, 2, [6, 4, 5]) Immutable/Mutable containers – a comment 27 Are those legal in python? >>> tup1 = (1, 2, [3, 4, 5]) >>> L1 = ['a', 'b', ('c', 'd', 'e')] >>> tup1[0] = 3 >>> tup1[2][0] = 6 >>> tup1[2] = 3 >>> L1[0] = 'g' >>> L1[2][0] = ‘g' >>> L1[2] = 'g' Immutable/Mutable containers – a comment 28 Are those legal in python? >>> tup1 = (1, 2, [3, 4, 5]) >>> L1 = ['a', 'b', ('c', 'd', 'e')] >>> tup1[0] = 3 >>> tup1[2][0] = 6 >>> tup1[2] = 3 >>> L1[0] = 'g' >>> L1[2][0] = 'g' >>> L1[2] = 'g' Aliases 29 An alias is a second name for a piece of data. Often easier (and more useful) than making a second copy If the data is immutable, aliases don't matter because the data can't change But if data can change, aliases can result in a lot of hard-to-find bugs Aliases 30 Aliasing happens whenever one variable's value is assigned to another variable >>> first = 'isaac' >>> second = first variable value first 'isaac' second id function 31 Id(object) Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. In most of the computers id function return the address of the object in memory. Aliasing immutable items – same identity 32 When we copy immutable items, the two items have the same id: >>> first = 'isaac' >>> second = first >>> id(first) 4314103120 >>> id(second) 4314103120 variable first second value 'isaac' Any new assignment will result in a different identity 33 But new assignment will always result in a new identity >>> first = 'isaac' >>> second = first >>> id(first) 4314103120 >>> id(second) 4314103120 >>> first = first + ' newton' >>> id(first) 4314315376 >>> id(second) 4314103120 variable value first 'isaac' second 'isaac newton' Aliasing mutable items is a completely different story! 34 As mutable items are allowed to change, they behave very differently in aliasing For example: >>> L1 = [1, 2, 3] >>> L2 = L1 >>> print(L2) [1, 2, 3] >>> id(L1) 4314314696 >>> id(L2) 4314314696 >>> L3 = L1[:] >>> print(L3) [1, 2, 3] >>> id(L3) 4314313992 # != id (L1) Huh?! Copying with the equal sign copying a reference 35 Assign a list to another - Both point to the same place in memory! >>> colours1 = ["red", "green"] >>> colours2 = colours1 variable value colours1 colours2 'red' 'green' Copying with the equal sign copying a reference 36 Assign a list to another - Both point to the same place in memory! >>> colours1 = ["red", "green"] >>> colours2 = colours1 >>> colours2[1] = "blue" >>> print(colours2) ['red', 'blue'] >>> print(colours1) ['red', ‘blue'] variable value colours1 colours2 'red' 'blue' New assignments are new references 37 On the other hand – any new assignment will always lead to a new identity variable >>> colours1 = ["red", "green"] >>> colours2 = colours1 colours1 colours2 >>> colours2 = ["pink", "yellow"] >>> colours1 ["red", "green"] value variable 'red' 'green' value colours1 colours2 'red' 'pink' 'green' 'yellow' Copy with the equal operator Same identity! 38 >>> nums1 = [1, 2] >>> nums2 = nums1 >>> id(nums1) == id(nums2) True >>> nums2.append(3) >>> print(nums2) [1, 2, 3] >>> print(nums1) [1, 2, 3] >>> id(nums1) == id(nums2) True variable value nums1 nums2 1 2 3 Shallow and Deep Copy 39 Shallow copy In the process of shallow copying A, B will copy all of A's field values. If the field value is a memory address it copies the memory address, and if the field value is a object that is not containers: int, float, bool (primitive type) - it copies the value of it. Deep copy In deep copy the data is actually copied over. The result is different from the result a shallow copy gives. The advantage is that A and B do not depend on each other, but at the cost of a slower and more expensive copy. Copy with the slice operator 40 Simple data types >>> list1 = ['a', 'b', 'c', 'd'] >>> list3 = list1[:] >>> id(list1) == id(list3) False >>> list3[1] = 'x' >>> print(list3) ['a', 'x', 'c', 'd'] >>> print(list1) ['a', 'b', 'c', 'd'] Copy with the slice operator – shallow copy 41 Compound data types - copy the reference! >>> lst1 = ['a', 'b', ['ab', 'ba']] >>> lst2 = lst1[:] >>> lst2[0] = 'c' >>> lst2[2][1] = ‘d’ >>> print(lst1) ['a', 'b', ['ab', 'd']] >>> id(lst1)==id(lst2) False >>> id(lst1[0])==id(lst2[0]) False >>> id(lst1[2])==id(lst2[2]) True deepcopy from the Module copy 42 Create a new version of the same values but with new references! >>> from copy import deepcopy >>> lst1 = ['a', 'b', ['ab', 'ba']] >>> lst2 = deepcopy(lst1) >>> lst2[2][1] = 'd' >>> lst1[0] = "c" >>> print(lst1) ['c', 'b', ['ab', 'ba']] >>> print(lst2) ['a', 'b', ['ab', 'd']] >>> id(lst1) == id(lst2) False >>> id(lst1[2]) == id(lst2[2]) False Quick Summary - immutable items 43 An alias is a second name for the same piece of data In immutable items every copy is an alias >>> a = (1,2,[3,4]) >>> b = a >>> id(a) == id(b) True >>> c = a[:] >>> id(a) == id(c) True Quick Summary - Mutable items 44 In mutable items we distinguish between three cases: Assignment (=): Assign a second name to the same identity Shallow copy ([:]): Copy all the fields (values for simple types and references for memory addresses ) Deepcopy (copy.deepcopy) Copy (recursively) all the values in one list to another is Vs. == 45 In python we have two functions to compare objects: is and the equal operator is test for identity and is similar for all types Equal is a function that may be implemented differently (wait for the cool stuff in OOP) In Lists == works similar to deepcopy and compare the values of two lists is Vs. == example(1) 46 >>> L1 = [1, 2, 3] >>> L2 = [1, 2, 3] >>> L1 == L2 True >>> L1 is L2 # similar to id(L1) == id(L2) False is Vs. == example(2) 47 >>> tup1 = (3, 4) >>> tup2 = (3, 4) >>> tup1 is tup2 False >>> tup1 == tup2 True >>> L1 = [1, 2, tup1] >>> L1 = [1, 2, tup1] >>> L2 = [1, 2, tup2] >>> L2 [1, 2, (3, 4)] >>> L1 [1, 2, (3, 4)] >>> L1 == L2 True >>> L1 is L2 False Function scopes 48 How can we determine what belongs to a function and what to the module? Scopes Function Scope – Everything between the function definition and the end of the function. Python functions have no explicit begin or end, and no curly braces to mark where the function code starts and stops. The only delimiter is a colon (:) and the indentation of the code itself. Everything inside the scope of a function “belongs” to it – local variables, local functions and more Functions have their own variables 49 Reminder: >>> a = 3 >>> def print_func(): ... a = 12 ... print('inside the func: a = ', a) ... >>> print_func() inside the func: a = 12 >>> print('outside the func: a = ', a) outside the func: a = 3 Local variables 50 Functions have a special type of variable called local variables These variables only exist while the function is running. Local variables are not accessible from outside the function When a local variable has the same name as another variable (such as a global variable), the local variable hides the other. Local variables - example(1) 51 >>> def func_a(): ... a = 3 >>> def func_b(): ... b = a -2 >>> func_b() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in func_b NameError: name 'a' is not defined Local variables – example(2) 52 a = b = e = def 5 3 4 print_func(): a = 3 print('in the b = a + 100 print('in the d = 2 * a print('in the print('in the return b + 10 c = print_func() func a =', a) func b =', b) func d =', d) func e =', e) Local variables – example(2) 53 a = b = e = def 5 3 4 print_func(): a = 3 print('in the b = a + 100 print('in the d = 2 * a print('in the print('in the return b + 10 # output: in the func a = 3 in the func b = 103 in the func d = 6 in the func e = 4 func a =', a) func b =', b) func d =', d) func e =', e) print('a =',a) a = 5 print('b =',b) b = 3 print('c =',c) c = 113 print('d =',d) c = print_func() NameError: name 'd' is not defined The global variable 54 a = 3 def print_func(): global a a = 12 print('inside the func: a = ', a) print_func() print('outside the func: a = ', a) inside the func: a = 12 outside the func: a = 12 When possible, avoid the use of global variables – global variable can potentially be modified from anywhere, and any part of the program may depend on it. Mutable items as variables 55 >>> def func_a(L): ... L[1] = 2 >>> L1 = [4,5,6] >>> func_a(L1) >>> L1 [4, 2, 6] Huh?!?! What happened to local variables? Mutable items are passed as references! 56 >>> def func_a(L): ... L[1] = 2 >>> L1 = [4,5,6] >>> func_a(L1) >>> L1 [4, 2, 6] Let’s test you (1) 57 L = (1,2,3) def foo(L): L[2] = 4 >>>L What will happen? Let’s test you (1) 58 L = (1, 2, 3) def foo(L): L[2] = 4 What will happen? >>>foo(L) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in foo TypeError: 'tuple' object does not support item assignment Let’s test you (2) 59 L = [1, 2, 3] def foo(L): L[2] = 4 >>>foo(L) >>>L What will happen? Let’s test you (2) 60 L = [1, 2, 3] def foo(L): L[2] = 4 >>>foo(L) >>>L [1, 2, 4] What will happen? Let’s test you (3) 61 L = [1, 2, 3] def foo(L): L = [1, 2, 4] >>>foo(L) >>>L What will happen? Let’s test you (3) 62 L = [1, 2, 3] def foo(L): L = [1, 2, 4] >>>foo(L) >>>L L = [1, 2, 3] What will happen? Let’s test you (4) 63 def foo(L): L2 = [1, 2] L[2] = L2 L = [1, 2, 3] >>>foo(L) >>>L What will happen? Let’s test you (4) 64 def foo(L): L2 = [1, 2] L[2] = L2 L = [1, 2, 3] >>>foo(L) >>>L L = [1, 2, [1, 2]] What will happen?