A Hundred Days of Code, Day 010 - Python Functions, Basics Done!

Today was hard! Notes ‘*args’ way to get multiple arguments without having to assign placeholders for them it scoops up all the arguments and gives it to the function in a tuple. I could then loop over it with for. I just put * in front of one of my placholders et voilà, def example_func(*catch_everything) I can define placeholders to catch specific arguments, but those need to be before my ‘*args’. Edge Case: I could have my arguments in a list/tuple already. I can just add the structure with a * in front of it and Python will unpack it for me. If I have a list, catch_me_if_you_can=[1,2,4] then I can pass the elements individually, as arguments with a def example_func(*[catch_me_if_you_can]) Another kinda frequent edge case: ‘*args’ catches everything that is unassigned. so if i have something with a default value, it will get trampled by the data from my args. Best thing to do is to set the default after the ‘*args’ like so, example_func(a, *args, b=10) Keyword Arguments ...

July 17, 2020 · Mario Jason Braganza

A Hundred Days of Code, Day 009 - Python Functions, Basics

Started up with learning about Python function basics, today. Notes follow. Using the Lerner pool of wisdom, as usual. Why do we need functions? DRY (Don’t Repeat Yourself), because we can take stuff that is repeatable, assign it a nickname and just call that nickname over and over, instead of tediously writing all that stuff over and over and over If want to modify something, I can just call it (by the nickname) and then add my little spice to it. Like I have the recipe to an omlette written down somewhere, I can then just add a little note with secret ingredients at the bottom of that recipe to create a better or a different omlette. Functions are objects. ...

July 16, 2020 · Mario Jason Braganza

A Hundred Days of Code, Day 008 - Python Basics, Lists, Tuples, Dictionaries, Sets and Done!

This was an amazing run! Learnt lots. Done with the basics course. Woohoo! Notes With lists Not pythonic to mix types can iterate, slice and dice, search, get lengths, transmute them (for e.g. reverse items in them) just like strings can have lists of lists! lists are mutable, unlike strings. can change items/elements of a list If i create a list from another list, the new list items reference the old list items if i want to copy elements from a list rather than reference them, I’ll go newlist = oldlist[:] which will copy the elements from the old list into the new one, rather than create references to the old ones Realise that there is a difference between changing the values of a variable and between changing elements of a list. When I do x = 2 and y = x and then change x to be x = 3, remember that the value of y does not become 3. y continues to point to the original location in memory which holds 2. What I did was to break x’s connection to that value and assign to another value in another location On the other hand, when I do x = ['jane', 'jill', 'mary'] and then create a copy with y = x and then change x[0]='edith', what I do in this case is change the actual element. The references to that object in momory stay unchanged. Which is why y[0], which holds references to the same object, will also reflect the change to edith. Finally if I go, x = ['athena', 'diana', 'aphrodite'], now we’re back to the assignment. x will point to this new list while y points to the old one. This distinction between changes in assignment vs changes to content is very important, when dealing with mutable/changeable data types like lists Append something to a list with .append - list.append(something, something else) Heuristic, when a method on a mutable data type, changes data, in returns None So I should just go mylist.append('blah') and stuff will be done If go mylist = mylist.append('blah') (which I am very apt to do) the method will change the list, then return None and that None will get assigned to mylist, In effect, erasing the list and causing unnecessary heartache. So, be careful, very careful. Not careless, like Bond, James Bond. += or .extend takes an iterable on the right. picks each element. and then assigns them singly to the list on the left. Append can take only one item. If I want to add xyz as separate entries to mylist that has ['a','b','c'], append will just take it as a big lump and make ['a','b','c','xyz'] Instead I do a += mylist += 'xyz' or mylist.extend('xyz')will give me ['a','b','c','x','y','z'], which is what I wanted in the first place it will only work if there are iterables on the right. (strings, lists, dictionaries etc.) the insert method will let you insert something at a location in the list. Give it what you want, tell it where you want, and boom! mylist.insert('d', 3) will put d after abc, giving me ['a','b','c','d','x','y','z'] I can replace things in a list by giving it a location and telling it what to put in there. I could do mylist[0]='artemis' and the list will change to ['artemis','b','c','d','x','y','z'] I could also give it a slice along with a list of what to put in there. Doing mylist[1:2]=['josephine','lisbeth'] will now give me ['artemis','josephine','lisbeth','d','x','y','z'] if you add additional elements, than what you replace, Python will insert them, growing the list. Removing things from a list? the .pop method will pop off the last item in a list. If i give it a location, it will remove the item at that index location. mylist.pop(3) will remove d from mylist giving me ['artemis','josephine','lisbeth','x','y','z'] When I know what I want to remove, I just use the remove method instead of pop. mylist.remove('josephine') will remove poor Josephine leaving us with ['artemis','lisbeth','x','y','z'] If I’m not sure, I could check for the presence of an item before I remove it. Should prevent a program from barfing on me if that element isn’t there if 'q' in mylist: mylist.remove('q') also the remove method only removes the first instance of something. Iterating and counting over lists? the for loop! I can use the enumerate function if I want numbered items out I can iterate over a slice. The range function is very list like in its behaviour. I can sort lists. same caveat as above. sort will change the list in place and return None. Don’t go assigning mylist = mylist.sort(). It won’t work A .sort(reverse=True) will sort in reverse sorting between mixed types in a list doesn’t work in Python 3 anymore. The types in a list, ought to be the same. Sorting list of lists works by comparing indices If I don’t want to change my original list, I can use the sorted function on the list. It works on most iterables, not just lists, while the list method is restricted to lists It returns a new sorted list, and keeps the original list intact. I can do sorted('something', reverse=True) will return a reversed list. I can str a list and list a string ...

July 15, 2020 · Mario Jason Braganza

A Hundred Days of Code, Day 007 - Python Basics, Variables, Basic Data Types, Strings and Loops

Started with the Reuven Lerner, Intro Python:Fundamentals course today. Made surprising headway, even though today was crazily demanding with work and personal stuff. Notes The difference between == and is If you want to see if two things are equal, use == like, is 2+2 == 4 If you want to know if two objects are the same thing. if they are just pointers to the same memory location, use is. The heuristic is, if you are checking for singleton values, something that there is only one thing of; then in Python, we use is. Use sparingly . Make sure you check mostly to see if things are the same object or practically to see if something is None mostly to check for the presence or absence of things. like x = None and then I go check if x is None … True / False heuristic in Python Nearly everything in Python is true except for False, None, 0 or anything empty (empty lists, dictionaries, etc.) Learnt how working with strings in reverse works if I want the last element in a string, I could reference it by calculating it’s length and lopping one off (since indexes start at 0), like with the string s = 'Halt! Who goes there?' I could access the last element by s[len(s)-1] or the last but one, with a s[len(s)-2]. This is made a lot more convenient by just dropping the len(s) stuff, just leaving the - numeral part - s[-1] or s[-2] This makes so much sense in my head now, if what I am doing is counting straight and then subtracting one. I should remember, things sometimes are simpler than they seem :) For some reason, I always imagined, Python could see the length of my string, so why couldn’t there be a reverse string way of doing things like s.rev[0] that would just count backwards 😂 Strings are immutable. They can’t be changed. I can just process a copy and generate new ones, though. just realised that the f in f-strings stands for formatted strings, since when I write raw strings, I use an r for, duh, raw strings Slicing involves carving out a small contiguous part out of a larger string. The thing to note is that when I say s[0:4] it means upto, but not including 4 If I say s[0:100], slices are forgiving and give me upto the end of my small string, without throwing an error. Empty colons in slices imply endings. s[:10] means start from 0 and go up to 9. Or s[9:] means start at 9 and go upto the end. Ergo s[:] means from the beginning to the end. I can have step sizes to step over. The default, hidden size is 1. I can step, oh, say every three elements by append :3 to the end of my slice like so, s[0:20:3], basically [start:end:step size] I can also have negative step sizes which will give me the results in reverse. The most common one being -1, because the quickly reverses a string for me (commonly done). But it works with other step sizes too. A -2 will start counting backwards every other character from the end. A reverse slice begins with the end character and then beginning. So s[10:5:-1] to carve out a slice backwards. Sequences are strings, tuples and lists. They all can be sliced and diced and iterated upon. Heuristic, else in a for loop is to match stuff when I don’t encounter a break. the else part matches the for to form the for-else construct, even though the break is inside the for loop while loops are for when you don’t know the end of what you are looking for. there is not finite end. No 0 - 10 happening. You are just searching for something in an amorphous swamp. The swamp is vast, there is no way to say from this end of the swamp to that end.You only give up when you find what you are looking for, or when you decide it’s time to give up (some preset condition). make sure there is a counter that breaks stuff or I might loop forever Learning / Feedback/ Experiences from doing exercises Realising why Python notebooks are used. Very, very, very, handy to quickly write prose and code at the same time. It fits my mental model of programming perfectly! I keep thinking strings and characters are English and forget to quote them! The number of NameErrors I get, is not funny. Thing that keeps biting me when I write or statments. I should remember to say if x='blah' or x='meh'. I keep writing if x='blah' or 'meh', which is wrong. I keep using a lot of superfluous variables. I should be more intentful. Instead of just printing an expression, I tend to figure out the expression, assign to a variable and then print it. Good for building, probably bad for optimal use. But I won’t worry about it too much now. Just something to improve on in the long term. Reuven is a painstakingly methodical teacher. If he’s so good in his videos, I am jealous of folks attending his live classes Read all about my Python basics journey here ...

July 14, 2020 · Mario Jason Braganza

A Hundred Days of Code, Day 006 - Starting and Quitting Comprehensions

I know I said, I’d start with the basics, Reuven, but please forgive me this once :) Will do the rest, bottom up :) Have started up with this, because I’m fascinated with how folks manage to build in so much functionality into short, easy to read statements. To my mind, comprehensions are the pithy proverbs of the programming world. So here goes … Notes This style of writing code, comes from functional programming Functional Programming is another style of writing code It assumes that data is immutable. (Or at least it treats it as such) It does not change the originals I work with. (I assume this means that I always work on a copy or something) we work with sequences of data and create new ones based on the old ones (changing case of a sentence, comes to mind) There are a bunch of techniques/patterns/heuristics that’ll let me do that We can treat functions as data and pass them around as arguments to other functions. The functools module assists with writing such code Why code in such a manner? Some benefits include them being easier to read, easier to debug, shorter, more understandable. Distributed Computing / Multiprocessing across processors and cores/threads makes these techniques more relevant in this day and age My personal need is to write easy to read code, like when I see a well crafted list comprehension If I want to square a list of numbers, my current go to is to generate a new list, using a for loop. Comprehensions are a better way of doing this For loops are far when I want to execute something on each item of something iterable, like a list or a dictionary. when i want to have a statement happen If just want to transmute the elements of list into something else, change each element, like square them all above, then comprehensions are my friend Here’s a list comprehension to square a list of numbers from the list numbers. [one_number * one_number for one_number in numbers] The square brackets make it a list comprehension. If I want dictionary comprehensions, I would abut them with curly braces {}. And if I use (), I’ll get a generator expression (which I know only the bare basics about) For loops and comprehensions might look similar, but they really are different Note: whatever expression you use to generate output has to return something. like the square expression above . because what I want to do is catch all my results in a container. functions (like the print function) that return None as their result, cannot work here. They will display stuff, but store only None in our comprehension container :) I can also write the comprehesion over multiple lines (works because they are bounded by the list brackets here or bounded by other brackets elswhere) [one_number * one_number for one_number in numbers] here with the breakdown of the lines, the first line becomes my output generator; the expression I want to use and the second line, the data I want to process. Much more readable this way learning / feedback/ experiences from doing exercises Exercises today required a bit of head scratching and a bit of research, but were relatively simple I should keep in mind that the computer can go crazy too. I kept wondering why my code wouldn’t run and and kept banging my head for an hour. Even Rueven’s solution was what I did. Until I restarted my Jupyter note book and everything worked the way I expected. Should have a time limit on how much struggling I do. From the last week, it looks like I am a real sucker for pain otherwise. Half an hour tops and then go look up the solution. Have reached the second set of exercises and realised why Reuven told me to start with the basics. I failed with the second one in this set. I just know, there is a simple solution and I cannot seem to get it. This basically means … yes … that my foundations are creaky. Note to self, walk before you can run. By Jove, you should’ve learnt that by now! :) So this is me, waving goodbye sorrowfully to comprehensions. Will start with the basic Python course tomorrow. But I’ll be back soon enough, damn it! ...

July 13, 2020 · Mario Jason Braganza

A Hundred Days of Code, Day 005 - Magic Methods and Winding Up OOP

Done with Reuven Lerner’s OOP basics Notes len does the right thing across multiple types of objects. it counts characters in a string, elements in a list, and key-value pairs in a dictionary. how does it know how to do that? that is because len uses a magic method (methods that have a __ for a prefix and suffix) len uses the __len__ method which i can use in my own classes, to implement a len method for my classes If I choose to do so, I need to realise what those underlying methods expect to return and return the same type in my classes. __len__ expects to return integers, so when I implement it in my classes, I ought not to return a string. Once again Reuven strongly suggests using common sense :) same thing when i try to print something. it calls the magic method __str__ to do stuff. or if i try to do repr to check for raw representations, the __repr__ method is called. Python is filled with these methods which I can use to allow my classes to have standard Python like functionality. like a print(doggie) should give me details about the cute pup object i just created, if I have taken the time and attention to implement the __str__ or __repr__ methods most of these methods come with the base primitive class object which every class inherits from. so i get them for free. and then i can override them and customise them to what I want to show. people try standard methods on new objects. implementing them is much better than creating my own and asking people to use ’em. if both are equal or really similar, ok to just use only __repr__. later when I have experience and other needs, i can implement __str__ too learning / feedback/ experiences from doing exercises Despite warning myself above, I went ahead and made the mistake of returning a whole lovely string, instead of an integer, when I tried to implement the len method on my class XD and then I forgot to add the f prefix to an f-string and wondered why it was not interpolating for nearly 30 mins Reuven has a wry sense of humour. In one of my exercises I get to create classes of animals for a zoo, with various attributes such as colour and legs and so forth. Then he has me put them in cages. After making me put 2 sheep in a cage with a wolf, he wonders if the legs of the sheep ought to be reduced or not XD The number of typos I am making is staggering. Missing colons, missing quotes, missing brackets. If this is Python, I shudder to think how I’d fare if I picked up a static language to learn XD Wasted another half an hour because I spelt colours with capitals like Black and then later looked for black and was tearing my hair out, because I knew there were black animals and why in tarnation, would Python not show me them XD Saw Reuven do nested comprehensions and now I want to do that too! it took him one well thought out line to do what I did in 2 multiline functions Final Words This was amazing! I learnt so much about classes and the way they work. Reuven has a very joyful pedagogy. I love him go hahahaha like Santa Claus. I love the fact that he makes mistakes. I love that for every problem, he poses, he has various approaches. His fluency shines through every lesson. I got lucky with the Pycharm Humble Bundle. But I loved this so much, that I am going to sign up for all the Lerner courses, I possibly can. Beginning with the basics. If OOP is any indicator, the journey is going to be lots of fun. ...

July 12, 2020 · Mario Jason Braganza