"WEBVTTKind: captionsLanguage: enHey guys, welcome to this advanced Pythoncourse. My name is Patrick and I create freetutorials about Python and machine learning.In this course, I teach you all the advancedtopics that bring your Python skills to thenext level. So who is this course for thiscourse is aimed at an intermediate skill level,you should already have some basic Pythonknowledge. For example, if you just completeda beginner course and are looking for thenext step, then this tutorial is perfect foryou. And even if you are already in the intermediatelevel, you can benefit from this because Ishare some helpful tips along the way. Andwe really go into detail of all the differenttopics. So here's an overview of what we willcover today, the course is splitted into 21sections. And in my opinion, every experiencedPython programmer should know about thesetopics. Alright, let's start. list is a collectiondata type that is ordered mutable, and thatallows duplicate elements. So let's have acloser look at lists and what you can do withthem. First of all, a list is created withsquare brackets. And within these brackets,you put each element that you want separatedby a comma. For example, let's put some stringsin here, banana, cherry, and an apple. Andif we print this, then we see that all elementsare printed, we can also create a new emptylist with the list function. So my list twoequals list. And if we print this, then wesee that this creates an empty list. And lateron, you can append items. List allows fordifferent data types. So for example, we cansay that our list can contain an integer,a Boolean, and a string. That's all possible.And the list allows duplicate elements. Soif we put in another apple here, that we thenwe see that we have two apples now insideour list. Now if you want to access an element,you do that by referring to the index. Solet's say item equals my lists, and then insidebrackets, you specify the index, and notethat the indices start at zero. So index zerois the first the very first item in this casethe banana. And if we print the item, thenwe see this is the banana. And index numberone is the cherry. index number two is theapple. And now if we put in an index thatis too large, what will happen, then we getan index error list index out of range. Sobe very careful with that. Now you can alsospecify a negative index, so minus one, thisrefers to the last item, in this case, theapple minus two is the second last item, andso on. Now if you want to iterate over yourlist, you can do that simply with a for loopfor i in my list colon and then do somethingthis crazy, just want to print it. So thenwe see that for each element inside our list,we print it and note that you don't have tocall this I you can call this also x or whateveryou want. Now if you want to check if an itemis inside our your list, you can do it withan IF and then your item that you want tocheck, say banana in my lists, colon and saylet's print. Yes. Else. Print. No. Now ifyou run this then we see that the banana isinside.All this let's check if the lemon is no theapple yes So that's a very simple syntax tocheck if your index is inside your list. Nowlet's talk about some other useful methodsthat you can do with the list. First of all,if you want to check how many elements Doyou have inside your list, you can do thatwith the Lang method. And now if we printthis, and we see that we have three elementsinside our list. Now if we want to appenditems, we can do that by my list dot append.And now let's append a lemon. Now, print that,we see that a new item the lemon, got insertedat the very last at the end of the list. Nowif we want to insert an item at a specificposition, we can do that with that insertmethods. And now First, we have to specifythe index let's say at index number one, andthen the item, say a blueberry, and then printit. And we see that at index number one, nowwe have the blueberry. If you want to removeitems, we can do that with the pop method.And this returns the last item and also removesit. So if we assign this to a variable, andprint it. And we see that now we got our appleback. And if we print our list, then we seethat the app is no longer in our list. Nowwe can also remove a specific element withthe dot remove method. For example, let'sremove that. Sherry then we see that the cherrygot removed. Now what happens if we specifyan item that is not inside our lists, forexample, if we have a typo here, then we geta value error. It's not in list. So be carefulhere. We can also remove all elements withthe clear method. So now we have an emptylist. Some more useful things that you cando is for example, you can reverse the listwith the reverse method. So now the list isin reversed order. And you can also sort yourlist with the sort method. Maybe this, forexample gets clearer for us numbers here also,let's say 4231 minus one, minus 510. And ifwe start this, then we see that it's now inascending order. So note that this sort methods,sorts your list in place. So this changesyour original list. And if you don't wantto have this change, but rather create a newlist, then you can do this with the builtin sorted method, new list equals sartet,and then your original list and note thatif you print your original list again, thenyou see this is still the same. And if youprint a new list, then you see that this isnow the new sorted list. Now, some usefultrick if you want to create a new list withthe same elements multiple times. So for example,I want a new list with five zeros in it, thenyou can do it like this. So let's say it'sput in a zero, and then times five. So ifwe print this,then we see that we have a new list with fivezeros. And we can easily conquer two listswith the plus operator. So let's say I haveAnother list equals to 12345. And then wewant a new list. So a new list equals my listplus my list too. And if we print this, thenyou your fun new lifts with both elementswith both lists inside it. So, yeah, let'stalk about slicing, slicing is a very niceway to access sub parts of your list withthe colon. So for example, let's create anew list with some numbers 12345689. And let'screate a new list and simply call it a andthen inside brackets, the A equals and thenmy list. And inside the brackets, you specifythis start index and the stop index. So let'ssay for example, start index one and stopindex five. And if we print this, and we seewe have a new list that goes from index one,to index five, and the last item, the lastindex is excluded. So it said index 123, andindex four. So our list has all the numbersfrom two to five. Now, if we don't specifya start index, then it starts all the wayfrom the beginning. And if we don't specifya stop index, then it goes all the way tothe end. And you also have an optional stepindex. So and then I put in another colon,and then the step index, and by default, it'sone. So let's say, this goes all the way fromthe beginning to the end with a step one.And if I put in a step two, then it takesevery second item. And I can also specifya negative index. So this is a SIM, a nicetrick to reverse your list. Now let's talkabout copying a list. So let's say let's callthis list original, and put in some fruitsin here, banana, Sherry, and an apple. Now,if I want to create a copy, and I simply doit by assigning it to the original one, thenyou have to be very careful. So if I printthe copy, the nice see that it, it's the sameas our original list. But now if I if I modifythe copy, what will happen is that it willalso modify the original list. So for example,if I append a lemon, and if I print the copy,and I also print the original, then we seethat the original list now also has a lemonin it. And this is because with this assignment,both lists refer to the same list in insidethe memory. So yeah, be very careful here.And if you want to make an actual copy ofyour list, you can do it with the dot copymethod. So now if we print them, we see thatthe original method, the original list isstill the same. We can also do it with thelist function, and as argument we use theoriginal list. So this also makes an actualcopy. And as third option we can use slicing,if I just use a colon here, so this meansslicing all the way from beginning to theend. And this also makes an actual copy.Now, as a last nice trick, I want to showyou an advanced technique that is called listcomprehension. So that's an elegant and fastway to create a new list from an existinglist with one line. For example, if we havea list with numbers 123456, and we want tocreate a list with squared numbers, and wecan do it like this, inside brackets, we say,i times i, for i in a, or maybe let's callthis my list. Now if we print my list andprint the second list, then we see that anew list got created where each element issquared. And the syntax is you have your expression,and then a four in loop over your list. Sonote like the same with iterating, you don'thave to call this AI, you can also call thisx. And then also use the x here. So that'sa very simple and elegant way to create anew list with another with some expressionin one line. tuple is a collection data typethat is ordered and immutable. It is similarto a list with a main difference to the tuplecannot be changed after its creation. a tupleis often used for objects that belong together.And let's have a closer look at tuples. Andwhat you can do with them. First of all, atuple is created with parentheses. And withinthese parentheses, you put each element thatyou want separated by a comma. So for example,let's put in Max, 2008, and Boston. And ifwe print this, we see each all the elementsinside our tuple. Now the parentheses areoptional. So we can leave them away. And it'sstill a tuple. One special thing is if youjust want to have one element inside yourtuple. And even if you put it in parentheses,and you write it like this, then this is notrecognized as a tuple. So if we have a lookat the type of this, then this is recognizedas a string. So what you have to do, thenyou have to put a comma at the end, even ifit may look strange. That's the right syntax.So now it's recognized as a tuple. You canalso use the built in tuple function to createa tuple from an iterable. For example froma list, so say Max 28. Awesome. If you printthis, then we also have our tuple created.Now if we want to access elements, we justdo that by referring to the index. So if wesay item equals my tuple, and then insidebrackets, we specify the index that we want,and the indices start at zero. So index zerogives us the very first item, we print this,then we see we have Mac's index one, we get28 index two, we get Boston, and if you usean index that is too large, we get an indexeiroa index out of range. So be careful here.We can also specify a negative index minusone refers to the very last item. So that'sBoston, in this case, minus two is the secondlast item, and so on.Now, what happens if we want to change theelements inside our tuple like with listsweek, if we write my tuple and then get thefirst index and assign it to a new value,like Tim, and if we run this, then we geta type error object does not support itemassignment. So this is not possible becausea tuple is immutable. Now we can easily iterateOver a tuple with the for in loop. So fori in my tuple colon and then do somethingin this case, I just want to print the element.So then for each element, we print that, andwe don't have to call this I can also callit for example x or whatever we want. We canalso easily check if an element is insideour tuple with an if in statement, so if maxin my tuple, and then we say just print, yes.And otherwise, we print No. And if we runthis, then we get a yes, so Max is in ourtuple. If we check for Boston, it's also insideour tuple if you check for Tim, and we geta no. So very easy syntax to check if somethingis inside our tuple. So let's talk about someother useful methods that you can do witha tuple. For example, create a tuple withsome letters in it. And first of all, if wewant to get thenumber of elements inside our tuple, we canjust use the Lang method, Lang, of my tuple.And this returns five, so we have five elements.If we want to count some elements inside ourtuples, so we can use my tuple dot count,and then we count the letterP.So then we see we have two letter piece insideour tuple. If we check for the L, we get aone, if we check for all, which is not insideour tuple and we get zero. And we can alsofind the first index of some specific elements.So for example, my tuple dot index of P. andif we run this, then it returns the firstoccurrence of this element. So this is anindex P. For example, if we say a, and weget index zero, we get if we want to get theindex of L, then we get index three. And ifwe check for an element that is not insideour tuple, then we again get a value error.So be careful here. Um, we can also easilyconvert a tuple to a list and vice versa withthe list and the tuple function. So if I saymy list equals and then I use the list function,and put the tuple here, then I get a listout of it. And I can convert it back, I saymy tuple to equals, and then the tuple function,my list if I print this, so then I have atuple again. Now let's talk about slicingwith tuples. So slicing is a very nice wayto access sub parts of your tuple with theuse of the colon. So for example, let's createa tuple with some numbers in it. And let'screate a tuple. And then the syntax is weuse the tuple, the original tuple. And theninside brackets we specify a start and a stopindex. So for example 225. And if we printthis, then we have number 345. So this goesfrom index number two to index number five,and the other last index is not included.So it only has index two, three, and fourin it. So if we don't specify a start index,then it starts all the way from the beginning.And if weIf we don't specify a stop index, then itgoes all the way to the end. Now, we can alsouse an optional step argument. So by default,this is one. So in this case, it goes allthe way from beginning to the end with a stepof one. And if we put in a two here, for example,then it takes every second element. And wecan also use a negative step, this is a nicelittle trick to reverse your tuple. Now wecan, let's talk about unpacking. So if wecreate a new tuple, like at the beginning,let's put, let's use Max, 28, and Boston.And we can unpack it, if we write to the,at the left side, we write our variables,so name, H, and city, and then just say equalsto my tuple, then we get each separate elementand the city. But the number of elements thatyou put in here must match the elements insideour tuple. So if we just use two elementshere, then we get a value error, to many,many values to unpack. But what we can dois we can unpack multiple elements with astar.So for example, if we use some numbers, so1001234. And if we want to unpack this, solet's say I won, and then a star, and say,I, two, and I three equals to my tuple. Andthen if we print I one, this is the very firstitem, if you print by three, this is the verylast item. And if we print by two, then theseare all the elements in between, and now convertedto a list. Yeah, so one more thing that Iwanted to show you is to compare a tuple anda list. And because a tuple is immutable,Python can make some internal optimizations.And thus, working with a tuple can be moreefficient sometimes, especially when workingwith large data. So let me copy this in here.In this example, we create a list and a tuplewith the same elements. And then we use theSIS dot get size of method to return the numberof bytes. And both of them. And if we comparethem, then we see that a list is larger, eventhough it has the same elements as the tuple.And also can be more efficient to iterateover a tuple. And also to create a tuple.So if we compare if we use the time it method,so there's a very nice method in the time,module time at that time it and then you canuse a statement and repeat this specific numberof times. So in this case, it's 1 milliontimes 1 million times we want to create aa list and 1 million million times we wantto create a tuple and then measure the time.If we run this, then we see that it took muchlonger to create the list than to create thetuple. So yeah, keep that in mind that workingwith tuples can be more efficient than workingwith lists. dictionary is a collection datatype that is unordered and mutable. It consistsof a collection of key value pairs. So eachkey value pair maps the key to its associatedvalue. And let's have a closer look at dictionariesand what we can do with them. First of all,a dictionary is created with braces. And insidethese braces, you put each key value pairseparated by a colon. So let's say key name,and then colon, and then the value, Max. Andthen you separate each item with a comma.So comma, and then let's put in another keyvalue, pair, age, colon 28, comma, and anotherone, city, Cole on New York. And if we printthis, and we see all the key value pairs here,then we can also use the dict function tocreate a dictionary. And there we put allour keys as arguments. So name equals Mary,comma, age equals 27, comma city equals Boston.And if you print this, we see that we havea second dictionary here. And note that withthis function, you don't have to use quotesfor your keys. Now, when you want to accessthe values, you do that by saying my dictand then inside brackets, you give it thekey. So you printthe associated value for the name, then weget max. And if we want to look up the age,we get 28. And what will happen if we usea key that is not inside our dictionary, forexample, check the last name, then this willraise an exception, a key error. So be carefulhere. A dictionary is mutable, so you canadd or change items after its creation. Sowhen we want to add an key value pair, wesimply do it like sell, we say my dict andthen inside brackets give it the new key.Let's give it an email. And then the associatedvalue max at x y z.com. And if we print it,then we see that our dictionary now has theemail key value pair here. Now if we do thesame thing again, and the key already exists,then it got gets overwritten. So let's sayemails, coolmax, then we see that it stillhas the key email. And now with our new value.If we want to delete items, we have severaloptions, we can say, we can use the Dell statement,so say Dell, my dict and then off the keyname, and then we print it then we see thatthe name key value pair is no longer insideour dictionary. Or we can use the pop method.So we can say my dick dot pop, and then giveit the key, let's pop the age. So now we seethat the age is no longer inside our dictionary.Or we can use the pop item method. So priorto Python 3.7. This removes an arbitrary pairand since Python 3.7 This removes the lastinserted item. So in this case, it's Python3.7 and then it removes the city. So we seethe city is no longer inside our dictionary.When you want to check if a key is insideour dictionary then there are two common waysto do that. The first one is to use an ifin statements so we say if name in my dictand then we can use this key we can say printmy dict name. So then max gets printed. Ifwe say last name and want to print it thenthe if statement is wrong. So this doesn'tget executed, so nothing is printed here.Or you can use a try accepts accept statements.So try and then access a key. So let's saymy texts, name. And except print, let's justprint error. So if we run this, then thisstatement is successful, so it can print thename. And if we want to access the last name,then this statement will raise an exception,a key error. So an exception is thrown, whichis caught here. So this statement then willbe executed. So if we run this, then we seethat we have the error here. When you wantto loop through a dictionary, you have severaldifferent ways within for in loops. So youcan say for key in my dict, and then printthe key, then you can see that this loopsthrough the dictionary, and loop through allthe keys. You can also say dot keys. So thiswill do the same thing. The keys method returnsa list with all the keys inside it.You can also loop over the values. So youcan say for value in my dict dot values andthen print the value. And then it prints thevalues. Or if you want to have both in oneloop, you can say for key comma value in mydict dot items, and then you can print thekey and the value. Now when you want to copya dictionary, you have to be careful. So themost common way to do it is like so let'ssay my dict copy equals to my dict and justassign it to the original mighty dictionary.And now if you print this, then we see thatis the same as the original one. But now ifwe modified the copy, this will also modifythe original one, let's say my direct copyand at the email max@xyz.com. Now if we printthe copy and the original one, then we seethat both dictionaries now have the new keyvalue pair. This is because with this simpleassignment statement, both dictionaries nowpoint to the same dictionary inside our memory.So be very careful if use this expression.If you want to make an actual copy, you canuse the built in copy function. So if we usethis one and print it and we see that theoriginal one didn't change,oryou can use the dict function. And as an argument,you pass the dictionary that you want to copy.So if you use this, then we see that the originaldictionary also didn't get affected. Now there'sa useful method to merge two dictionaries,that is called the updatemethod.Let's create two dictionaries. And the firstdictionary has a name, an age and an email.And the second dictionary also has a nameand an age but no email, but then it has acity. And if we want to merge these, we cando it like this. They might take a dot updateand then with the second dictionary, and nowif we print this then what happened. All theexistingkeysor key value pairs got overwritten. So thename is now Mary, the age is now 27. The emaildidn't change and the non existing keys thecity got edit So, yeah, that's a nice wayto update to dictionaries. Let's talk aboutpossible key types. So in all the examplesbefore I used a string as a key, but you canuse any immutable type, for example, you canalso use numbers as a key, or even a tuple.If it only contains immutable elements. Forexample, we can say, my dict, and then keythree, and so value, give it the squared value,then a key six and 36, and the key nine, and81. Now let's print this. So this is alsopossible, but then you have to be very careful,because when you want to access a value, likeso, and you want to do it like with lists,and you refer to the index number, for example,say index zero, then this will raise an exceptionbecause you have the key error. Zero is notin our list, what do you rather want to dois you want to use the actual key, so thekey three is not nine, and then if you printthe value, then we see we get the nine. Soyeah, we also can use a tuple as a key. Solet's say my tuple equals eight, seven, andthen create a dictionary and S key, we usethe tuple and s value, we use the sum. Nowif we print this, then we see we have ournew tuple here, and are our new dictionaryhere. And yeah, so tuples are also possible.But what is not possible, for example is alist. If we use a list here and run this,then this will throw an exception type erroron hashable type. That is because a list ismutable and can be changed after its creation.And therefore it's also not hashable and cannotbe used as a key. So be careful here. Setaside collection data type that is unorderedand mutable. But unlike lists, or tuples,it does not allow duplicate elements. A setis created with braces, just like a dictionary,but we don't put key value pairs in it. Butinstead just single elements separated bya comma. For example, let's put some numbersin here and print this. Then we will see ourset here. And if we put for example, anotherone and another two here, and print this again,then we see that only one of each elementis kept. Because a set does not allow duplicates,we can also use the set function and use aniterable. Here, for example, let's use a listhere. This will also create a set, or we canuse a string here are example Hello. And ifwe print this, first of all, we see that theorder is arbitrary because a set is unordered.And the order is not important. And we alsosee that there's only one l in our set. Sothis is a nice little trick to find out howmany different characters are in your word.Now, if you want to create an empty set, andyou do it like this just with the braces,then you have to be careful because now ifyou have a look at the type of this, thenwe see that this is recognized as a dictionary.So if you want to have an empty set, you haveto do it with the set method. Set is mutableso you can change it later on. So now we canadd elements and we do this with the dot addmethod. So let's put in some numbers hereand print this. And we can also remove elementsagain with the Remove method. So let's removethe three and if we want to remove an elementthat does not inside Our set, then this willraise a key error. So be careful here. Sothere's another method, let's call that thiscart method that does the same thing. So italso removes the element. And if it does notfind the element, then nothing will happen.So no error here. We can also use the clearmethod, of course, this will empty our set,or we can use the pop method. So this willreturn an arbitrary value of our set and alsoremoves it. So we print this. Then we seein this case, it returned the one and alsoremove the one from our set. Now, we can iterateover our set very easily with an for in loops.So for i in my set, and then do something,in this case, just print this. So this williterate over each element and print it. Andwe don't have to call this I we can also callthis for example x or whatever we want. Nowwe want to check if an element is inside ourset, we can do this with an if statement.So if one in my set, and then we print, yes.So the one is in our set, the two is in ourour set. And if we check for example, forthe four, then nothing gets printed. Now,let's talk about union and intersection. Andfor this case, first of all, let's createthree different sets one with odd numbers,one with even numbers, and one with primenumbers. And now we can calculate the union.So the union combines elements from both fromtwo sets without duplication. So let's calculatethe union of odds. And we do this with dotsunion, and then as an argument, the secondset so events and print this. Then we seethat now we have all the numbers from zeroto nine. So the union will combine elementsfrom both from two sets without duplication.We can also calculate the intersection oftwo sets. So the intersection will only takeelements that are found in both sets. So ifwe say the intersection equals arts dot intersectionevents, and if we print this, then we willget an empty set, because arts and eventsdon't have the same elements. Now if we calculatecalculate the intersection of arts and primes,we will get all the prime numbers that arealso odd. So 357 if you calculate the intersectionof events and primes, then we will get backonly the even prime numbers. So in this case,only the two now we can also calculate thedifference of two sets. So let's create twodifferent sets again, set a with numbers fromone to nine and set B with one with 123 101112. Now the difference will return a setwith all elements from the first set thatare not in the second set. So let's call thatcall a diff equals set a dot difference setB and print this.Then we will see that we will get back thenumbers from four to nine because it takesthe elements from our first set, but not theones that are also in the second set so onlyfrom four to nine. So if we do it the otherway around set be the difference set a thenit will take 10 1112 but not these three numbersbecause they are also here. So then there'sa second different method. second differencemethod, that's called the symmetric differencemethod. So, the symmetric difference methodwill return a set with all the elements fromset A and set B, but not the elements thatare in both sets. So again, so it takes 456789from set A, and 10 1112 from set B, but notone, two, and three, because they are in bothsets. So if I use set a symmetric differenceset B, then this is the same thing. Now, unionand intersection and the difference methodthat I just showed you, they will not modifythe original sets, they always will returna, a new set, but we can also modify our setsin place. So for example, we can say set adot update, set B. And now print our set A,then we will see that this updates the setby adding the elements that are found in anotherset. So without duplication again, so it doesnot add one, two and three again, but it adds1011 and 12. There's also a intersection upupdate method. So set a dot intersection update,set B. And what this does, it updates theset by keeping only the elements from foundin both sets. So only one two and three arefound in both sets. So only these numbersremain in our set. Then there's also the differenceupdate methods. So set a difference updateset B. And if we print this, we will see thenumbers from four to nine because differenceupdate, it updates the set by removing elementsfound in another set. So it also it foundit finds one, two and three in the set B soit removes these numbers from our set A. Andthen there's the symmetric difference update.So this updates the set by only keeping theelements found in set A and in set B, butnot the elements that are found in both. Soone, two, and three are found in both sets.So these are not taken, but then it takesall the remaining elements from both sets.Yeah, you'd have probably have to play aroundwith them yourself a little bit to make itclearer. And yeah, let's also talk about soapsets superset and disjoint methods. So forexample, let's make them a little bit smaller.You can calculate the if set A is a subsetof set B. And we print this then this willreturn false because subset means that allthe elements of our first set are also inour second set. So if we use it the otherway around set B is a subset of set A, thenthis will return true because one two andthree are also in the second set. And theopposite is called the super set method. Sois super set.And in this case, it returns false becausea super set returns true if the first setcontains all the numbers or all the elementsfrom the second set. So, set B does not contain546. So it's not a super set. But set a isa superset of set B, because it contains one,two and three. And we can calculate if twosets are disjoint. So this join returns throughif both sets have a null intersection, sono same elements. So set a is this joint setB. And if we print this, this will returnfalse because they have same elements. Andif we create, for example, a set C and putseven, eight in here, and check set a is thisjoint with set B, then this will give us true.Now let's briefly talk about copying two sets.If you have watched the previous episodesabout lists, for example, then you alreadyknow this, you have to be careful, and youwant to copied two sets and only do this witha simple assignment. So let's say let setB equals to set one, set a. First of all,if we print this, then we see that we havea copy. But now if we modify the copy, let'ssay set B at set seven. And if we print thecopy and also print the original one, thenwe see that also the original one changed,because with this simple assignment both pointsto the same set. So be careful here, you onlycopy the reference. Now if you want to makean actual copy, you have to use the dot copymethod. So if you run this again, and we seethat the original set didn't change, or youcan also use the set method and use the firstset as a argument. This will also make anactual copy. Now as the last thing, I wantto show you the frozen set, the frozen setis also a collection data type. And this isjust an immutable version of a normal set.So you create this with the frozen set method.And there's an argument you can also put aniterable here, for example, a list and let'sprint this, then we see our frozen set here.So with a frozen set, you cannot change itafter its creation. So if I try to do a.at,two to this will give us an error. Or I canalso say try a remove one. This will alsogive us an error or any of the updates, updatemethods I showed you, they also don't work.But for example, Union intersection and differencemethod, they will work a string as an orderedand immutable collection data type that isused for text representation. And it is oneof the most use data types in Python. So Ihope that at the end of the session, you'llfeel comfortable working with them. So let'sstart. First of all, a string is created witheither single or double quotes. So you canuse double quotes and then put your lettersin here. So let's say hello world, and nowwe can print this and then we see our stringhere or you can use single quotes This isprobably more common. The only thing you haveto be careful is if you have another singlequote inside this. So if you have for example,Iam a programmer. Now if you try to run this,then this will get a syntax error. So whatyou can do is you can either use an escapingbackslash here, so this is valid. Or you canput your single quote in Side double quotes.So this is again, a valid string. You mayalso sometimes see triple quotes. So thisis typically used for multi line strings.So now I can go in another line. And thisis also used for documentation inside yourcode. So now if we run this, we see that ourstring goes over multiple lines. Now, youmay also sometimes see an escaping backslash,like so. And this just says that the stringshould continue in another line. But it shouldnot create a new line here. So now if we runthis, then we see we have our one line helloworld string. Now, if you want to access characters,or sub strings, it's the same like with lists,you access it with inside brackets, so let'ssay char equal, or let's create a string first.Alright, my string equals hello world. Andthen you can say char equals and then my string.And then in brackets, you put the index youwant. So if you want the very first character,you have to use index zero. So we can printthis. So this is the H and F, we use indexone, we get the E, and so on, we can alsouse a negative index, so minus one is thevery last character, minus to the second last,and so on. But what we cannot do, for exampleis we cannot access a character and changeit. So if I want to change the first characterto a lower age, if I tried to run this, now,this will get a type error, a string objectdoes not support item assignment. And thisis because strings are immutable, so theycannot be changed. So be aware of that, wecan also access a whole substring with slicing.So then I will say my string and in brackets,I put this start index, so let's say one,and then a colon and then a stop index. Andthen if I print this, then I will see I getthe string, e Ll O. So what this does, itstarts at index one, and goes until indexfive, but index five is excluded. So be carefulhere. So it has 123, and four, so our stringis E Ll O. Now if I don't use a start index,then it starts all the way from the beginning.And if I don't use a stop index, then it goesall the way to the end. So this goes all theway from beginning to end. And then there'sanother optional step index. So if I put anothercolon here, and by default, this is one. Sothis takes every character. And now if I puta two here, it takes every second character.And I can also put a minus one here, and thenwhat it does, it will reverse our string.So that's a nice little trick to reverse thestring with this slicing operator. Now, wecan concatenate two or more strings simplywith a plus. So if I create another string,Tom and I will just call this hello and saythis is now a greeting. And then I can saymy sentence, I will create a new string thatis greeting plus, and then I want a spacebetween them. And then plus again, plus thename. And now let's print thisand then we see we have our concatenated string.So very easy with this plus here. Now we caniterate over our string with a four in loopso for i in greeting, and then do somethingso just print this print every letter So,this goes over our whole string and printseach character. And we don't have to callthis I, we can also call this for examplex or whatever we want. Now, if you want tocheck if a character or substring is insideour string, we can do this with an if in statement.So I say if and then I want to check for theletter E. So if e in greeting, and then Iwill print Yes. And otherwise else I willprint. No. So he is inside my word. So itprints Yes. So if I check, for example, forp, then it will print No. And I can also checkfor substring. So I can check for E Ll, thiswill also print Yes. Now let's talk aboutsome more useful methods that you can do withstrings. So let's say we have a string withsome whitespace here, and then we have ourhello world, and then some more whitespaceat the end. So if we print this, we will seethat our printed string also has the widestring. Now if I want to get rid of this,I can do my string equals my string dot strip.So this method removes our whitespace. Sonow if I print it, we see that the whitespaceis gone. And be aware that we this methoddoes not change our string in place, becauseas I said, a string is immutable. So if Ijust write it like this, then this will notchange my original string. So if I run it,our original string still has the whitespace.So what we have to do is, we have to assignit again to our original one, and then wehave the new string with without whitespace.Now, what we can do also, with strings iswe can say, we can convert every characterto an upper case, so let's say my string dotupper. And then we have all an upper cases,we can also say my string dot lower, thenwe have all in lower cases, we can check ifmy string starts with specific character orsubstring. So if we can say starts with andthen we can say h. so this will give us trueor we can also check for Hello, also trueand check with world. And we will get a false.But we can also check if it ends with something.So if it ends with world, so now we have true.And yeah, if it ends with Hello, then we geta false. Now we can find the index have acharacter or a substring. So let's say mystring dot find and then we want to find O.So this will return the first index that itfinds with an O. So index 01234. So it returnsa four, we can also check for substrings.So this is the at index three, our l o substringstarts and if it does not find a string, thenit will return a minus one. We can also countthe number of characters or substring it finds.So let's check for how many O's we have inhello world. So this will return to and howmany peas do we have? We have zero.We can also replace characters or substringsinside our string. So we can say my stringdot replace. And then we want to replace worldwith a new word. So we want to replace itwith the universe. And now, if we print this,then we see our string is now Hello universe.And also be aware here that this will returna new string and does not change this one.So if it does not find this strings, let'ssay for example, we have a typo here, thenit does nothing. So it will still print theoriginal string hello world. Now, let's talkabout lists and strings. So let's say youhave a string with some words. So let's saywe have here, how are you doing. And you wantto convert this to a list and put at eachword of my string as an element in my list.Now, what you can do then is you can say,my list equals my string, dot split. And ifwe print our list, then we see that we haveeach word now as an element in our list. Andby default, the delimiter it is looking foris a space. So here, the default argumentis a space. So it looks for each space, andthen splits our string here. Now, for example,if you have commerce, here, and then cannotfind a space, so it, we only have one elementhere. So now what you would then have to use,you would have to use as a delimiter, a comma.And then again, we have four elements. Nowif you have the list, and you want to convertit back into a string, what you can do isyou can say, let's say new string equals andthen we say, my whip, you know, we say andempty string, and then dot join, and thenthe list as an argument. And then we printthe new string. And then we will see thatthis will concatenate all of our words, allof our elements in our list. So this willput all of our elements together as a string.And between each element, it will put thisstring that we put here. So now if you puta space here, then it will put a space betweeneach element. And now we have our originalstring again. So the dot join method methodis a very useful method to quickly join theelements of a list back into a string. AndI would highly recommend to remember thisone because this is very useful. And let'sIn fact, let's talk about this a little bitmore. So let's say we have a list with someelements. So let's say for example, only A'sand then times six. So maybe you know thissyntax. So this will create a list with sixelements. And now if you have the task tojoin this into a string, a lot of times whatyou will see is that you will create an emptystring and then you will use a for in loop.So for i in my list, and then you will saymy string plus equals i. So let's check this.So it worked. We have our string here, butthis is bad Python code. Because what happenshere since a string is immutable. This willcreate a new string here and then assign itback to our original string. So this operationis very expensive. What you should betteruse it The dot chain method. So as I justshowed you, we can say, my string equals,and then we will say an empty string dot,join my list. And then we will print this.So this will also give us the same thing,but it's much cleaner, and also much faster.So let's look at the time of both of theseways. So let's say we have saved from thetime at module, we import the default timeras timer. And then we will say here, startequals timer. And at the end, we can say,Stop equals timer. And then we will print,stop minus start. So this will give us thetime it takes from here to here. And we willdo the same thing here.So if we run this, we will, let's remove this,we see that both both was very, very fast.But now let's say we have, for example, avery large list with let's say, 1 millionelements. And now I don't want to print mylist. So if we run this now, what we willsee that this The second way with a dot joinmethod is much faster. So the first way tookmore than half a second and the second onlypoint 01 seconds. So forget this way of doingit. And remember that duck shine method. Nowas the last thing, I want to talk about formattingstrings. So there are two ways to format astring, the old styles are with a percentoperator, or with a thought format method.And since Python 3.6, there's also the newf strings. And let's talk about all of thesemethods. So let's say we have a variable andcall it it's, let's say variable equals astring, and we have the name Tom. And thenwe will create a string and say it's the variableis and then we use the first method, so weuse a percent s. And then after our string,again, we use the percent and then the variable.So this tells the interpreter that we havea placeholder with a string here. And thenafterwards, we fill this placeholder withour variable. So now if you print our variable,then we will see that our string is the variableis Tom. Now, if we have a number here, weshouldn't use percent s here, we should usepercent D. So this stands for integer decimalvalue. So now we have the variable is three.And let's say we have a floating point. Solike this, and if we run this, then we seethat we still have three here because we toldthe Python that we have a decimal value here.So now what we want now is we want a floatingpoint, so we say percent F. And then we haveour floating point value here. And by default,it has six digits after the decimal points.So if we want to specify how many digits wewant to have, we can say, dot percent dotand then how many digits and then let's saytwo digits and then.to F. So this will giveus two digits after the decimal point. Sothis is the very old formatting style. Thenew formatting style is with the dot formatmethods. So now what He wants to do is asa placeholder, we use braces. And then afterour string, we call the dot format method.And then here we put all our elements as arguments.So now if we print this,then we see that we have the placeholder gotreplaced with our variable. And we can alsospecify how many digits so we can say, colon,dot two, F. So then we have two digits afterthe decimal point. And for example, if wehave more variables, we simply would placeanother placeholder here, and then anotherargument here. So let's say we have var twoequals six, and then we would put var twohere. And then we will see that we have allour variables inside our string now. So theseare the old formatting styles. And the newestway to do it is with the F strings. So thisis, since Python 3.6, or newer, you can usethe F strings. And with an F string, you wouldsimply put a f between the string and thenthe string. And then you will also use braces.And inside the braces, you can use your variablesdirectly. So you can use var here, and vartwo here, and then you don't need this anymore.So if we run this, then we see it worked.And yeah, I think this is much more readable,it's more concise. And it's even faster, especiallyif you have a lot of variables here. So Iwould highly recommend using this f stringf strings now, since python 3.6. And yeah,what this does is it evaluates the this atrun time. So we can also put some operationhere. So let's say it's a mathematical operation,like var times two. And then this will, willbe evaluated at runtime. So now, we see wehave our two times our variable here. And,yeah, so that's it about f strings. And that'sall I wanted to show you about the strings.The collections module implements specialcontainer data types, and provides alternativeswith some additional functionality comparedto the general Bert and containers, like dictionaries,lists, or tuples. So we will be talking aboutfive different types from the collectionsmodule, the counter the named tuple, the artistsdict, the default dict, and the deck. So let'sstart with the counter. And first of all,we have to import it from collections import,counter. And the counter is a container thatstores the elements as dictionary keys andtheir counts as dictionary values. So let'ssay we have a string called a with some differentcharacters, a BBB, CCC. And then we can createour counter, we say my counter equals counter,and then we give it our string. And if weprint it, then we see we have a dictionarywith all the different characters as keysand their count as values. So we have fivetimes a four times B, and three times C. And,like with a normal dictionary, we can havea look at only the items. So this will giveus all the key value pairs, we can have alook at the keys. So this will give us aniterable over the keys. And we can also onlyhave a look at the values. So this will giveus all the different values. And what's alsovery helpful is to have a look at the mostcommon element in our counter dictionaries.So we say if we first print our counter again,and then we can see Today we want to printmy counter dot most common. And then herehow many different items, so I want to seeonly the very first so the most commonelements. So if I print this, then I willget the A with the count five is the mostcommon element. So if I say two here, thatwill give me the two most common types, soit will also put the B in here. And this willreturn a list with tuples in it. So, for example,if I want to have a look at only the, I wantto see what is the most common element, thenI will x have to access the index zero, so,this will give us the tuple at index zero.And then if I only want to see the element,then I will again have to access the firstelement of this tuple. So against zero, andthen I will get the A is the element thatis most common in our string. So, we can alsouse a list here or any other iterable. Yeah,we can also have a list with all all the differentelements. So, if we say, print my counterdot elements, and this will give us an iterableover elements repeating each as many timesas it counts. So, I have to convert this toa list in order to print it nicely. So nowif I print it, and I will see, I will getall the different elements here as a list.And I can, for example, iterate over this.So that's the counter next talk about thenamed tuple. And of course, first of all,we have to import it. So we say from collectionsimport named tuple. And the named tuples isan easy to create and lightweight object type,similar to a struct. So what I can do is Ican define my named tuple. I say for example,let's create a 2d point and call it pointequals and then I will say named tuple. Andthen as first argument, I give it the classname. So typically, this is the same namethat I use here. And then as a second argument,I use another string and here I use all thedifferent fields I want separated by eithera comma or a space. So I can say x comma y.So this will create a class called point withthe fields x and y. So now I can create thispoint. So I can say p t equals point and thenI will give it values for x and y. So forexample, I will give it one and minus four.And now if I print my point, then I will seeI have a point with x equals one and y equalsminus four. And I can also access the fields.So I can say p t dot x and p t dot y. So thenthis will print the values for x and y. Nextis the ordered dictionaries. So from collectionsimport, ordered dict. And the ordered dictis just like a regular dictionary, but theyremember the order that the items were inserted.So they have become less important now sincethe built in dictionary class has also theability to remember the order since python3.7. This is guaranteed. But for example,if you use an older Python version, this maybe a way to use a dictionary that remembersthe order. So for example, let's create adictionary like so. And then we can appendkey value pairs like with a normal dictionary.So we say here and brackets give it a keya and a value, one. And let's do this withsome more key values. So let's say we haveB, C, and D, and 234. And now if we printthis,then we see it's the same order as we insertedit. So for example, if we inserted the A,at the very end, then it will also get printedat the end of our audit dictionary. Yeah,since here, I'm using three python 3.7. Soin this, I can also just simply use a normaldictionary now and it still remembers theorder. Next, we have a look at the defaultdict. So from collections import default dict.And the default dict is also similar to theusual dictionary container, with the onlydifference that it will have a default valueif the key has not been set yet. So what wewill do, we have to create a default dict.And as an argument, we will give it an a defaulttype. So let's say we want to have an int,an integer here as default type. And thenwe can fill our dictionary, again, let's sayD, with the key a is one and D with the keyb equals two, and let's print our dictionary.So we will see it here and then we can accessthe keys. So for example, let's access thekey a, and then it will give one and the keyp will return to and now if I put in a keythat does not exist, so for example C, thenwhat will happen, it will return the defaultvalue of an integer. And this is by defaulta zero. So I can also for example, say I wanta float default value. So then this will return0.0 if it does not exist, or for example,I will have an empty list if it does not exist.So yeah, with a normal dictionary, this wouldraise a key error. So now this would raisea key error, but with a default dict it wouldreturn the default value of the type thatwe specify. So, as a last collections type,we will talk about the deck. So the deck isa double ended queue. And it can be used toadd or remove elements from both ends. Andboth are implemented in a way that this willbe very efficiently. And yeah, let's createa deck so let's say d equals deck and thenwe can append items like with a list, let'ssay the append one and the append two andthen print it. Now, now, we see our deck hereand also we can say we can say d dot pannedleft. So this will add elements at the leftside. So now we can see our three got addedhere. And we can also again remove elementsfrom both sides. So we can say d dot pop.And now if we print our deck then we willsee that the with pop, this will return andremove the last element. So now the two gotremoved or we can say d dot pop left so thiswill return and remove the other From theleft side, so now, the three got removed.can also of course, say d dot clear. So thiswill remove all elements,we can extend our deck with multiple elementsat a time. So we can see d dot extend, andthen give it a list, let's say 456. So thiswill add all the elements at the right side,or we can say d dot extend left, this willextend all the elements at the left side.And note that now, it will add First, thefour from the left side and the five, andthen the six. So now six is the most leftelements in our deck. We can also rotate ourdeck so we can say d dot rotate one. And nowif we print it, we will see that this willrotate all elements one place to the right,I can also say for example, do not rotateto and then this will rotate all elementsto places to the right. Or if I want to rotateto the left side, and I will give a negativenumber here. So if I say d dot rotate minusone, then all our elements will rotate oneplace to the left.The inner tools module is a collection oftools for handling iterators. Simply put iteratorsare data types that can be used in a for loop.So for example, the most common iterator isthe list. And the error tools offer some advancedtools. And we will be talking about the product,the permutations combinations, the accumulatefunction, the group by function, and someinfinite iterators. So let's start with theproduct. So first of all, we have to importit. So we say from it or tools, import product.And let's say we have two lists a equals one,and two, and B equals a list with three andfour. And then we say we have a product ofa and b, and the product will compute theCartesian product of the input iterables.So let's print this. So print the product.And then we will see that we have a editortools object. So this is an iterator. Andto see the elements we can come convert itto a list, and then we will see the product.So the product will combine one and three,and one and four, and then two, and three,and two and four. So this is the product,we can also define a number of repetitions.So if we say repeat equals two, then it canrepeat. And let's run this and then we seethat this is a very large list. So let's makeour second iterables smaller, and print this.And then maybe the repetition gets clearer.So we have one and three. And since we canrepeat again we do one and three, and we haveone and three and two and three, two, andthree and one and three, and again with repetition,two and three, and two, and three. So that'sthe product. Then we also have something calledpermutations. So permutations will returnall possible orderings of an input. So let'ssay we have one, two and three as a input,and then we calculate the permutations ofa and print this again, as list and then wesee all the different orderings So we have123132213231312, and 321. So that's permutations.And we can also specify the length of thepermutations as a second argument. So if wewant to have shorter permutate, permutationswith only length two, we skip the argumenttwo. And then we see different orderings withthe length of 22121321, and so on. That'spermutations, then we have combinations. Sofrom either tools, import combinations, andthe combinations function will make all possiblecombinations with a specified length. So let'salso make an example here. Let's make a list123, and four, and then say comm equals combinationsof a. And the second argument with the lengthhere is mandatory. So in this example, I onlywant the length two, and then print this againas a list.And then we will see all possible combinationswith length two, so 12131423, to four, andthree, four. And, and note that we don't havecombinations of the same arguments or no repetitionshere. And if we want that, we can also usethe combinations with replacement function.So then we import it, so import combinationswith replacement. And then let's make anothercombination iterable and say combinationswith replacement of a and also of length two,and Prentiss comm with replacements, and thenwe see that it will make combination of oneand itself. So one and one, one and two, oneand three, and so on. So this is combinationsand combinations with replay replacement.Now, when we have the accumulate function,so the accumulate function makes an iteratorthat returns accumulated sums, or any otherbinary function that I will give as input.So let's make an example. First of all, importthe accumulate function. And then we can say,we leave the list a equals 123, and four,and then we say, accumulate equals accumulateof a, and print this. First of all, let'sprint our list and then print the accumulatedlist. So we see that our list is one, two,and three, and they accumulated sums is 136,and 10. So the first elements stays the same.And then we have one plus two is three, threeplus three is six, and six plus four is 10.So that's the accumulate function. And bydefault, it will compute the sums. But wecan also for example, multiply the elementsso let's import operator. And then we cangive as a second argument, we can say funcequals operator.ml. So this will multiplyeach element so one stays the same. One timestwo is two, two times three is six, and sixtimes four is 24. And as a third example,let's just use the max. So this will returnthe max for each comparison. So for example,if we have a five here in between, and havea look at our list than one is the same twonow two is the max then compared with fiveand five is Till the max compared with threeand five, still the maximum and compared withfour, five is still the maximum. So that'saccumulate. Now let's talk about the groupby function. The group by function makes aniterator that returns keys and groups froman inner rebel. So let's make an example.To make this clearer, let's say we have ourlist a equals 123, and four. And then we saywe make a group object, and that is groupby, and then we want to group A, and we haveto give it a key, which map has to be applied.So as key, we can define a function, so let'ssay smaller than three, and give it an input,and then return x smaller than three. So thiswill return true or false. And as a key, wewill give it this function.And then let's print this. So we will seethat this is a group by object and we caniterate over this. So we can say, for keyand value in our group object, and then wewant to print the key and the value. And thenwe will see it prints the key and an innertools, object, group or object. So we canconvert this to a list to see the values.And then it gets clearer. So we have our inputarray. And we group this into other lists.With the comparison if it's smaller than three,so for one and two are grouped together, becausethey are smaller than three, and the key istrue, and three and four are grouped together,and the key is false. Now, we can also usea lambda function here, so I will talk aboutthis in the next video. But as a very shortexplanation, lambdas are small one line functionthat can have an input and will do some expressionand then will return an output. So I can writethis same function in one line with a lambdaexpression. So I can write lambda, x and thencolon, and then simply x smaller three. Sothis will do the same thing. If I run this,then it will print the same thing. Now let'smake an another second example. For this,maybe this is not clear at the first side.So let's define a object persons. And thisis a list. And inside this list, we have differentdictionaries. And the dictionaries containsa name and an age. And let's say we want togroup our persons by the same age, so letand then we say lambda x and simply x ands key the age. And then if we run this andprint this, then we will see as keys, we havethe different values for age. So we have 2527and 28. And then we also see that it groupedTim and then together because they both are25 years old. And then we have Lisa and Claire.So that's the group by function. Then we alsohave some infinite iterators. There's thecount function, then this cycle function andthe repeat function. And the count functionis very simple. So if we just say for i incount and then Give it a start values. Solet's start at 10, and then print this. Sothis will make an infinite loop that startsat 10. And then adds one for every repetition.So one, so 10 1112, and so on. And this isstill going now. So then for example, if Isay, if I is 15, then we will we break, sothen it will stop at 15. That's the countfunction, then there's the cycle function.So this will cycle infinitely through an iterable.So let's say we have a list that has one,two, and three. And we want to cycle througha and print this. So this will print one,two, and three, and then cycle again, one,two, and three, and again, infinitely, untilI make some stock condition. So that's thecycle method. And now as a last thing, therepeat methods, so repeat,for i in repeat, and then I want to repeat,for example, just the one, then this willsimply make an infinite loop. And we'll printone. And I can also as a second argument,give it the stop repetitions. So how manytimes do I want to repeat for example, ifI say four, here, then it will repeat theone four times.Lambda function is a small one line anonymousfunction that is defined without a name, andit looks like this. First it has the lambdakeyword, then it can take some arguments,then a colon, and then an expression. Andwhat this will do, this will create a functionwith some arguments, and it evaluates theexpression and returns the result. So let'slook at an example. To make this clearer.Let's call a function and we call this add10. And this is equal a lambda with an input.And let's call our input x. And then it shouldevaluate x plus 10. So this will create afunction with one argument, and it adds 10to the argument and returns the result. Andwe assign this function to our var variableat 10. So now this is a function that we cancall with an argument. So let's call it withwith five. And now if we print this, thenit will print 15. So this is practically thesame as a normal function like this, let'scall this at 10. func, and this will takean argument x and return x plus 10. So thesetwo things do the same thing. But the lambdafunction is much shorter and only in one line.So lambda functions can also have multiplearguments. So let's say let's create a anotherlambda function and call this mouth and andthis is equal lambda. And now we give it xand y. And it should evaluate x times y. Sothis will create a function with two arguments,and it will multiply these two arguments andreturns the result. So now if we print forexample, mod two, and seven, then it willprint 14. So that's the lambda syntax. Lambdafunctions are typically used when you needa simple function that is used only once inyour code. Or it is used as an argument tohigher order functions, meaning functionsthat take in other functions as arguments.For example, they are used along with thebuilt in functions, sorted map, filter, andreduce, and we will have a look at all ofthem to make the usage of landac euro. Solet's start with the sergeant methods. Soyou probably already know this, and I alsoshowed this in my video about lists. So let'ssay we have a list. And we call our list pointsto the, and the list has tuples with two elementsin it. So you can think of this as the x andthe y well use of our points. And now if wewant to start this, so let's create a pointsto the sorted list. And then we can call sorted,this is built in, so we don't need to importanything. And now we can start our list. Sowe want to sort points 2d, and now print,first, print our points and then print ourpoints to the sorted. So by default, thiswill start our, our list by the first argument,so by the x argument, so one, 510 and 15.But we can also give it a specific rule howto sort it. So we can say we can give it akey argument and the key equals, and thisshould be a function. And as we now know,we can write a function with a lambda in oneline. So we can say, lambda with an argumentx. And now let's say we want to sort it bythe Y Well, you so by the second index, sothen we say, x of the index one. So now ifwe run this, then we will see that our listgot sorted according to the Y index. So whatthis does is, you can also, for example, giveit a or define a function, and let's say sortby y and then give it a index. And in this,give it an argument, and in this case, twoargument is a tuple. And then it returns thefirst index. So now we can also use this functionhere, so sort by y, and if we run this, thenthis will return the same result. But nowwe see with a lambda, we don't need this.And then we can simply use our lambda here,so we can use our lambda here, and get ridof this function. And yeah, that's one usecase of a lambda. For example, let's makeanother example of sorting. Let's sort thisaccording to the sum of each. So therefore,we would say lambda x and then evaluate xof index zero plus x have index one. Now ifwe run this, then we see that it got sortedaccording to the sums of each tuple. So that'sthe sergeant's method with a lambda is keyargument. Now let's talk about the map function.So the map function transforms each elementwith a function. So it looks like this. Ithas a func, a function as an argument, andthen a sequence. So this is for example, alist. So let's create a list with some numbersin it. So 123, and four, and five. And nowlet's create a another list and call thisB equals and now we will want to multiplyeach element by two. So let's say map. Andthen as a function, we define a lambda withan argument and evaluate x times to and thenas a second argument, we use our list. Andthen we print this and if we want to printthis, then if we simply print it like this,then it will print a map object. So we haveto convert it to a list first.And then we can see that each element gotmultiplied by two. So that's the map function.However, you can achieve the same thing withlist comprehension. So you probably alreadyknow the list comprehension syntax. It's alittle bit easier. So you can write it likethis. C equals And then let's say x timestwo, for x in a. Now, if you print this, thenthis will do the same thing. So, personally,I would prefer this syntax, it's a littlebit easier. But you should have heard aboutthe map function. Now the second functionis the filter function. So the filter functionalso gets a function and a sequence. And itwill, this function must return true or false.And the filter function will return all elementsfor which the function evaluates to true.So let's say let's also give it a six. Andlet's say we want to filter this. And we say,we equals filter. And let's say in this example,we only want to have the even numbers. Sothen we create a lambda with x, and we evaluatex modulo two equals equals zero. And thenif we run this, we should get only the evennumbers. So again, here, we can achieve thesame thing with list comprehensions. So wecan also write C equals a list and then insideour list, we write x for x in a, and thenwe can give it a condition, we can say, ifx modulo two equals equals zero. So we printC, then we see that this will do the samething. And as a last function, I want to showyou the reduce function. So the reduce functionalso takes a function and a sequence. Andit repeatedly applies the function to theelements and returns a single value. So let'ssay I have a list here. And I want to computethe product of all the elements. So let'scall this product, product A equals and thenI can say, read us. And in Python three, Ihave to import this now. So I have to savefrom func tools, import reduce. And then Ican come call the reduce function. And asa first argument, I give it a function. SoI define the function here, again, in oneline with a lambda i say, lambda, x, and nowit has two arguments here. So function, thefunction for the reduced function always hastwo functions has two arguments. So let'ssay x and y. And then it should evaluate xtimes y. And as a sequence, I gave it a, solet's print the product. So this will print.Let's make this example smaller, then we cansee it has one times two equals to two timesthree equals six, and six times four equals24. So yeah, that's the reduce function. Andthat's all I wanted to show you about lambdas.A Python program terminates as soon as itencounters an error, and an error can be eithera syntax error or an exception. So in thistutorial, we will have a look at what's thedifference between a syntax error and an exception?What are the most common built in exceptions?How can we raise and handle exceptions? Andhow can we define our own exceptions. So let'sstart with a syntax error. a syntax erroroccurs when the parser detects a syntacticallyincorrect statement. So for example, if Iwrite a equals five, and then in the sameline, I want to print this, this will raisea syntax error because I have no I have touse a new line here. So this will be fine.Or a syntax error can be for example, missingor too many parentheses. So if I try to runthis now, this will also raise a syntax error.And now exceptions. So even if a statementis syntactically correct, it may cause anerror when it is executed. And this is calledan exception error. There are several differenterror classes, for example, trying to adda number and a string will raise a type error.So, if I say A equals five plus, and thenas a string, I write the 10. And now, if Irun this, then this will raise a type error,unsupported operand types for plus int andstring. So, this is a type error. And nowlet's talk about some more common built inexceptions. So, of course, there is the importerror. So if I say import, and then some modulethat does not exist, then this will raisea module not found error, which is a subclassfrom the import error. This is a common exception,then there's the name arrows. So let's sayif I have a variable A equals five, and anotherone, b equals C, and C is not defined yet.So, if I run this, then it will raise a nameerror name C is not defined, then there'sthe file not found error. So, let's say Iwant to open a file f equals open and thenthe file is called some file dot txt. So ifI try to run this, then I will get a filenot found error, no such such file or directory.Then there's the value error. Which happensif the function or operation receives an argumentthat has the right type, but an inappropriatevalue. For example, let's say I have a listwith some numbers here 123. And now I canremove elements from a list with the dot removemethod. So I say a dot remove one, so thisworks fine. So now, I print A, and the onegot removed. And if I try to add the two,remove the four, which is not in the list,and this will raise a value error, so list,remove x x not enlist, then there's the indexerror. So if I want to access an index ofa sequence, or of this list, that is not thatis too large. So for example, if I try toaccess the index for, then this will raisean index error list index out of range. Andif I have a dictionary, so let's say I havea dictionary with and name, and the name isMax, and it has only the key value pair havethe name, and I want to access for example,I want to access the age then this will raisea key error because the H key is not insidemy dictionary.Now let's talk about raising an exception.So if you want to force an exception to occurwhen a certain condition is met, then youcan do this with the race keyword. So let'ssay we have a variable x equals and minusfive. And then we say if x smaller than zero,then we want to raise an exception and thenwe say, race and then we raise simply thebase exception, and as message we give itx should be positive. So now if we run this,then this will raise this exception x shouldbe positive. And now if we get given a valueof larger than zero, then no exception willbe raised. As a second way you can use theassert statements so you can say. You don'tuse an if statement. So you use an assertstatement. So you say assert, and then a conditionand the search statements will will throwan assertion error if your assertion is true.Not true. So if you write here, you make anassertion that x should be larger or equalto zero. And now if we run this, then thiswill raise an assertion error, we can alsogive it a message here. So x is not positive.And now this will print the message here.And if our statement is correct, so x is positive,then your code will be just fine. So if Iran this, then no assertion is here. Now ifyou want to handle exceptions, so you cancatch exceptions with a try except block.So you write for example, you write try andthen call on and then you can do some operations.So let's say I want to try a equals five dividedby zero, and this will raise an error. Solet's simply run this and show you what happens.So this will raise a cirro Division error,because division by zero is not allowed. Sowhat I can do, then I can make a try exceptblocks. So I will try this statement. Andthen I can write except, so if an exceptionis raised, then the code will continue here.And then I can simply print and our are happened.So if I run this, then your program doesn'tstop here, it will continue and it will continuein this line. And you can also catch the typeof exceptions so you can ride except exceptionas E. And then you can print your exceptions.So you can if I run this, then it prints thedivision by serial message from the zero divisionerror class. Now, it's good practice to specifythe type of exception you want to catch. Andtherefore you have to know the possible errors.So for example, if you know that this is azero division error, you can simply writeor you should write, except zero divisionerror. And then you can do something here.You can also for example, use multiple statementshere. So you can try multiple operations.So let's say we want to try five divided byone. So this is this is fine. And then wesay B equals a plus and then a string. Sowe we've already seen this, so this will race.So let's this will raise a type error. Solet's print here. So let's catch this acceptivezero division error as E and print E. Andnow we also want to catch a type error. Sothen we write type error as E, and then wecan also print this. So now if we run this,this will catch the Type error and printsthis message, unsupported operand types forfloat and string. And now if this fails, thenthis will be catched here, and then this matchmessage gets printed. So now we have divisionby zero. That's how you can handle exceptions.Now you can also with a try except block youcan also have a else clause. So an else clauseis run if no exception occurred. So here Iprint. Everything is fine. And now, if I,for example, make divide by one that's fine,and I want to say a plus four, that is fine.And then the code continues in the else clause.And I also can have a finally clause. So thefinally clause runs always No matter if therewas an exception or not. And this is, forexample, use to make some cleanup operations.So here we print Li cleaning up. So now ifyou run this, then the else clause runs, andthe finally clause runs. And if there is anexception, for example, this, then this lineis running. And again, the Finally, clausealso is running. So yeah, that's how you canhandle exceptions. Now, as the last thing,let's talk about how we can define our ownexception. so we can simply define own errorclasses by sub classing from the base exceptionclass. So we can say for example, class value,too high error, and typically, you want togive your class a name with an error at theend. So the class value to high error. Andthen as a base class, we use the exceptionclass, and then we can simply say pass. Sothis is already a valid, defined exceptionerror. So now, we can say, let's write a smallfunction, test value with an input. And nowwe say if x is larger than 100, then we canraise this value to high error. And by default,it can also have an error message. So we sayvalue is too high. And now if we run our methodwith an argument of, let's say, 200, thenwe will see that this will raise the valueto high error, so value is too high. And now,for example, we can use a try and accept lock.So let's say try test value, and then acceptand catch the value to high error. And thenwe print or let's print the era as E.And then print, let's catch the value to highera E and then print E. So then, we will seethat the message gets printed here. And usuallywhat you want to keep this classes small,but you can write it like any other class.So you can, for example, let's make a valueto small error. And also, as a subclass. Ithas a sub base class, it has the exceptionclass. And now you can, for example, definea custom in it method. So it has the selfargument, and then we give it the messageand value. And then we can store this variableshere. So we can say self dot message equalsmessage, and self dot value equals value.And now, inside our test function, we makeanother if statement. So let's check if xis smaller than five, and then we want toraise a value to small error. And now we haveto give it the message. So the message isvalue is too small. And then as a value, wegive it the x. And now if we catch this, thenwe want to catch the value too small erroras E. And now we have the information aboutthe error so we can print e dot message, andwe can also print e dot value. So if I testmy function with one, then the value to smallerror will get raised. So I'm sorry, I'm Misscolon. I forgot the column. So then, um, Itcatches the error here and prints all theinformation that I defined here in my errorclass. Python already comes with a powerfulbuilt in logging module. So you can quicklyadd logging to your application by simplysaying import logging. And then you can usethis. And in this tutorial, we will have alook at the different block levels, the differentconfiguration options, how to lock in differentmodules, how to use different lock handlers,how to capture stack traces in your log andhow to use rotating file handler. So let'sstart. So after importing the logging module,you can import to five different, you canlock to five different log levels. So letme copy this here. So the levels are debuginfo, warning, error and critical. And theyindicate the severity of the events. So ifI run this, then we will see that only warningerror and critical are printed. And this isbecause by default, only levels of only messageswith level warning or above are printed. Andif we want to change this, we can do thatby setting the basic configuration. And usuallywe want to do this right after importing themlogging module. And then we say logging dotbasic config. And then we can specify somearguments here. And for this, I would havea look at the documentation. So in the officialPython documentation, you find the differentarguments for the basic configurations. Sofor example, you can set the level and theformat, and then the date format. And so inthis case, I said level two logging dot debug.And then for the format, I give a string,and inside this string, I canspecify this lock record attributes. So forexample, I can have the name being locked.And I do this by saying or by writing percent,and then in parentheses, name and then S.Or I can say the ASC time, so this locks thetime, then the level name and the actual message.And then I can specify how the time shouldbe locked by saying date format equals andthen give a string for the date format. Andfor this, I can also have a look inside thedocumentation. So here are the different formattingrules for how to lock the time. So for example,percent m will look the month, then the daythen the year, then the hour, the minute andthe second. And now if I run this, then wesee our new format. And also that debug info,warning, error and critical are all locked.And by default, our logger is called the rootlogger. So that's because the name here isroot. Now, if I want to log in different modules,then it's best practice to not use this rootlogger. But create your own logger in yourmodules. So let's say we have a helper modulehere. And what you do then, after importing,logging, you create your own internal loggerhere by saying logger equals logging dot getlogger. And then you give it a name. And it'salso good practice to use this double underscoreand then name global variable. So this willcreate a logger with the name of the module.So it's called helper in this case, and thenyou can use this logger to lock somethingso as for example, say logger dot info. Hellofrom helper and then in your main module.After importing, logging, and setting theconfig, then for example, if I import thishelper module, then it will lock the messagefrom the helper module with the name of thislogger. So it's good practice to create yourown logger in your modules with this get loggerfunction and then give this name with doubleunderscores here as a name. Now, if I createthis log on here, then this will create ahierarchy of loggers. It starts at the rootlogger, and all these new loggers get addedto this hierarchy. And they propagate itsmessages up to the base logger. So now ifI don't want to have this propagation, I cansay logger dot propagate equals false. Soby default, this is true. And now this willnot propagate to the base logger. And nowfor example, if I run this module and importthe helper module, then nothing gets lockedhere because it doesn't propagate to our baselogger.Now let's talk about lock handlers. So handlerobjects are responsible for dispatching theappropriate lock message to the handlers specificdestination. So for example, you can use differenthandlers to send log messages to this standardoutput stream to files via HTTP or via email.And ba you let me show you how you set differentlock handlers. So first, we create a our loggerin our module by saying logger equals loggingdot get logger, and then the name of thismodule. And then I want to create my handler.And let's say I want to have a handler thatlocks to this stream. So a stream handler.And then this equals logging dot stream handler,though this is a built in class. And I alsowant a file handler that locks to the file.The file handler equals logging dot file handler,and then it needs a name. So let's say ourlock file is called file dot lock. And thentypically, for each handler, you want to setthe level and format. So we say, stream handlerdot set level, for example, set this to loggingdot warning. And for the file handler, thefile handler should only lock method messagesof level logging dot error. And now we alsospecify some format. So we say, a stream formatequals logging dot format. And then insidehere, we give it a string, just with the,the same like with the basic config. So let'ssay we want to have this string here. So wewant to have the name of the logger and thelevel name and the message. And all let'salso set the file handler to this format,or just call this format. And then First,we set the formatter to our handler. So wesay stream handler, dot set format, formatter,and also we say file handler, dot set formatterformatter. And then at the end, we have toadd our handler to the logger. So we say loggerdot add handler. And first we want to addthe stream handler, and then logger.at handler.And now we want to add the file handler. Andnow if we use this logger and lock somethingfor example, say logger dot warning, and thenwe want to say this is warning. And now wealso want to have logger dot erawan and Block,this is an error. And now if we run this,what will happen is in our stream, we havewarning and error, because our stream handlerlocks, messages of level warning and above.And then also file handler locks to a file.So now if we have a look, in our folder, thereis now this file lock. And this only has theerror message. So this is how we can definethe front lock handler. Now let's talk aboutother configuration methods. So we've alreadyseen the basic config method. But we can alsouse the file config or dict config method.And for this, you will create a file in yourfolder. And you specify it with this syntax.So you call it logging.com, or logging dotini. And then you define the loggers, thehandlers and the formatters. So in this case,we define two loggers with these names, onehandlers, and one format. And then you specifyeach of these further. So you say logger,and then underscore and then the name of thelogger. And then you give it its arguments.So let's say for example, we have a loggercalled simple example. And this should lockto level debug and above. And it should havea console handler. And then we come and wedefine the console handler, and this is astream handler with this formatter. And thenwe define this formatter and give it the format.And now if we want to use this config file,then in our file, we say, import logging,dot config. And then we can call logging dotconfig dot file, config, and then give itthe file name. So we say logging.com. Andnow what we can do is we can create a loggerwith for example, with this name. So thiswill get the simple example logger. So let'ssay logging dot get logger. Simple example.And now if we lock something with this logger,say logger dot d back, because it also locksdebug, this is a D block message. And nowif we run this, then we see we have the messagehere with this format, the time then the name,the level, and the actual message, just likewe defined here for our formatter. And wecan also use a dict config, but I won't coverthis now. So for this, you should also havea look at the documentation. So the configis just a different syntax that you can use.And then you would right here, logging dotconfig dot dict. config, and set this configfrom a dictionary. So with this two methods,you don't have to hard code your configurationin your code. But you can use a separate filethat you can easily change without changingthe code. So yeah, remember that you can alsouse these tickets and file conflicts. Nowlet's talk about capturing stack traces inyour lock. So this can be very helpful fortroubleshooting issues. So let's say you havea, you run a code thatraises an exception. So let's say we havea list with some values 123. And we want toaccess a value, but we use an index that istoo large. So this will raise a index error.And we can catch this by saying except indexerror as E and then we can say Logging doterror. And by default, this will only nowlock the error message live index out of range.But if we also want to lock the stack trace,then we can set the argument e xe info equalstrue. So e xe underscore info equals true.And this will also now if you run this, thiswill also include the stack trace in our logger.So now we can see that trace back and theline where our exception occurs. And yeah,so this is helpful for troubleshooting issues.And now let's say we don't know what kindof error we raised. So let's say we just say,accept and catch everything. But we stillwant to have our trace back, then we can importthe trace back module. And we can, for example,look a string. So the error is, and then weuse string formatting. So we say percent s,this is a placeholder. And then here, we callthis trace back dot format, e x c method.So this will now if we run this, then thiswill do the same thing. Basically, this willalso print this measure message to the lockthe error is, and then includes the traceback. So let's talk about rotating file handlers.So let's say you have a large applicationwith a lot of log messages, and you want tokeep track of the most recent events, thenyou can use a rotating file handler that keepsthe files small. So for this, let's say, wealso have to import this. So we say from loggingdot handlers import rotating file handler,then, let me quickly copy this here. You createyour logger. Here, you set level. And thenhere, you create your file handler. So yourhandler is now a rotating file handler. Andthen you give it the name of the lock file,then the max bytes. So this means that aftertwo kilobytes, it will roll over the lockto another log file. And it will also keepfive backup counts. And then we add our handlerto the logger. And then for example, we loga lot of messages. So we say, for underscore,this means that we don't care about this.So for underscore in range 10,000, we lookHelloWorld. And now if we run this, we seethat in our folder, we now have differentlog files, all with this Hello, world message.And now if we also have a look at the folder,then we see that each of these files is twokilobytes and after two kilobytes, it getsrolled over. So this is how you can use arotating file handler. And sorry, now, let'ssay your application will be running for along time, then you can use a time rotatingfile handler. So for this you say from loggingdot handlers import, timed rotating file handler,and this will create a lock, a rotating lockbased on how much time has passed. Sowhat we will do here is we also create a ourhandler that is now a timed rotating filehandler. And then the name of the lock andthen we say when should it roll over. Andtherefore we can give for example, we cangive an S for seconds, an M for minutes, anH for hours, then a D for day. We can alsosay midnight, or we can give it the weekdays.So, W zero means Monday, W, one means Tuesday,and so on. So in this case, let me rotatethis every seconds with an interval of five.So every five seconds, a new file gets created.And we keep a backup of five files. So nowif we say, for example, for underscore inrange, let's say six, and then we want tolock something. And after this, we want towait a specific amount of time. So let's importtime, and then say time dot sleep. And thenwe want to sleep five seconds. So now if werun this, we see that our lock file got created.And now if some time has passed, so afterfive seconds, another log file got createdwith this timestamp. And then after five seconds,again, another, and so on. So this is thetime rotating file handler. And as a lastthing, I want to mention that also if youhave a lot of different modules, and lockmany, many different things, so especiallyif you use a micro service architecture, thenI would recommend to use not locked to thissimple messages, but use the JSON format forlogging. And for this, I would recommend thisopen source, Python, Chase and logger. Soyou can find this on GitHub. And you simplyinstall it with pip install Python, Chaseand logger. And then you can define this format,and add this formatter to your handler. Andthen you log in JSON format. Jason is shortfor JavaScript Object Notation. And it's alightweight data format that is used for dataexchange. It's heavily used in web applications,so you should be comfortable working withit. Luckily, Python already comes with a builtin JS module that makes working with JSONdata very easy. So in this tutorial, we willhave a look at how we can encode and decodeJSON data with this module. So let's diveinto it. And first of all, let's have a lookat how Jason data looks. So here I have thisexample file called example dot Jason. Andhere we seethat chastened data looks very similar toa dictionary. So it consists of several keyvalue pairs. And as values it can take stringsor numbers, or Booleans, are also nested types,like here, a nested array or a nested dictionary.And we can also have a look at the whole conversiontable. And by the way, you can find this onmy website, Python minus engineer.com. Thereyou can find written tutorials to all my othervideo tutorials. And this is how Python istranslated to chase and vice versa. So a dictionaryin Python is an object and chasen list andtuples are an array is string is a string,integer, long and float are a number and chasten.True and False are also true and false, butwith a lowercase and none is now in Chase.And so these are all the conversions you haveto know. And let's start working with it.So let's say we have a Python dictionary andwant to convert it to a JSON format. And thisis also called serialization or encoding.So let's say let me copy this here. Let'ssay we have a dictionary called person. Andthis has a name, an age, a city, a Boolean,if it has children, and then titles and thisis a nested list. And let's say I want toconvert this to a chase an object. So firstof all, I have to import the chasen module.And then I can say, if I want to have thisin chasen format, I can say person chase Thenequals and then I use this module and I usechasen dot dump s, and then the person. Sothis will dump our object to a JSON string.Now, if I print this, print our person andchasen then I will see that this is now inchastened format. And we can see this, forexample, because false has a lower case. NowI can also specify an indent here. And I wouldrecommend setting this indent to four. Andnow this has a nicer format. I can also specifydifferent separators. And this is a tuplewith two values. So here I can specify differentseparators. So instead of a comma here, Iuse a semi colon in the space. And insteadof a colon in the space here, I want to use,let's say, an equal sign and the space. Andnow if I run this, then we can see that differentseparators here, but I would not recommendusing different separators, but instead usethe default ones. But what's also helpfulargument here is to use this sort keys argumentand set this to true. So by default, thisis false. And now if I run this, then we seethat our keys are sorted alphabetically. Sothis is how we can convert from a Python dictionaryto a JSON object. And in this case, to a string.Now, I can also convert it or dump it intoa file. And for this, I can say, I open afile. So let's say with open and let's callour file person, the chasen and I want toopen it in right mode, open it as file. Andthen I can say chasen dot DOM, not dump sbecause S stands for our string, I want todump into a file. So let's dumb and I wantto dump the person object into our file. Sonow if I run this, then we see that this filegot created in our folder. And this containsour JSON data here. So for example, I canalso specify the indent here, let's say indentequals four, and run this and have a lookat our file again, then we see that it hasnot a much nicer format.So this is how you convert from Python objectto JSON data. And let's say we have chasteneddata and want to convert it back to a Pythonobject. And this is called D serializationor decoding. So let's say I have our personin JSON format here and I want to convertit back into a dictionary and I will say personequals Jason dot load. So in this case, Iwant to load from a string and then I willgive it the person chasing and chasing andnow if I print our person again, and don'tprint this, then we will see that now we havea Python dictionary again, because here wecan see that false is written with an uppercase.So this is how you convert from a chase string.And, like before, if you want to convert froma chasen file and you use the chasen dot loadmethod. So for this we have to open our fileso we still have our person dot chasen herein our folder. So we say with open and let'sopen this file person, that chasen and nowwe want to open it in read mode as file andthen I want to I can say person equals chasendot load from our file. And then I can printthis and if we run this, then we see thatthis does the same thing. So this is how wecan decode chastened data. And now, in thiscase, we work with a dictionary by Let's saywe have a custom object. So let's say we havea custom class, let's call, let's create aclass called user. And our user has two instance,variables. So let's say it has a name andan age. Let's say, self dot name equals name,and self dot age, equals age. So now let'screate a user object user equals user. Andlet's say the name max and the age 27. Andnow let's say I want to have this in JSONformat. And like before I call chasen dotdump. So dump from a string, dump as a string.And I want to dump the user. Now if I runthis, then this will give a very long errorhere. And at the end, it says type error objectof type user is not chased and serializable.So what I have to do, I have to write a customencoding function, and this is not very long.So let's say let's create a function calledencode.user. And this will take a object. And insideour function, we check if our object is ofwith this is instant method. So this willcheck whether an object is an instance ofa class. So let's check if our object is ofclass user. And if so, then we will returna dictionary with all the instance variablesas key value pairs. So let's say it has thename. And this equals it, this is our objectdot name. And then it has the key h with thevalue object dot h. And then as a little trick,it will get also the class name as a key.So I can say, object dot with double underscoresclass and then dot double underscores name.So this would give the name of the class asa string. And then as a value, the value doesn'tmatter. So I simply put in true. And otherwise,I will raise a type error. Let's raise a typeerror and as a string or message, I will putthis same message here. So now this is ourcustom encoding function. And now in our dump,or dump s method, I give it that as a defaultargument. And now here, I use this encodeuser function. So this now we'll use thisfunction for how to encode the object. Andnow if I run this, then this worked. So nowI can print our user dot JSON. And now wesee that we have our dictionary with the name,the age and the user class is key with valuetrue. So this is how you encode a custom objectwith this default argument. And then there'salso a second way so you can implement a customchasen encoder. So let's say we import fromChase. We import the chase and encoder. Andthen we create a class called this user andcoder. And this is derived from this basechazan encoder. And then we override thisdefault method. So let's say this is calleddefault and this takes self and an objecthere. And then inside we do the same thing.So we check if our object is of the Last user,and then we'll we will return this dictionarywith the class name in it. And otherwise wewill we let the base chasen encoder handleit. So we say return chasen encode our default,self and object. And now in our dump or dumps method, I can give it a class argument asa class. Now I use the user in encoder andnot the bass chasing encoder anymore. So nowif I run this, then we see this also worked.And as a last option, now I can use this encoderdirectly. So I can say user chasen equalsuser encoder. Now let's create a user encoder.And then I can say dot encode our user. Andnow if I run this, then we see this also worked.So this is how you encode custom objects.Now let's say I want to decode our objectback. Let's say I have here our user in JSONformat. And I want to have it in a normalPython object. So I can say user equals Jasondot load s. And then I will give this userchase in here. Now, if I run this, then thisworked. So I can print the user. And now wesee we have a dictionary here. So we don'thave a user object. So let's check the typeof this user, then we see that this is a dictionaryhere. So for example, I cannot call user dotname, because it's not a user object. Butwhat I have to do if I want to decode thisinto a user object, I also have to write acustom decoding method. So let's call thisdecode user. And this will get a dictionary.And now, inside this function, we check ifour dictionary contains the user key. So nowhere, in in our encoding function, we addedthe user class name as a key. So now, in here,we check if this key is in our dictionary.So let's say if user dot double underscorename in dictionary, and then we will createand return a user object. So let's returna user. And as name, it will get the namefrom our dictionary, so name equals dictionaryand then the dictionary with the key name.And as a age, it will get the age of the dictionary.So age equals Dictionary of age, and otherwise,it will simply return the dictionary. So thenstill, the decoding will work but it willbe decoded into a dictionary. And now we haveto use this custom decoding method. So wecan say in our chasen dot load or chasen dotload s method, we can specify an argumentthat is called object hook. And now we setthis object hook to our decoding message.And now if we run this, we see that we haveour user object so we can let's print thattype of user. And then we see that this isnow a class user. And we can access its instancevariables for example, user dot name, andhere it prints max. So this is how you decodecustom objects.So Python comes with different built in modulesto generate random numbers. In this tutorial,we will have a look at the random module forpseudo random numbers, the secrets modulefor cryptographically strong random numbersand the NumPy random To generate arrays withrandom numbers. So let's start with the randommodule. And first of all, we import random.And this is used to generate pseudo randomnumbers for various distributions. And it'scalled pseudo random because the numbers seemrandom, but they are reproducible. And wewill see how we can reproduce the data ina second. But first of all, let's have a lookat the different functions. So the easiestone is random dot random. So let's say a equalsrandom dot random, this will print a randomfloat in the range from zero to one. So let'sprint a. So this is a random float in therange from zero to one. Now, if you want tohave a specific range, we can use random thatdot uniform and give it a start and a stop.So let's say our range is from one to 10.Now this will produce a random float in thisrange. Now if you want to enter chess, wecan use random dot Rand int, and give it therange. And if we run this a couple of times,hmm. Now it's not happening. But this rangewill actually now we got it, this will includethe upper bound, and you might expect a behaviorwith this is not included. So for this reason,you can use the RAND range method, so thiswill do the same thing, it will pick a randominteger in this range. But here the upperbound is not included. So this will neverpick the 10 here. Then there's the randomdot normal variate function with a mu anda sigma. So let's give it zero as mu and onesigma. And this might be useful if you'reworking in statistics. So this will pick arandom value from a normal distribution witha mean of zero and the standard deviationof one. So let's have a look at how this normaldistribution looks. This is the normal distributionfor different means and standard deviations.So in this case, we use zero and one, so wehave to have a look at the red line. And thiswill pick a random value somewhere in thisrange where our red line is not zero. So thisis the random normal variant. Now the randommodule also comes with different functionsto work with sequences on let's say, we havea list and call it my list equals. And let'screate a list with different characters. Soif we print this, we will see that each characteris now a element in our list. And for example,now we can pick a random choice. So let'ssay a equals random dot choice from our list.And print this so this will pick a randomelement. Now if you want to pick more elements,we can use random sample and give it the numberof different elements we want to pick. Andthis will pick unique elements. So it willfor example, never pick a twice. And if wewant to have a behavior where elements canbe can can be picked multiple times, we canuse the random dot choices method. And herewe have to use k equals three. So this willdo the same thing, but now we see it can pickelements multiple times.Then there's also the random shuffle methods.So let's say random dot shuffle our list sothis will shuffle a list in place. Now ifwe print this, then we see that the elementsare now shuffled. So these are the most commonfunctions to generate random numbers. Noware Yeah, I said that these are pseudo randomnumbers, because they are reproducible. Andyou can do this with the random seed method.So I can say random dot seeds and give ita value here. So let's say for example, one,and then I can do different random operations.So let's say I want to have, I want to printrandom dot random. And I want also want toprint some random integer. So let's say randomdot Rand int in the range from one to 10.Now, if I run this, this will produce somerandom numbers. And then I can reseed againwith this value with the same value here,one, and then do the same set of operations.And now if I run this, then we see that theseare now exactly the same numbers here. Now,I can also, for example, now I can see itwith a different value here, let's say two.And then I do this operations. And then again,I will see it with one and do these operations.And at the end, I will seed with two againand do these operations. And then I run thisand now let's have a look. And now we seethat all our operations are our random numbers,with a seed of one are now the same, and thenall, where I use the seeds to all these randompicks are now the same. So this is how youcan reproduce your data with this random seedfunctions. And because these numbers are reproducible,they are not recommended to use for securitypurposes. And for this purpose, you shoulduse the secrets module. So we can use importsecrets. And this only has three functions.And they should be used for things like passwords,or security tokens or account authenticationthings. So for all these purposes, you shoulduse the secrets module. The disadvantage isthat it's it takes more times for these algorithms,but but they will generate a true random number.So and it only has three functions. So thefirst one is secrets dot ran below. So let'ssay a equals secrets dot ran below, and thenit has an exclusive upper bound. So this willproduce a random integer in the range fromzero to 10. And 10 is not included. Then youhave the secrets dot random bits method. Sothis will return an integer with K randombits. So for example, let's give it four bits.Now, if you you're familiar with bits andbytes, so for example, here for bits meansthat it can has four different random randombinary values here. So the highest possiblenumber here, and this case would be 1111.So this is 15. So this is two to the powerof three, which is eight, then this is twoto the power of two, which is four. So eightplus four plus two plus one equals 15. Sothis will generate a random number in therange from one to 15.No from zero to 15, sorry. Then you also havea secrets choice method. So let's say I havea list. My List equals list and with somecharacters in here, and then I can use A equalssecrets dot choice and my list. And this wouldpick a random choice that is not reproducible.So this is the secrets module. And now ifyou're working with arrays, then you can usethe NumPy module. So if you have not installedit, just use pip install NumPy. And then youcan say import NumPy as NP. So usually, youwill do it like this. And then you can say,for example, you want a array with randomfloats, then you say A equals NumPy dot randomdot Rand, and then give it the dimensions.So in this case, I will put in three here.So this will produce a 1d array with threeelements in a year. So three random floatshere. Now, if I can, I can also use more dimensionshere. So I can three, this is now a threeby three array. Now if I want to have randomintegers in a range, I can say, Rand end andgive it the range from, let's say, zero to10. And here 10 is excluded. And then I cangive it this size. So let's say also sizethree a 1d array with random integers. Now,if I want to haveaarray with higher dimensions, I have to usea tuple here, so I can use a tuple and say,three by four, for example. So this will createa three by four array with random integers.Then, this will also have a randomshufflemethod. So let's say I have a NumPy arraywith different dimensions. Now print thisarray. And then I can say NumPy, dot randomdot shuffle, and then our array and now printthe array. And this will only shuffle theelements along our along the first axis. Sothis will never switch elements in between,but only switch elements in the first axis.So this is the NumPy random module. And oneimportant thing you have to know is that theret NumPy random generator uses a differentnumber generator than the one from the Pythonstandard library. And it also has a differentseat. Well, seat functions, so I can alsosay NumPy dot random dot seeds, and then giveit a value, let's say one. And then I cando some operations. So let's say NumPy ofprint this print NumPy dot random dot Randthree by three. And then I can receipt anddo the same thing. And this will now reproducethe same, the same array. And the importantthing is that you should use the NumPy randomseed method instead of the seed method fromthe random module that we've seen previously.So these are two completely different seedgenerators. decorators are a very powerfultool in Python and every advanced Python programmershould know it. In this video, I show youthe concept behind decorators how you canwrite your own decorators the difference betweenfunction and class decorators and some typicaluse cases. I promise you that once you haveunderstood the concept, it is not as difficultas it seems in the beginning, and it mightimprove your Python knowledge a lot. So let'sstart there are two different decorators,function decorators and class decorators.more common is the function decorator andit looks like this. So you have a function,call it def. And let's say call it do something.And that does nothing in this case. And aboveyour function, you have an add sign, and thensome other function name. So some decoratorfunction name, let's say my decorator. Sothis is how the decorator syntax looks. Andwhat this does a decorator is a function thattakes another function as argument and extendsthe behavior of this function without explicitlymodifying it. So in other words, it allowsyou to add new functionality to an existingfunction. So in this case, this function wouldbe extended with the functionality of thisdecorator. And in order to understand thisconcept, we have to know that functions inPython are first class objects. This meansthat like any other object, they can be definedinside another function passed as an argumentto another function, and even returned fromother function. So now, let's have a closerlook at the concept. So let's say we wantto, we have a function and call it print name.And this will simply print LX. And then wehave a decorator function, call it start anddecorator. And now as an argument, it takesa function. And inside our decorator function,we have an inner function called and we callit wrapper. So def wrapper, this is a wrapperfunction, which, which reps our function.So he inside this wrapper function, we executethe function. And then as I said, I can extendthe behavior. So I can do something before.And I can do something after it. So beforeI say in this case, simply printstart, and after it, I want to print and,and then after creating this inner wrapperfunction, I also have to return it. And now,to apply this, let's first of all, simply,let's execute the print name functions. Andif I run this, it prints LX. And in orderto apply the decorator, I assign this printname function to now to our decorator function.And as argument I take the print name function.So now the print name function has this newfunctionality. So now if I run this, we willsee that it prints Dart then executes thefunction and prints Alex and then it printsand, and now the decorator function will dothe same thing as this line. So now if I writeat start, and decorada, then I don't needthis anymore. So this now that's the samething. If I executed now, it will also printstart Alex and end. And now this is how wecan extend the behavior of a function witha decorator. So let's see what happens ifa if our function has some arguments. So let'ssay we have a function, call it at five andthis takes an argument and then it returnsX plus five. And now if I tried to run thisat five and this argument I give 10. Now,if I run this, I will get a type error becauseour wrapper takes zero positional arguments,but one was given. So here, I need the samearguments is here. And to fix this, I canuse the arcs and quarks. I will talk aboutthis in another video in more detail. Butbasically with this syntax, I can use as manyarguments in keyword arguments as I want.And now inside our wrapper function, I alsocall this function with the arguments andkeyword arguments. So let's write it likethis. And now if I execute it, then it works.So this is how you apply arguments. And nowwhat about the return value, so let's storethis in a result. So let's say result equals,add five, and then print the result. Now,if I print this, this will print none here.And to fix this, I also have to save the resultof the function here, and then return it frommy inner wrapper functions return result.And now if I run this, it can print the result.And now I said last thing, what about thefunction identity. So let's print the helpfunction of f5. The health information withthis help function, and also let's print thename of this function with this double underscoremethod. Now, if I run this, this will printthat help function wrapper, and the functionname is also wrapper. So Python got confusednow about the identity of this function. Soin order to fix this, I can import func tools.And here before my wrapper, I apply also adecorator. That's called func tools, dot wraps,funk. So this will now preserve the informationof my used function. So now if I run this,I see that it now knows the help on functionat five. And also, our function name is nowagain, at five. So this is all to completethe decorator funk decorator syntax. So thisnow is atemplate for a decorator that you can usefor all your function decorators. So let'ssay call it my decorator, then you can dosomething before the function, then you executethe function. And then you can do somethingafterwards. And then you return the resultand return the wrapper. So this is the templatefor a nice decorator. And you can also havea look at this on my website, Python minusengineer.com. Yeah. So now, as we've seenhere, we see here a decorator that takes afunction that takes an argument so decoratorscan also take arguments. And what this meansthis is basically now two inner functions,so an inner function within an inner function.And to make this clearer, we'll look at anotherexample. So let's say we have a function,call it greet, and then it takes a name. Andthen inside it will print. And now we usean F string. And I've shown this before inanother video about strings, so we can sayhello. And then inside braces, we use thename. And now we use a decorator and callit repeat and give it an argument num timesand set it to three. So I want a repeat decoratorthat executes this function three times. Sohow does this decorator now look? First ofall, we have the outer function repeat, whichalso takes num times and then inside it takesout decorator function as we've seen it before,so we have a Decker Ray down. So define adecorator. Repeat. And this takes a function.And then inside here we have our wrapper.And this takes arcs, and Clark's, and we decoratethis with our func tools dot wraps Deckerdecorator. And then inside our wrapper, Isimply want to repeat this the number of timesI've given here. So I say for underscore,because I don't need this for underscore inrange num times. And then I say result equalsour function with the arcs and the quarks.And then I return the result, then I returnthe wrapper, and then I return that decorator.So now if I execute greed LX, then this willbe executed the number of times I've givenhere. So now if I say executed four times.So this is how the concept behind decoratorswith arguments work. And now let's also talkabout nested decorators. So you can stackdecorators on top of each other. So you can,let's say we have a function and call it letme copy this here. So let's, we have a function,say hello, which gets a name, then it printsa greeting and returns the greeting. And nowwe can debug this, we can decorate this withour start. And decorator as we've seen itbefore. Now, let me copy this here inside.This is our start end decorator, which willprint start and end after our function. Andwe also decorate this with a second decoratorand call it D block.And now let me copy this debug decorator inhere. So, this debug decorator extracts thename and the arguments and the keyword argumentsand then it prints the information of thisfunction it executes the function and thenit also prints the information about the returnvalue. So, this will basically print somemore information about this function. Andso now if I apply multiple decorators to adda function, they will be executed in the orderthey are listed. So this means now if I sayfor execute say hello LX this will first ofall execute the debug function and then insidethe debug function, it will execute the startand decorator function. And then inside thisfunction it will execute the say hello function.So now if I run this, we will see that firstof all, it prints calling say hello this isfrom my Dubuc wrapper. Then it prints startfrom the start and decorator. Then it printsHello LX then ends and then again I'm hereI am prints the function name and the returnvalue. Hello Alex. So this is how you canapply multiple decorators. And now it's thelast thing Let's talk about class decorators.So instead of a function decorator, you canalso define a class decorator. So let's saywe have our function, say hello. And thenit simply print. Hello. And I want to decoratethis with a class decorator. And I call thiscount cause. So class decorators do the samething as function decorators, but they aretypically used if we want to maintain andupdate a state. So in this example, I wantto keep track of how many times I have executedthis function. So let's create a class callit count calls. And this has a init method.And it takes self Of course, and then it takesthe function just like the decorator function.And then inside the in it, I will save thefunction as class variable, or as member variable.And I said self funk equals funk. And thenI will also create a state. And I call thisself dot num calls. So and this is zero inthe beginning, so I want to keep track ofhow many times this got executed. And nowin order to write a class decorator, I haveto implement the call method. So this alsotakes self, then the arcs and the quarks.And this is the same as the inner functionin our function decorator. And now, sorry,this also has trailing double underscores.And now the call methods allows me to executea object of this class just like a function.So let's, as an example, let's just printHi, there, here. And now, let's say I createa object of this class called cc equals countcalls. And this takes a function here. Sothis example, I just use none. And now, sinceI've implemented this call methods, I cansay CC andexecute this as a function. So now, if I runthis, it prints Hi there. So in our example,I don't want to print Hi there. So, what Iwant to do now, I want to update the state.So I say self dot num calls plus equals one,then I want to print the number of calls.So, I print this is executedself dot num sorry self dot num calls timesand then now this is my man, I also have toexecute and return the function. So I sayreturn self dot func and now I call the functionwith all the arguments and the keyword arguments.And now if I say, if I run this and I saySay hello, then Oh, sorry, self num calls.Now, if I run this, then I will see this isexecuted one times and now if I run this again,then I will see. Now this is executed twotimes. So here I could keep can keep trackof how many times this is executed. So thisis how you can implement class decorators.And now let's talk about some typical usecases of decorators. So for example, you canimplement a timer decorator To calculate theexecution time of a function, you can usea debug decorator like you've seen before.To print out some more information about thecalled function and its arguments, you canuse a check decorator to check if the argumentsfulfill some requirements and the depth thebehavior accordingly. You can register functions,like plug ins, with decorators, you can cachethe return values. Or you can add informationor update the state generators or functionsthat return an object that can be iteratedover. And the special thing is that they generatethe items inside the object lazily, whichmeans they generate the items only one ata time and only when you ask for it. And becauseof this, they are much more memory efficientthan other sequence objects when you haveto deal with large data sets. They are a powerfuladvanced Python technique. So let's have alook at some examples. To understand how theywork. A generator is defined like a normalfunction, but with the yield keyword insteadof the return keyword. So let's define a functioncall it my generator. And here I can returnor I can yield some values. So here I usethe yield statement and yield a value. SoI want to yield one. And then I can have multipleyield statements inside a generator function.So I can, for example, also yield two, andthen yield three. And now I can create a generatorobject. So I can say ci equals my generator.And now if I print this,and this will only print that this is a generatorobject. And now what I can do, for example,I can loop over this object. So I can say,for i in ci, and then I print the value. Sothis will print one, two, and three. And Ican also get the values one at a time withthe next function. So I can say value equalsnext ci, and then I can print the value. Sothis will print one, and this will executethe function and runs until until it reachesthe first yield statement. And here, it returnsthe value and pauses at this line. So thenext time if I want to get the next value,again with this next function, so again, Isay value equals next ci, then it will continuehere and runs until the next yield statement.So it runs until here, and returns to andpauses here. So if I run this, now, it will,it will print one and two. And if I do itagain, then it will also return and printthree. And now what will happen if I try torun it a fourth time. So now if I run it,this will raise a stop iteration, becausea generator object will always raise a stopiteration if it does not reach another youthstatement. So yeah, this is how generatorswork. And you can also for example, use themas inputs to other functions that take iterables.So for example, the built in sum functiontakes a iterable. So I can give the generatorobject here and I can print this. So thiswill calculate one plus two plus three equalssix. Or I can, for example, use the builtin sorted method and put the generator objecthere. So this will return. This will createand return a new list with all the objectsin a sorted order. So for example, if I haveit the other way around three to one, andthen with this, I can sort it again. And thenit prints one, two, and three. And now let'shave a closer look at the execution of a generatorfunction again. So let's say I have anothergenerator, and I call it countdown, and ittakes a starting number. And then I say firstof all I want to print starting. And thenI say while num is larger than zero, I yield,the num. And then I also want to update thenumbers. So I say num minus equals one. Andthen I create my generator object. So I sayCD equals countdown. And for example, I wantto start at four. And now if I, let's firstof all, run this, and notice that this willnot print starting here, so nothing will beexecuted here. And now the first time, I wantto get the first value with, let's say, valueequals next of this countdown generator object.Now if I run this, then now it will startfrom the beginning of this function and executeit. So this will print starting, and thenit will run until it reaches the first yieldstatement. And here, it will return the numberand stops at this statement. So I can alsoprint the value. And then it prints four.And again, the next time, I want to continuehere with again, with this next statement,let's say print, seed print next CD, thenit will continue here, it will remember thecurrent state, so the current number is four,then it will update the number now the numbersthree, then it will continue in the whileloop. And then it stops again, at this line,and now returns three. So now if I run this,this will also print three, and then again,it remembers the state and the next time Icontinue, it will continue from here, andso on. And again, if I run this a couple oftimes. Again, if I print next, then it willalso print to and now it will also print one,and now it will raise the stop iteration.So this is the execution in detail. And nowlet's have a look at the big advantage ofgenerators. So as I said, generators are verymemory efficient. So they save a lot of memorywhen you work with large data. So what thismeans is, let's have a look at an example.Let's say I want a function, call it firstn and it takes a number as input. And thiswill return a sequence with all the numbersstarting from zero all the way up to n. Sousually what you would do is you create alist call it nums equals an empty list, thenyou also say num equals zero. So, this isyour start number and then you say while numis smaller than n nums dot append num. Soyou at the current number to a list then youupdate the current number. So you say numplus equals one and at the end, you will returnthis list. So you return nums and now I cansay for example, I can say my list equalsfirst n and give it for example 10 and thenI can simply print this so now this will printall the numbers from zero to nine in a list.And for example I can also calculate now thesum of this. So this will print 45. And nowhere with this way,all the numbersare stored in this list. So this takes a lotof memory. And now if I use a generator instead,I can say I define another function firstn underscore, Jenna rater. And now it alsotakes as input, and now I don't need the listanymore, I simply say num equals zero andalso the while loop while num is smaller thann. And here, I simply yield the current number.So I yield num. And then I also have to updatethe number. So I say num plus equals one.So this is the whole implementation of thisas a generator object. And now I can, forexample, also print the sum of this firstand Jenner Raider object. And now you seethis will give the same result. And this willalso print 45. But here, I don't have to saveall the numbers inside this array. So I cansave a lot of memory here. And for example,if I analyze this, I can import sis. And nowI can get the size of this object. So I cansee size persists precice dot get size ofthis object, this will return the size ofthis object in bytes. And again, here, I alsosay, print sis dot, get the size of this object.So first, I print the size of my list object.And then I will print the size of the generatorobject. And here we see that already, thegenerator object is smaller. And now let'ssay I don't have 10 numbers in here. But let'ssay I have 1 million numbers in here. Andthe same number of elements in here, thenthis you see, this takes way more memory.So and use cases like this, the generatorobject is very useful. So remember this. Andanother advantage of the generator objectis that we do not have to wait until all theelements have been generated before we startto use them. Because we can, for example,get the very first item with the first nextstatement. And we don't have to calculateall the numbers. Yeah, so this is the bigadvantage of generators. Now let's have alook at another example to practice the generators.A typical example is the Fibonacci sequence.So we say define feeble, not cheap. And thiswill give this will get a limit as argument.And the Fibonacci sequence works like this.So the first two numbers are zero and one,and then all the following numbers are a sumof the previous two numbers. So now, we havezero plus one is one. Now one plus one istwo, one plus two is three, and so on. Sothen we have five 813, and so on. And to implementthis as a generator, first of all, we haveto store the first two values. So we say aand b equals zero and one. And then we saywhile a is smaller than our limit, we yieldthe current value, so the current value isa and then we update the current value. Sonow we say A equals B. And also we in thesame line, we update the B value, and nowthe B value is the sum of A plus B, the sumof the previous two numbers. So we say a,b equals B, and so a is B, and B is a plusb. So this is the whole implementation ofthe Fibonacci sequence. And now we can sayfor example, fib equals Fibonacci and as alimit for example, like if it 30 and Now Ican loop over this object, I can say, fori in fib, and then print I. And now we seethis will print the sequence until, untilthis limit. And now as a last thing, let'shave a look at generator expressions. So generatorexpressions are written the same way, likelist comprehensions, but with parenthesesinstead of square brackets. And this is avery simple syntax and shortcut to generatesome generate to implement the generator expression.So I can say, my generator equals and nowI use parentheses and here I can use an expressionwith a for in loop. So I can say I, for I,in range, for example, 10. And I can alsouse an if statement, I can say, if I modeltwo equals equals zero, so this will put allthe elements all the even elements from zeroto nine in a in my generator object. And sofor example, I can print or I can loop overthis object, so I can say for i in my generator,and then print i. So this will print 0246,and eight. And this is similar to the listcomprehension. So the list comprehension worksthe same way, except that they use squarebrackets here instead of the parentheses.So I can say, my list equals this expression.And then if I print the list, this will onprint the same sequence as a list. And bythe way, I can also say I can convert a generatorobject to a list with the list function. SoI can say print list, my generator, and thiswill do the same thing. And again, let's analyzethe size of this. So let's say print sis dot,get size of this object. and here also I wantCES dot get size off this objects. And nowthey here they are almost equal. But let'ssay again, I have a large number 100,000 Thenagain, my generator object is much much smallerand saves a lot of memory. So with threadingand multi processing, you can run code inparallel and speed up your code. And in thistutorial, we will learn what is the differencebetween a process and a threat, the advantagesand disadvantages of both how and why threadsare limited by the Gil and how we can easilyuse the built in threading and multi processingmodule to create and run multiple threadsor processes. So let's start with the differencebetween a process and a threat. So a processis an instance of a program. So for example,if I'm running one Firefox browser, then thisis one process. Or if I'm running one Pythoninterpreter, then this is one process. Anda thread on the other hand is an entity withina process. So a process can have multiplethreads inside processes take advantage ofmultiple CPUs and cores. So you can executeyourcode on multiple CPUs and parallel processeshave a separate memory space. So memory isnot shared, but between processes and theyare great for CPU bound processing. So thismeans for example, if you have to, if youhave a large amount of data and have to doa lot of expensive computations for them,then with multi processing, you can proceedAs the data on different CPUs and this wayspeed up your code and new process is startedindependently started independently from otherprocesses and processes are easily interruptibleand killable. And there's one Gil for eachprocess. So this avoids the Gil limitation.And I will come to the Gil or global interpreterlock in a second. Now, there are some disadvantages.So process is heavyweight. So it takes more,it takes a lot of memory and starting a processis slower than starting a threat. And sinceprocesses have a separate memory space thatmemory sharing is not so easy. So the so calledinter process communication is more complicated.And now on the other hand, threats, so asI said, a threat is an entity within a processthat can be scheduled for execution. And it'salso known as a lightweight process. And aprocess can spawn multiple threads. So allthreads within a process share the same memory.And they are lightweight. So starting a threadis faster than starting a process. And theyare great for IO bound tasks. So this meansinput output tasks. So for example, when yourprogram has to talk to slow devices, likea hard drive or a network connection, thenwith threading, your program can use the timewaiting for these devices and then intelligentlyswitch to other threads and do the processingin the meantime. So this is how you can speedup your code with threading. But on the otherhand, threading is limited by the Gil. Sothe Gil allows only one thread at a time.So there is no actual parallel computationin multi threading. So threading has no effectfor CPU bound tasks. And they are not interoperableand kill killable. So be careful with memoryleaks here. And since threads share the samememory, you have to be careful with race conditions.And a race condition occurs where when twoor more threads want to modify the same variableat the same time. So then this can easilycause bugs or crashes. And yeah, that's thedifference between processes and threats.And now I mentioned a couple of times theGil. So let's talk about the Gil. And thisis also known as the global interpreter lock.And this is a lock in Python that allows onlyone thread at a time to execute. And thisis very controversial in the Python community.But why is it needed. And this is needed becausein C Python, so C Python is the referencePython implementation that you get when youdownload and install Python from python.org.So the gala is needed because in C Python,there is a memory management that is not threadsafe. So in C Python, there is a techniquethat is called reference counting for memorythat is used for memory management. And thismeans that objects created in Python havea reference count variable that keeps trackof the number of references that point tothe object. And when this count reaches zero,the memory occupied by the object can be released.And the problem now in multi threading isthat this reference count variable needs needsprotection from race conditions where twothreads increase or decrease the value simultaneously.So if this happens, it can either leak, itcan cause leaked memory that is never released.Or it can incorrectly release the memory whilea reference to that object still exists. Sothis is the reasonwhy they introduced the Gil. And a coupleof ways to avoid the Gil if you want to useparallel computing is to use multi processingOr you can use a different free threaded Pythonimplementation and not c Python. So there's,for example, Chai THON or iron Python. Oryou can use Python, Python as a wrapper forthird party libraries. And this is the wayit's it works in NumPy artists Sai pi modules.So they are basically just wrappers in Python,that then call code that is executed in C.So yeah, that's enough theory. And now let'sjump right into code. So let's start withmulti processing. And for this, you simplysay from multi processing, import a, the processI'm sorry. And now I create a list calledprocesses, where I will store all my processes.And now I define a number of processes. Anda good number usually is the number of CPUson your machine. So you can say import o s,and then we say num process processes equalso s dot CPU count. So on my machine, thereare four different CPUs. And then I will createthe processes, so create processes. So I willsay, for i in range, num processes, P equalsa new process. And this takes two importantarguments. Now the first one is target andthe target function. So this is a callableobject or a function that is then executedby this program process. So I have to definea function here. So I say, let's define thisup here. So let's say in this example, let'ssay their square numbers. And here, I willsay for i in range 100. I will simply sayi times i. So this is a dummy example, that'sbasically not useful, but just for how toshow you to show you how to use differentprocesses. So this is the function that myprocess should execute. So I say target equalssquare numbers. And if my function here hassome arguments, so then I would also needto specify arcs equals and then as a tuple.Give the arguments here. So in this case,I don't need them. So now I created my process.And then I say processes dot append, my process.And now I want to start each process. So Isay for p in process, and then I say P dotstart. And then I also have to join the processes.So I say for P and process, P dot join. Sothis means that I want to wait for a processto finish. And while I'm waiting, I am blockingthe main thread. So here I am waiting forall processes to finish. And I blocked themain thread until these processes are finished.So now at the end, I can for example, simplyprint and main. And I will only reach thispoint when all processes are done. And nowif I execute this, let's For example, let'salso import time and tear.Just to show you the different processes,I will wait some time and say time dot sleep0.1 and now I am having a look at the activitymanager or the task manager. So here I canfilter for processes. So I say I filter forPython. And as you can see that I've alreadytwo Python processes running, they all havea different process ID. And they all, it'salso shown how many threads are inside myprocess. So now if I'm executing this Pythonfile, then we will see what will happen. Soit takes a couple of seconds. And now we seefive Python processes coming up. So this isthe main process, and then the four processprocesses I created here. And now after acouple of times, after this is finished, theywill disappear again. So we can see that thereare actually different processes now runningon my machine. And this is how we can usemulti processing. And now let's talk aboutmulti threading. So the threading API is verysimilar to the previous multi processing IPAAPI. So here, I say from threading, importthreat. And then here, let's call these threats,and num. Now I call this number of threats.And let's simply say I want to have 10 differentthreats. And then for i in num threats, nowI create a threat. And this takes the samearguments. So it also has to define a target.And if my target has some arguments, thenI would also have to specify the arcs here.And then I say, threats dot append my threat,then I will start each threat. So I will sayfor t in threats, T dot start and also jointhem. So I will say for T and threats, T dotjoin. And now let's have a look at the activitymanager again. Now if I'm running this Pythonfile, then we will see takes a couple of seconds.Now we will see one process coming up with11 threads inside so the main threads andthe 10 child threads that I created here.And now processing is finished and the threadsdisappear again. So this is how you can usethe threading module.In this video, we will go into more detailabout the threading module. So we will quicklyrecap how we can create and start multiplethreads, then we will learn how we can sharedata between threads and how to use locksto prevent race conditions. We will also learnwhat is a daemon process and how we can usea queue for thread safe data exchanges. Solet's start and let's quickly recap from thelast video how we create and start threats.So this is the code where we left off. Sowe say from threading import threat. And downhere we define a num so we want 10 threatshere. And now we create our threats. And foreach threat, we give them a target method.So this is the function that the Stan executedby this threat. And then for each threat,we also have to say thread dot start. Andalso threat dot join. So join means that wewait and block the main threat until the threatis complete. So yeah, this is how we can canuse the threading module. And now let's gointo more detail. And let's talk about howwe can share data between threats. So sincethreads live in the same memory space, theyhave access to the same data. So this makessharing data very easy. So we can for example,just use a global variable here. So let'sdefine a global variable. And in this case,I will call this database value. So and Iwill set this to zero in the beginning, sothis should simulate a database now And nowin our main code, what we will do is, we willfirst of all we print, print the start value.So we print our database value here. And thenwe will create two threats. So let's say threatone equals threat. And this will get a targetmethod that we will call increase, and alsothreat a second threat. So threat to thatdoes the same thing. And then for each threat,we say threat start. And also, threat join.So we wait for the threads to complete. Sothread two dot join. And at the end, we printthe end value. And then we again, want toprint a database value at the end. So andnow we have to define this increase methods.So we say define increase in here, we wantto get and modify our database values. Soin order to modify the global variable, wehave to say global database value. And nowwe can use it here. And now let's make somedummy code. So we want to simulate some databaseaccess, we want to get the value from thedatabase and store it in a local copy. Sowe say local copy, equals and here, we cansimply copy it from our database value. Andthen we want to do some processing. So here,we simply say, local copy plus equals one,so we want to increase it. And then we simulatethat this should processing should take sometime. So we import time. And then we waitsome time here. So we say time dot sleep 0.1.And then when we are done, we want to writeour new value back into our database. So wesimply copy it back and say database valueequals local copy. So this is our increasefunction. And now let's run this. So now wehave two threats.And if we run this, let's clear our console.And let's run this again. So we he sees startvalue is zero, and end value is one. So nowyou might be wondering, why is this one becausewe have two threats. And both threats shouldincrease our database value. So now the endvalue should actually be two. And now whyis it one and this is because we have a racecondition here. So a race condition happenswhen two or more threads try to try to modifythe same variable at the same time. And nowlet's step through this code what is happeninghere. So when we say thread one dot start,then it will get the database value and storeit in a local copy. So in the beginning, thisis zero, and then we will modify the localcopies. So now our local copy is one. Andnow since we say time dot sleep, our programcan intelligently switch to the other threadsand use the waiting time. So now it switchesto threat number two. And now thread numbertwo invokes this increase method. So it alsocopies the database value in the local copy.And the local and the database value is stillzero because we didn't write it back here.So now thread two also has a local copy, whichis zero and then it increases it's to oneand then we again say time that sleep so wecan switch back to threat number one. Andnow threat number one copies it's it's a Copythat is one into our database, and then it'sdone. And then we are switched back to threadtwo again. And that now also copies its localcopy that is also one here into the databasevalue. So this is why the end value is one.And now how can we prevent this. So for this,we use the lock object. So we say from threading,import, lock, and then we create a lock here.So we say lock, dot lock equals lock. Andnow we say our increase method gets a lock.So we have to give this year in the arguments.So we say arcs equals lock. And since thisis a tuple, with only one element, we alsoneed a comma here. So Python needs this commahere in order to know that this should bea tuple. And also, for our second threat,this will now get the lock as an argument.And now with a lock, we can so a lock preventsanother threat to access this to access thiscode part at the same time. So now we cansay lock dot acquire. So it basically hastwo, only two methods. So we say lock dotacquire. And now we can process and modifythe value. And at the end, when we are done,we say lock dot release. So and we shouldalways, every time we acquire a lock, we alwayshave to release it. So Otherwise, this willblock and never release. So then we are stuckhere. And now what is happening with thislock. So now our let's run this and see ifthis works.Lock dot acquire. So Oh sorry. This is a lockobject. So now let's run this. And now wesee that it's correct, our end value is two.So what happened here, so now our first threatgot here. And since it locked the state, nowit can modify the value. And it will not switchback to our threat number two here, becauseit's the state is locked. So it can countit continues and runs and copies the localcopy that is now one into our database, andthen it releases the lock. So now our secondthreat can enter this code part. So it alsogets the database value. And this is now alreadyone and then it modifies it to two and writesit back. So now this is working fine. Andas I said, you should never forget to lockto say lock dot release. So there's a recommendedway to use locks. And this is to use a lockas a context manager. So you can simply saywith lock colon, and then use the part ofthe code here. And then we don't need to saylock that release. So let's also get rid ofthis. So if we run this, then we see thisalso works correctly. So this context manageracquires and releases the lock for you. Soyeah, this is the concept of locks. And nowlet's talk about how we can use queues inPython. So queues are excellent for threadsafe and process safe data exchanges and dataprocessing in multi threaded or multi processingenvironments. And for this, we simply we haveto import the queue so we say from queue importqueue. And now let's get rid of this. Andfirst let's have a look at how a queue isworking. So a queue is a linear data structurethat follows the feefo or First In First Outprinciple. So a good example of a queue isa queue of customers that are waiting in linewhere the customer that came first is alsoserved first. So, let's create a queue object.So we say q equals Q, and then we can putin some elements. So we say q dot put one,and Q dot put to two. And also, let's putin us a third object, so say q dot put three.And now our code looks like this. So first,the one is, enters our Q, then we put in thetwo, and then we put in the three. And here,this is our front. So the beginning of thequeue. So now if we want to get the firstvalue, we can do this by saying first equalsq dot get. So this will get and remove thefirst item. So if we print first, then thiswill print one. And now our thread, our queueonly has three and two inside. So this ishow the queue principle is working. And thereare a couple of otherimportant methods. So first, you can checkif a queue is empty with Q dot empty, thiswill return true if the queue is empty. Andthen in a threat threading environment, wheneveryou get a object with queue dot get, and thenyou process this object. When you are doneprocessing, you should always call queue dottask done. So this now tells the program thatwe are done processing with this object andcan't can can't, can continue. And there'salso a Q dot join method. So this blocks untilall items in the queue have been gotten andprocessed. And this is similar to the threaddot join methods. So with this, we block themain thread and wait until all the elementsin our queue are processed. So these are thethe important methods you have to know. Andnow let's look at an example to how we canuse this. So we say Um, also, we want to definea couple of threats. So we say num threatsequals 10. And then we say for i in range,num threats. And here we create our threat.So now we say threat equals threat. And asa target, it needs to get a function. So wewill define this in a second. And then wesay thread dot start. And we will also nowuse a demon threat. So we say threat dot demonequals true. And I will explain what thiswill do in a second. So by default, it isnot a daemon thread. And then let's defineour function. So our function, let's callthem worker, and define this worker functionup here. So we say def worker. And now weuse an infinite loop. So we say while true,and then we say value equals q dot get. Sothis will get two arguments, this will getthe queue and also a lock. And here, we willget the first value inside our queue withQ dot get and then we will do some processingwith it. So in this case, we simply want toprint the values so we say print and let'simport the current so let's say from threadingimport current threads, so we want to printthis here. Let's use an F strings so we cansay we are in and then we are in our currentthreat dot name. And in this threat we gotthe value. So we simply want to print thishere. And then we are done. Remember, we haveto say q dot task done. And now what thisis doing, this is an infinite loop that isnow starting. And since we don't have valuesinside our queue, this Q get method will blockand wait until items are available. So nowwe wait here, so we have to fill our queuewith elements. So we simply say for i in range,let's say one to 21. So we want to fill thiswith all the numbers from one to 20. And wesay q dot put AI. And then at the end, wehave to say q dot join. So we block the mainthread and want to wait until all the itemshave been gotten and processed. And yeah,then we print and main. And now let's runthis code and see what's happening here. Andhere, we also have to, now this worker getsno, let's leave this lock, and only gave ita cue. And now as arguments, we have to giveit in a tuple. Again, we give it the cue anddon't forget the comma here with one item.And now let's run this and see what's happening.And nowwe see that we have threads with differentnames from one to 10. So we have 10 differentthreads. And they get the values from ourqueue and can process the item here. And theorder might not be sequential. But what isimportant here is that with a queue, we caneasily exchange the data in a thread safeenvironment. So this value, this queue getscall is thread safe. And also the queue putcalls are thread safe, so no other threadcan write at the same time into this queueposition. And now let's run this again. Soin this time, we, this time, we got lucky,and we got lucky again. So what might happenhere is that multiple threats might try toprint at the same time. So there might beprint statements that are in the same line.So two statements in the same line and noline break. So to make it work correctly withwe should say with lock and use a lock here.So let's also give this a lock. Let's saydown here, lock equals lock. And then as argument,it also gets the lock. And now this shouldwork fine and never produce confused lockstatements. And yeah, let's have a look atwhat is happening here again, and why we usea demon threat. So we are our threats, enteredthis infinite loop. And then it blocks herebecause we have no items inside our queue.And then as soon as items are available, thenit can continue here and process the items.So in this case just prints it and then afterall the items are done, we can continue herethen this will unblock and then we will continueand print n main and then we will leave themain threat. And now a demon threat is a background threat that will die when the mainthread dies. So you might be wondering, wehave an infinite loop here. Why do we Whydoes our program correctly stop so we sayand main and then it's it's done and I canuse my command line here again. So a daemonthread dies when the main thread dies. Soif I reach this statement and then exit themain thread, then all the threads die. Andso the worker method and the wild true loopno longer gets invoked. And this is why weuse a demon threat here. So by default, thisis false. And if we don't use a demon threathere, then our program will still continuehere in our wild true loop. So, what we shoulddo then is we should use another mechanism,for example, some some signaling mechanismlike an event to say that now we are doneand we can exit the wild true loop. So thenwe should have used here, if some conditionand then break. So yeah.In this video, we will go into more detailabout the multi processing module. So we willquickly recap how we can create and startmultiple processes. Then we will learn howwe can share data between processes, and wewill recap how to use locks to prevent raceconditions and how to use queues. And at theend, we will learn how to use a process poolto easily manage multiple processes. So let'sstart and let's quickly recap from the lastvideo how to create and start processes. Sowe say from multi processing import process.And then down here we define a number of processes.So a typical good choice for this is the numberof processes on your machine. And you getthis with Oh s dot CPU count. And then youcreate your different processes with processequals process. And this takes a target isa function argument and the target is a callablefunction. This is that this then executedby this process. So we define a function appear,this simply squares, some numbers. And thenwe give this to our process here. And thenfor each process, we call process dot start.And also process dot join. So this says saysthat we want to wait for all processes tofinish and block the main program until allthese processes are done. So this is all weneed to set up multi processing. And now let'sgo into more detail. And first, let's talkabout how we can share data between processes.So in the last video with multi threading,we learned that we can easily share data betweenthreads with a global variable. And now withprocesses, processes don't live in the samememory space, so they don't have access tothe same public data. And because of that,they need special shared memory objects toshare data. And there are two shared memoryobjects that we can use, we can use a valuefor a single value, or we can use an array.So we say from multi processing, import valueand import array. And down here, let's firststart with a single shared values. So we sayshared number. And this is now a value. Andthis takes two arguments. First, we have togive it the data type as a string, so we giveit an i for integer and a starting value.This is no cirro. And first of all printersso we say number at the beginning is and thenwe say we access this shared number with orthis value with share number dot value. Sonow if we run this, and we see that this iszero, and now let's create two processes thatshould modify this number. So we say processone equals process. And as a target, it getsa function that we call at 100. So let's definethis up here. So let's define adds 100 andthis gets a number and then it should modifythis number a couple of times. So we say fori in range 100. So 100 times it should saynumber though value plus equals one. So itshould increase this by one. And we also wantto modify a behavior that takes some time.So we say, time dot sleep and 0.01. And sohere we give it this at 100 to our process,and it also needs arguments. So we say artequals, and this is a tuple. So here, we giveit this shared number. And be careful. Sincethis is a tuple, with one element, it alsoneeds a comma here so that Python knows thatthis is a tuple. And then we create a secondprocess that will do the same thing. So processtwo, that should add 100 to our shared variable.And then we say process, one dot start, andprocess two dot start. And then we wait forthem to complete. So process one dot join,and process to the chain. And now at the end,we again, print our numbers. So we say numberat end is and then access it with share numberdot value. So let's execute this and see whathappens. So the beginning is 100. It's zero.And now we got lucky. Now let's run this asecond time. And now it's not 200. So it'sonly 168. And why is that because here a racecondition happened. And I will not explainthis in details, please have a look at theprevious video. There I explained in detailhow race conditions occur. So a race conditionoccurs when twothreadsor processes try to access and modify thesame shared variable at the same time. Soin this case, both processes try to read andwrite into this object at the same time. Sosome operations might get lost here. So inthis case, it's only 168. And to prevent this,we must use a lock. So we say from multi processing,import lock. And I also talked about thisin the last video, so please check this out.So a lock prevents another process from accessingthis at the same time. So to use this, wecreate a lock object, so we say lock equalslock. And then we give this to our functionto function. Yes. So this now also takes alock. And a lock has two important methods.So first, we say lock dot acquire. And thenat the end, we say lock dot release. So assoon as we say lock dot acquire, it will setthis in a locked state. So this means thatwhile this is running, no other process hasaccess to this code and can execute this parthere. And then when we unlocked the state,again, with lock that released and the secondprocess can also execute this. So this isall we need to prevent multiple process tomodify this at the same time. So now let'srun this. And now we get 200. Let's run thisagain. And yeah, still working. And a betterway to use locks is to use locks as a contextmanager. So whenever you say lock acquire,you always have to call locked release, thenat the end, otherwise, this will block andyour program cannot continue. So don't forgetthis. And you can use a lock as a contextmanager. So we say with lock, colon, and thenyour code. So this automatically will acquireand release this for you. So yeah, this alsoworks. And now this is how we can share asingle value. And now let's share a array.So we say shared array equals array, and thisalso needs a data type. So in this case, that'sgiven a D for double And here given a listas initial values, so we say, put in 0.0,here, 100.0, and 200.0. And then we say ourarray, at the beginning is, and let's sayshared array. And then we have to access eachelement with inside brackets and then withthe index. And we can also use slicing hereto access all in the indices. So let's justput in a colon here, and then again, printthis at the end. So at the end, we want toprint our array. So array, at the end, isthis. And now we have to change our functions,this now takes multiple elements. So thistakes numbers. And then we have to go overeach number here and increase it. So firstof all, let's also change this parameter here.So let's say shared array. And now, in our,in our function, what we want to do is wewant to go over each number and increase it.But be careful here. So we cannot say fornumber in numbers, and then simply say numberplus equals one. So now if we run this, thiswill print our error at the beginning andat the end, and this is still the same. Andthis is because this loop here will createa local variable called number that is thenincreased. So this has nothing to do withour shared value object. So in order to dothis, we have to say for, and let's say fori in range, and then the range has the lengthof our array. And then we access each elementwith numbers, dot i, and save plus equalsone. And now let's run this. And now we seethat it got modified. But we also have raceconditions here. So don't forget the lock.So we say withlock, and then our modification operation.And now we increased each element in our arrayby 200. So this is how we can use the sharedvalue and shared array. And we can also usea queue to exchange elements between processes.And I also already showed this in the lastvideo. So a queue can be used for processsafe data exchanges. And so in the last video,we set from Q, import Q. And there, we haveto use a slightly drif different queue thatwas formed from the multi processing module.So this has all the same methods except thethe tasks done and the tasks and the joinmethod. So a queue is a linear data structurethat follows the first in first out principle.So the first element that you put into yourqueue, that is then also the first elementthat gets retrieved when you want to get elements.So let's make an example to use a queue andexchange data between multiple processes.So in this case, let's say q equals Q, andthen create two processes that should do shouldaccess and write to this queue. So we havea process that gets as a targets, it getsa function that we call square. And as arcsit gets some numbers and our queue and thenwe curate a second process that has In a seconddifferent function here, so we call this makenegative, and it has the same arguments. Soit will write to the same queue. And now let'sdefine our functions here. So we say thatf square, and this will get some numbers,and Q. And then we say, so in this case, fori in numbers, we calculate the square andput it into our Q with Q dot put i times i,and then a second function make negative.And there we also it also takes some numbersand a Q. And here, we also go over our numbersfor i in numbers, and then we say q dot putminus one times i. And then let's say, let'sstart our processes. So pros, one dot start,and process two dot start, and then processone dot shine, and process two that shine.And here, we don't have to call q dot join,because there is no methods cue that join.But what we can do is we say while our queueis not empty, so while not Q dot empty, andthen we want to print each element. So printq dot get. So this will return and also removethe first element in our queue. And yeah,now let's run this and see what happens. numbersis not defined, oh, sorry, I have to createa numbers variable. And I will say this isa range object from one to five. So or fiveshould be included. So I say from one to six.And now this will print each element. Andwe see that both processes have access tothis queue and can writeput elements into it. And then in our mainprocess, we can also access the queue andget the elements back. So this is how we cana can use a queue. And now as a last thing,let's talk about a process pool. So a processpool can be used to manage multiple processes.So a process pool object controls a pool ofworker processes to which chops can be submitted.And it can manage the available processesfor you and split, for example, data intosmaller chunks, which can then be processedin parallel by different processes. So let'shave an example how this works. Basically,a pool takes care of a lot of things for you.So you don't have to consider a lot. So wesimply say from processing, importpool.And then down here, we create a pool. Andwe say, so we say pool equals pool, and thenit has two or four, let's say it has fourimportant methods that you have to know. Andfor the rest, I would recommend to have alook at the documentation because there area lot of more methods but the most importantones are map, apply, join and close. So whatwe want to do is we want to create multipleprocess that should access a or execute afunction. So we call define a function cube.And this takes a number and returns the cube.So it will will return number times numbertimes number. And now here we can simply sayor we create some numbers. So numbers equalsa range object from zero to 10 or 10 or onlyto nine. And then we say, pool dot map. Andnow we map we have to give it a function,so we give it the cube, and the numbers. Andthis will return a result that we can thenprint. So print our result. But first of allwe have to, so this will, what this will dothis will automatically allocate them themaximum number of available processes foryou and create different processes. So typically,this we'll create as many processes as youhave cores on your machine. And then it willsplit this iterable into an equal into equalsized chunks, and submit this to this function.And this function is now executed in parallelby different processes, or by different processes.So this is all you need to write and thenthe pool will take care of the rest. So thiswill allocate the pools, it will split thedata and then run this method in parallel.And when it is done, it will return the result.And we have to call pool dot close. And thenwe can call pool the join. So this means thatwe want to wait for the pool to process allthe calculations and return the results. Andwe have to remember that we should call poolthat close before. So now if we run this,we can print our result and we can see thatit has the cube here. So yeah, this is howwe can easily use thethe poolto run different processes with a function.And if we simply want to have one functionexecuted by a pool, then we can say pool dotapply. And then also the cube. And then inthis case, it will only has one number year.So we can for example say Apply numbers, thefirst element.Sonumber zero, so this will execute a processwith this function with one argument. Andyeah, so this is the most important thingsabout pools. And there are also asynchronouscalls to this map and apply functions, butI will not cover them here. First of all,we will learn what is the difference betweenfunction arguments and function parameters.Then we will talk about positional and keywordarguments, then about default arguments andvariable length arguments. So what are thearcs and quarks arguments for then we willtalk about container unpacking, we will alsotalk about the difference between global andlocal arguments inside of functions. And finally,we will have a look at how arguments are passedto functions and if they can be modified withina function. So let's start and let's quicklytalk about the difference between our argumentsand parameters. So parameters are the variablesthat are defined or used inside parentheseswhere defining a function. And arguments arethe values passed for these parameters whilecalling a function. So let's make an example.Let's say we have a function called printname, and it gets a name. And then we simplyprint this name, then this name here is ourparameter. And when we call this function,let's call print name with a string LX. Thenthis is the argument for this function. Sothere is a difference when we talk about them.Now let's talk about positional and keywordarguments. So we can pass arguments as positionalor keyword arguments. And let's make anotherfunction as an example. So let's say we havea function foo, that has three parametersA, B, and C. And we simply want to print themPrint A, B, C, then we will call this functionwith positional arguments. So we can say foo,and then just one, two, or three. So thiswill print 123. Or we can also use keywordarguments. So we say A equals one, b equalstwo, and C equals three. So this will alsowork. And note that if we use keyword arguments,then the order is not important. So I cansay, for example, C is one, and a is three,and a is the first one that is printed. Solet's see what happens. So it prints 321,and not 123. Like I like the orders here.So when using keyword arguments, then onlythe keywords matter and not the position.We can also use a mix of both. So I can usea positional argument first, that's a oneand then I can use keyword arguments. So bequals two, and C equals three. So this willalso work. But I cannot use another positionalargument after a keyword argument. So if Itry to call it like this, then this will raisean error. And also, if I try to assign a aagain, so A is the first positional argument.And now if I use a as keyword argument, thenthis will also raise an error. So yeah, that'sthe difference between positional and keywordarguments. And yes, sometimes it's betterto use keyword arguments, because it makesit more clear what they present. Or we canrearrange the arguments in a way that makesthe most readable. So yeah, then we have thepossibility to add default arguments. So Ican say D and give them give this parametera default value. So let's say d equals four.And now if I, I can call this fool, and justwith three arguments now, one, two, and three.And let's also print D here. So if I ran itlike this, then it will take the default valuefor D. And I don't need it here. But I canalso give it a different value. So I can say,seven here. So this will print 1237. Yeah,so default arguments must be at the end ofyour function parameters. So for example,if I have one here, b equals two, and I tryto run this, then this will give an error.And now let's talk about variable length arguments.So probably, you've also already seen functionsthat looked like this. So they have some parametersA B, and then have at this star, and arcsargument, and sometimes also with with doublestars and quarks. And now what these are,so this is a function. If you mark a parameterwith one asterisk, or one star, then you canpass any number of positional arguments toyour function. And if you mark your parameterwith two stars, then you can pass any numberof keyword arguments to this function. Andtypically they are called arcs and quarks,but you can call them whatever you like. Soalso, for example, C. So inside this function,let's print a and b first, and then this isa tuple inside your function. So we can goover this tuple and say for arc in arcs, andthen print arc. And the quarks argument isa dictionary so I can say For key in quarks,and then I want to print the key and the valueof this dictionary entry. So I say quarkskey. And now I can call this function. Forexample, at least it needs the two argumentsA and B. So I can say, one and two. But thenI can also use as many positional argumentsas I want. So I say, maybe 345. And then Ican use some keyword arguments. So I can,for example, say six equals six, and seven,equals seven. And now let's run this. Andlet's see what it prints. So first, it printsthe two positional arguments one and two,then it goes over our, our arcs. So this is345. So it prints each number in a differentin a new line, and then it goes over the keywordarguments and prints the keywords and thevalue. So this is how we can use variablelength arguments. And for example, I don'tneed them. So I can also simply use keywordarguments here. Or I can use some more positionalarguments and don't use the keyword arguments.Sorry. So this is also possible. Now, let'stalk about force keyword arguments. So sometimesyou want to have keyword only arguments, andyou can force enforce that. So you can, forexample, give a write a star here, and thensome more arguments after this. So let's sayC, and D. And then I want to print them here,print ABCD. And now everyparameter after this star must be a keywordargument. So if I write it, like call it likethis, then these are positional arguments.And then this will raise an error. So I haveto say C equals three and D equals four. Andthen it works. Or, if you, for example, usethe arcs variable here. And then each parameterafter that is also a keyword only parameters.So let's say C, and D, and then simply printthe last two. So if I write it like this,or for example, to make this more clear, let'scall this last. And then for arc, in arcs,print, arc, and then print. Last. So if Icaught it like this, then it's missing, thensees this parameter only as your arcs. Andthen it says that the last keyword parameteris missing. So I need another one. And nowI needed as keyword arguments. So I say lastequals 100. And then it's working. So thisis how you can enforce to have keyword onlyarguments. Now let's talk about unpackingarguments. So if we have a function, let'ssay again, fool with three arguments, A, B,C, and we simply print them a, b, and c. Nowlet's say we have a list, my list equals 1012.Here, then we can easily unpack this listinto our function in a function in the functioncall. Have this list unpacked into the arguments.So I can say, star and then my list. So thiswill unpack the first item into a second intoB and the third into C. And this also workswith a tuple here, so I can have a tuple.Here. The only thing is that is importantis that the length of your container mustmatch the number of parameters here. So forexample, if I have another item here, thenthis won't work. Now if I have a dictionary,so let's say my dict equals, and then the,it must have the keys with the same namesas your parameter names here. So a, and thensome well you want, then the second B, andsome well you and also see. And some wellyou then I can unpack a dictionary with twostars here. So I say two stars, and then mydict. And then this will also work. But here,also, the length of this dictionary must matchthe number of parameters here. And also, thekeys must match the name the parameter nameshere. So for example, if I use e here, thenthis will also raise a type error. So yeah,this is how we can quickly unpack a dictionaryor a list into our function arguments. Andnow, let's talk about local versus globalvariables.So let's say we have a function. Again, foo.And this now First, let's say we have a globalvariable somewhere. So we call this numberand say, the number is zero. And then inside,we create a local variable x and access thisallow a global variable, so we can say x equalsnumber, and then let's print let's say numberinside function, and then print x. So andthen we can call this. So let's call foo,then this will print the number inside thefunction, so we can access this number here.But if we want to modify it, so let's saynumber equals three, then what will happen,then this will raise a, a arrow here, becausethen what this will do here, this will createa local variable that is nowdifferent than this global variable. So ifyou want to modify this, then we first haveto say, global number, and this is the nameof this global variable. And then we can saynumber equals three. So this will work. Sonow if we print the number after our functioncall, then this will print the new value three.And if we now what will happen if we don'twrite this global here, and we don't havethis and simply assign number two three. Thennow what will happen if we run this now thisx is not available anymore. So let's run this.So this will Print zero, it prints the numberthat is still zero even after the functioncall where we set number equals three. Andthis is because here, we create a new localvariable. So this has nothing to do with thisglobal variable. And this is the, this onlylifts inside your function. And it will notmodify your global variable. So if you wantto modify the global one, then you have towrite global number here. And now it willprint three. Yeah, so this is the differencebetween local and global variables. Now let'stalk about parameter passing. So maybe you'veheard already of the term, call by value orcall by reference. And in Python, it's a littlebit different. So it uses a mechanism, whichis known as call by object or call by objectreference. And there are two rules that mustbe considered. So parameters are passed arethe parameters passed in?No, sorry, the parameter passed in is actuallya reference to an object, but the referenceis passed by value. And there is a differencebetween mutable and immutable data types.So this might be a little bit confusing. Butthis basically means that mutable objectslike lists or dictionaries can be changedwithin a method. But if you rebind, the referencein the method, then the outer reference willstill point to the original object and isnot changed. And immutable objects like integersor strings cannot be changed within a method.But immutable objects contained within a mutableobject can be reassigned within a method.So let's look at some examples to make thisclearer. So let's say we have a function foo.And this takes an argument x, and then itreassigns. This so it says x equals five.And now let's say we have a bar equals 10.So this is an integer, and then we call foowith this bar. And after this, we want toprint all of our now this will still print10, even if we assign X to five here. So becausewhat happens here that var is an integer,and this is an immutable, immutable type,so it cannot be changed. And that this willcreate a local variable called x here, thathas nothing to do with this. So this is thesame with the global and local variable difference.But yeah, so immutable objects cannot be changed,but mutable objects can be so let's say thiswill get a list. And then we can modify thislist. So we can say a list dot append an item,so let's append four, and let's create mylist. And this is, has three elements one,two, and three. And then we passed this listand then call this function with the listand then afterwards, print the list. So thenwe see the list got modified. So immutableobjects can be modified within a function.And also immutable objects within a mutableobject can be changed, so that immutable integerswithin this list can be changed. So I canfor example, also say, list and access thefirst index, so index zero, and this is nowlet's say minus one 100. So this will alsochange the global list here. And but whatis what is not possible so if we rebind amutable reference here. So if I say for example,first if I say, a list equals, and then let'ssay 200 300 400. And now I call, I createmy global list here, I call this function,and then I print it, and it will still printthe original list 123. And this is becauseI rebind, the reference here. So this is nowa local variable, a list with this new waysand new values. So this has nothing to doagain with the global variable. So yeah, maybenow the four points are more clearer. So again,mutable objects can be changed. immutableobjects cannot be changed. But immutable objectscontained within a mutable objects can bechanged. And like here, if we rebind, thereference in the method, then the altar referencewill not be changed. And let's have a lastvery quick difference thathow this can affect your list. So first, ifwe say, a list, instead of writing appenditems, we can, for example, say plus equalsand then a new list. So if I write it likethis, and now if I run this, then my outerlist here, my global list, got affected bythis. But now if I say a list equals a list,plus this, then if I run this, then this willnot change the original list. So this is aslight difference, but it can have a big effect.Because here again, this will create a localvariable. So be careful with this slight difference.So plus equals, again, will change the list.So in this tutorial, we will talk about thedifferent use cases of the asterisk or starsign in Python. So it can be used for multipledifferent cases like multiplication and poweroperations, the creation of lists or tuples,with repeated elements, for arts quarks, andkeyword only parameters for unpacking liststuples, or dictionaries into function arguments,for unpacking containers, and for mergingcontainers into a list or merging two dictionaries.So we will have a look at all of these usecases. First of all, of course, there is thesimple multiplication operation. So let'ssay result equals five times seven. And thenif I print the result, then this will printthe multiplication of these two. Or if I usetwo stars, or two asterisks, let's say two,and then two stars and then a four, this willbe a power operation. So this is two to thepower of four equals 16. This is one use case,then it can be used to create lists tuples,or strings with repeated elements. So let'ssay I want to have a list called Ciro's equals,and then I write one element. So I say, oneitem here, so zero, and then I write times10. So this will create a list with 10 elements,and each element has a zero. So this is mylist. I can also put in multiple initial itemshere. So if I write it like this, then thiswill repeat zero and 110 times. I can alsouse a tuple here. And it also works with strings.So if I say, let's say a B here, then thiswill create a new string with 10 times A BSo next is to use the star or asterisk forthe arcs and quarks and keyword only arguments.So if you don't know what this means, pleasewatch my last video about function arguments.So probably you've seen a function that lookslike this. So that define a function calledfoo. And then it has some arguments. And thenalso some arcs with one star, and with quarkswith two stars. So and then let's print A,and now arcs is a tuple. So I can go overthis tuple for arc, in arcs, and then printarc. And quarks here is a dictionary. So Ican say four key in quarks, and then printthe key and also the dictionary value of thiskey.And now, I can call this function with theA and B arguments. So let's say one and two.And then for this arcs, I can use as manypositional arguments as I like, so I can say345. And then I can also use as many keywordarguments as I want. So I can say, for example,six equals six, and seven, equals seven. Sothis will print my function here. Um, forgotthe beat here. And then if I only use onestar here, and then another parameter here,then all parameters after this star are keywordonly parameters. So if I want to print C,I cannot call call the function like this.So because here, the last item must be a keywordargument, so I have to write C equals three,and then it will work. So this is anotheruse case of the star operator to enforce keywordonly arguments. Then we can also use the asteriskfor argument unpacking. So let's say I havea list, my list equals and it has three elements.So 012, then I can call this function andunpack this list here with one star, and thenmy list. So this will work. And the only thingthat is important here is this is that thenumber of arguments must match thenumber of parameters here, the number of elementsin the list must match the number of RF parametershere. So if I have another one, then thiswill raise an error. And this will also workwith a tuple. And if I have a dictionary,so let's say my dict. And then this must havethe parameter names as keys, so a and thena value, one, B, and the value, and C andthe value, then I can unpack this dictionarywith two stars, and then my dict. So thiswill work. And also the number of elementsmust match the number of parameters here,and also the key, the keys, the name of thekeys must match the name of the parameters.So if I have a different key here, then thiswon't work. Then the asterisk can be usedfor unpacking containers, so it can unpackthe elements of a list tuple or steps intosingle and multiple remaining elements. Solet's say I have a list called numbers andThis is, let's say 123456, then I can unpackthem, let's say I write, star and then beginningand then a last value. And this is equal numbers.So let's print beginning. And let's printlast. So this will unpack all the elementsexcept the last one into a list, and thenit will unpack the last item into a singlenumber. And, yeah, be careful here, this willalways unpack your elements into a list. Soif I have a tuple, here, then unpacking works,but it will still be a list here. So if Irun this, and it looks like this, I can alsounpack the, or put the star sign for the lastitem. So this will unpack the first numberinto the first element into one number andall the remaining elements into a list thatis now called last. Or I can use this in themiddle, so I can say beginning and then star,middle, and then last. So and then I can printthe middle here. So now middle is my listwith the elements between so if I run this,it will print this. And for example, I canalso unpack more numbers into single element.So I can say second, last, and then here print.Second, last. So this is how we can unpackmultiple items into a list. And we can alsouse the star operator to merge iterables intoa list.So for example, if I have one tuple with elements,one, two, and three, and then I have anotherlist, so my list equals 456. And then I cansay second, or let's say, new list, equalsand then I say I, in brackets, I put my firstiterable here, so I can saystar, and then my tuple. And then I can putin the second iterable here, so my list. Soif I print the new list, then this will bea new match list. And I can also use a sethere. So if I use a set, here, my set, thenthis will also work. So this merging, worksfor lists tuples and sets into a list. OrI can merge two dictionaries. So if I haveone dictionary, call it dict, a equals andthen some elements here. So let's say a andone, and B and two, and then I have a seconddictionary, so let's say dict b, this hasthe keys C and D with the values three andfour. And then I can create another dictionary.So let's say my dict equals and then insidethese square brackets, I use two stars andthen the first dictionary and then comma andthen again two stars to unpacked this Seconddictionary. So this will merge multiple dictionariesinto one dictionary. Now if I print this,then I can see that I have one dictionarynow. And yeah, I think that's all the importantuse cases of the asterisk sign. This tutorial,we will talk about copying. So we will learnhow we can copy mutable elements with a builtin copy module, and the difference betweenshallow and deep copies. And we will alsohave a look at how to make actual copies ofcustom objects. So let's start. And firstof all, let's have a look at the assignmentoperator. So let's say we have a variablecalled orc, and this is now a number. Andnow if we want to make a copy with an assignment,so we say copy equals original, then thiswill not make a real copy, it will only createa new variable with the same reference. Sonow both variables point to the same number.And now for immutable types like this integer,this is not a problem. So let's say if wechange the copy, and say copy equals six,then this assignment will again, create anew variable. So they they are now both independent.So if we print the copy, and if we print theoriginal, they are different. But when wedeal with mutable types, so for example, alist then we have to be careful. So let'ssay we have a list here with some elements.So let's say 01234. And now we make a copywith this assignment operator. And then ifwe change elements of our copies, so let'ssay we want to change the first item and saythis is now minus 10. And now if you printboth the copy and the original, we see thatalso the original has the value minus 10.Here, and this is because this assignmentoperator doesn't make an actual copy. So tomake an actual copy, we can use the builtin a copy module, so we can say import, copy.And then we have to make a difference betweenshallow and deep copying. So a shallow copyis only one level deep. So at the first level,it makes an actual copy. But then it onlycopies references of the nested child objects.And then there's the deep copy. So this willbe an a full independent copy. So let's startwith an with a shallow copy. So to make ashallow copy, we can say copy equals, copythat copy, and then the original.And now if we print both, we see that theoriginal didn't get affected. So only thecopy here has minus 10. And, for example,with a list, there are several different optionsto make shallow copies. So we can also saycopy equals original dot copy. So this willalso work. Or we can use the list functionand give it the original as an argument. Thisis also possible. Or we can use list slicing,so we can say pork, and then the slicing operator.So this will simply be from start to end.So this will copy all elements. And this willalso make an actual copy or a shallow copy.So this works fine if our element is onlyone level deep. And now let's say we havea nest or nested lists. So let's say we havea first lists here, a list inside a list andthen a second list here. So with some moreelements, three, so this is our original list.And now we make a shallow copy. And now wechange an object or an item that is at thesecond level. So we say copy at index zero,so in this list, and then again at index zero,so this element, or for another example, let'smake index one here, so this is this element.And now this we want to set to minus 10. Andnow let's see what happens. So if we run this,we see that both the copy and the originalnow have minus 10. Here. And this is becausea shallow copy is only one level deep. Soto make an actual copy in all the levels,we have to make a deep copy. So we can saycopy dot, deep copy. And now if we run this,we see that the original didn't get affected.So this is the difference between shallowand deep copying. And for the built in types,like lists, dictionaries, or tuples, we canuse these methods. But we can also use itfor custom objects. So let's say we have acustom class and call it person. And now inthe in it, it gets self Of course, and thenit gets a name and an age. And then we sayself dot name equals name, and self dot age,equals age. And now let's create two personsperson one equals person. And now as the nameit gets LX, and as an age, let's say 27. Andnow let's make a copy, simply by assigningit, so let's say person two equals personone. And now if we change person two, doth, equals 28. And now if you print persontwo dot h, and we also print person, one doth, then we see again, both got affected becausethis is not an actual copy. So here, we canuse copy, copy. And now if we run this, wesee we have a shallow copy here, so the originalperson didn't get affected. But again, nowif we have a deeper structure, so let's say,let more let's first create our person class,and let's say we also have a class company.Um, this gets this has an init method, soin it, self and now this gets two persons,it gets a boss, and an employee. So self dotboss equals boss, and self dot employee equalsemployee. And now we create two persons. Soone boss, soboss, might be older. And now a second person.Cho was a little bit younger. And now let'ssay we want to have a company so we say, companyequals company, with our person one, and ourperson too. And now if we want to make a cloneof this, so if we say, company, clone equalscompany, or let's right away, make a shallowcopy, so we can say copy dot copy. And nowif we change some variability here, so let'ssay one boss turns a year older, so let'ssay company clone, dot boss dot age, equals56. Now, and now let's print this print companyclone dot boss dot age, and also print theage of the boss of the original company. Solet's say company, boss, ah, then again, wesee it got affected because this is only ashallow copy, and the age is at the leveltwo. So this will, again only be a copy ofthe reference here. And in order to make thisindependent, we have to say copy dot deepcopy, and now if we run this, we see thatthe Original bosses still 55. So this is thedifference between shallow and deep copying.So we will learn about the concept of contextmanagers, and what are they used for, we willthen have a look at typical examples of contextmanagers and how we can implement our owncontext manager. So, context managers area great tool for resource management, theyallow you to allocate and release resourcesprecisely when you want to. So a well knownexample is the width open statement. So, inorder to open a file, we can say, with open,and then a file name. So let's call it notestuff. txt. And we open it in write mode,and s, a, and give it a name here. So, insideour width statement, we can use this namenow. So we can say file dot write, so we writesomething into our file, some some to do.And now when we leave this with statement,again, this width statement or just contextmanager will make sure to correctly closeour file again, even if there is an exceptionsomewhere here. So if we would have to writethis as a full code, it would look somethinglike this. So we say file equals open, andthen note stuck text in write mode. And thenwe have a try block. So we try to write intoour file. So write some to do. And now wehave an A Finally, clause. So this will beexecuted with or without an exception. Sono matter what happens, this will, will beexecuted every time. so here we can say file,dot close our file again. And then our resourceis freed up again correctly. So now if wecompare this and this, then our with openstatement looks much cleaner, and much, muchmore concise. So this is the recommended wayto open a file. And this is a typical examplehow we can use context managers in order toopen an AI file and allocate the resources.And then after leaving, it's also make sureto correctly free up our resources again.So typical examples is like in this case thatwith open statements, then, for example, toopen and close database connections, or anothertypical example is the lock. So if you'vewatched my tutorials about multi threadingand multi processing, you already know howto use a lock. So if we have a lock, so wesay, from threading, import, lock. And nowif we create a lock, so lock equals lock.So whenever we acquire a lock, so we say lockdot acquire,and then we can do something here safely.So this is now thread safe. But after thatwe always have to call lock dot release. Andif we forget this, we might run into a deadlockhere, and our program won't continue. So neverforget to say lock dot release when we hadlocked out acquire. So a better way to dothis. And also much simpler is to say withlock, and then do something here. This willautomatically acquire our lock when we enterthis with statement and then it will makesure to say locked at release when we leavethis with statement again. So this is alsoa typical example. And now let's say how wecan implement a context manager for our ownclasses. So in order to do that, we have toimplement the ENTER and the exit methods.So let's say we have a class and call it managedfile. Now of course this has an in it andit will get a file name here. So we simplystore the file name, say self dot file name,equals file name. And now we re implementthe same functionality as With the with openstatement, just in order to show you how thisis done. So, now what we have to implementis we have to implement the Enter method.So this will get self. And then we have toimplement the exit method, this will alsoget self, and then it will get an exit exception,type, an exception value, and also an exceptiontrace back. Now, I will talk about this ina second. But first of all, let's implementboth of them. So, the Enter methods will beexecuted as soon as we enter the width statement.So, here we want to allocate our resource.So, in this case, first, let's print enter,to have a look at where this will happen.And now we allocate our resource. So we sayself, we create a file and say self dot fileequals and now we open it here. So we openit with the file name, and open it in writemode. And then also inside the Enter method,we want to return the allocated resource.So in this case, we return self dot file.And now in our exit methods, we want to makesure that we correctly close the file. Sowe say if self dot file, so if this is notnone, then we say self dot file, dot close.And then print, exit. And here, let's printin it. And now this is all we need to usethis class as a context manager. And now wecan say we can use a width statement. So wecan say, with Managed File, and this willget the file name notes dot txt, s file. Andthen we can say file dot write, some to do.And now let's say let's see what happens.So this will, let's also make a print statementhere. So let's say print, do some stuff. Sowe see here, that init method gets calledwhen our object gets created. Then as soonas we enter this width statement, the Entermethod gets called so enter is printed, thenour resource is allocated, then we can dosome stuff. And afterwards, our exit methodis called as soon as we leave this with contexthere again.So now let's talk about what will happen ifan exception occurs. So we see here that PythonPython passes the type the value and the traceback to the exit method. So you can handlethe exception here. And if anything otherthan true is returned by this exit method,then the exception is raised by the widthstatement. So let's say let's print continuinghere. So in order to see if we reach thiscode, and now, let's also print. The, forexample, let's print, we want say, exit exception,and then print the exception type. And theexception value. So now if we run this, wesee that our exception here is none. So noexception here, exception type, and the exceptionvalue is none. And now if we try somethinghere, this that won't work, so let's say filedot some methods, so this will not exist insideour class here, so it doesn't notice somemethod method. So this will raise an exception.So now if we run this, then we see insideour exit function, it still can close ourfile even if there is an exception. So itreaches this code. So then it prints the ACCchat exceptions. In this case, it's an attributeerror. And the error is that we don't havethis some methods. And then we can exit thisfunction. But then our width statement willraise an exception. So we won't reach thiscontinuing here. And now if we want to handlethis exception ourself, we can, for example,say, we check if exception, type is not none,then prints that here's an exception. So let'ssay exception. Exception has been handled.And now in order to not raise an exception,we have to return true here. So let's sayreturn true. And we don't want to print thisanymore. And now let's run this. Now we see,we did prints exception has been handled,then it exits our width statement again, andthen no exception here from our width statement,and we can continue. So continuing is printed.So yeah, this is an example of how to writeour own class as a cost as a context manager.And we can achieve this with implementingit as a class with the ENTER and the exitfunctions. But we can also implement it asa function. And to do so we have to say wehave to import something. So we say from contextlip import context manager, and we have touse this as a decorator. So and then we willcreate a function that is a generator. Soif you don't know, or are not familiar withgenerators and decorators already, and pleasehave a look at my other tutorials, becauseI already talked about them. So now let'screate a generator here and call this openManaged File. And this also will get a filename. And then here, oh, sorry, I misspelledit. So Managed File, and then inside here,we want first, of course, want to open ourfile, so we say f equals open file name, inwrite mode. And here we have to write a tryand a finally clause. And inside the try statement,we want to yield the file. Sohere,we would, we want to write everything thatwould otherwise end up in our enter function.And then we want to have a finally clauseand here we write all the content of the exitmethod to free up the resource, the resource.So here, we say F dot close. And then we alsoneed to decorate it with our context managerdecorator. And now we can use this functionin a width statement. So we can say, withopen Managed File and call it notes dot txt,and then S f and then we can say F dot writeand then write something. So this will alsowork. And now let's go over this again whatwill happen here, so is because this is agenerator, so this will first make sure toallocate our resource and then it will tryto yield our resource. So and by yieldingit it will temporarily suspend its own execution.So we can continue here and use this file.So then we can do some operations with thisfile. And then when we exit the width statementagain, then our function here continues running.And then the finally clause will be executed,and our file will be closed again. And alsowe can handle exceptions here. And yeah, sothis is the second way how to use a contextmanager. And that's all I wanted to show youabout context manager. I hope you enjoyedthis tutorial and if you liked it, pleaseleave a like and subscribe to the channel.See you\n"