This article is not targeting the absolute beginner. It is specifically for JS Developers or the like looking for a fun introduction to the incredibly popular programming language Python. Many concepts explained: multiple inheritance, list comprehensions, the basics, and peculiarities of the language. All code can instantly be copied/pasted into a repl, and there is a repl near the end of the article to look directly at. ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### **In a universe of 90328443435329598 alien beings. Two new beings came from the void…**  Python Alien > Hello human. Your name is Marcel or so I hear. And you are one of 7530305890 human beings. > I am a [python](https://hackernoon.com/tagged/python) and my name is Guido, one of 3 python beings. > Now, there are: 90328443435329600 alien beings. Now, some code, that compiles to exactly what was written above: `total_aliens = 90328443435329598` . That is to say that Python is dynamically typed. `class Alien(object):` as well as `class Human(Alien):` expresses that the Alien class inherits from class object while Human inherits from class Alien. `def` is simply how a function is created. `__init__` is what is automatically run when a new instance of a class is created, it is the initialiser. `self` : Every method in a class necessitates this first argument. It does not have to be `self` but this is the convention. This is what the purpose of self is, taken from a concise description on Stack Overflow: * `instance_object.parent_class_method(arg)` internally converts to: `parent_class.parent_class_method(instance_object, arg)` . So `self` binds the instance object to the method invocation, similar to `this` in JS, with some subtleties to be aware of. Lastly, `global` : writing it as above references the global variable so it can be altered within the functions scope. `super` interacts with the direct parent class that Human inherits from, Alien. The argument sets `self.being` of the new instance to be equal to `human`. `pass` is necessary in Python when you write an empty function, an empty `if/else` or anything of the like. If left without `pass` an error occurs. A new instance is created as shown. `print` is how one logs out values. Grabbing values associated with the instance of the class is done with dot notation. Ok, onto functional [programming](https://hackernoon.com/tagged/programming) and a continuation of the story. _Human, I have six tasks you must accomplish to leave this planet:_ _To leave this planet, there is a generator function that runs each instance in which you overcome a problem. This builds up fuel for your spaceship home. This is the function:_ _First, I give you a list(_ `_['str_1', 'str_2', …]_`_), six strings will be inside it. You must check what the first letter of each string is numerically (a is 0, b is 1, etc.), then check if this index exists in the list, and finally add that string to a new list. Return the new list._ This returns `['damnation', 'fuggedaboutit', 'zoological', 'buttercup']` . `[]` : in this case it is a list, not an array. They are slightly different. * The major difference: `array([3, 6, 9, 12])/3.0` (array syntax) returns `array([1, 2, 3, 4])` while `[3, 6, 9, 12]/3.0` (list syntax) returns an error. `for str in strs:` is the predominant type of loop one sees in Python. It iterates through each index’d value starting at the zeroth index. `some_list.append(some_value)` pushes the specified value to the end of the list. `some_list.index(some_value)` looks for `some_value` inside the list and returns the first index where the value exists. If it is not found, `ValueError` exception occurs. _You are at: 17% fuel. Now, a different task. Another function. First argument: a single number. Second argument: a dictionary (_`_{‘some_key': 'some_value', …}_`_) containing a key called_ `_a_list_` _with a value that is a list full of strings (_`_'a_list':[...]_`_) and a separator (_ `_'separator': ‘something'_`_). As so:_ `_{‘a_list': […], ‘separator': ‘something'}_`_). The first argument specifies how many strings to use from the list. Store each string concatenated with the separator into a single variable or memory location and return that._ This returns: `‘Trump is terrible! Genghis Khan is terrible! That noisy person is terrible! ’` `range(num)` is an iterator of the number specified. If only one argument it iterates from zero to the number minus one. Range can take three arguments, it is similar to a condensed for loop: `range(-10, -100, -30) => -10 -40 -70` with whatever `for this_thing_is in range(...)` being the `=>` values. `{...}` : dictionaries are unordered key/value pairs or associative arrays. The keys must be strings and to access the values through bracket notation one must also insert a string value, or a variable name. _Your now at: 34%. Next, I give a more confusing challenge. For one, you do not know how many arguments are given! The first set of arguments contain either a number, the value None, or a string. The second set contains key/value pairs associated in this way:_ `_some_keyword=some_value_`_._ `_some_keyword_` _will be a string._ `_some_value_` _will be a number. Return a dictionary. One key/value. The key must be only the strings I first gave you (the arguments) in reverse order. The value must be a concatenated string, only use the string in the keywords from the zero index up to the number specified as the value, all into one single string without spaces._ This logs out: `{‘big amazing animal’: ‘elephant’}` . If you print out args prior to `reversed(args)` you see that args is: `(‘animal’, ’amazing', None, 6, ‘big')` . This is a tuple. A sequence of immutable objects. Tuples are written with parentheses and they cannot be altered the same way as a list or array, as in, altering at specific indexes. `enumerate` allows one to have an automatic counter and access the values simultaneously. `if/elif/else` is how to write if/else statements. `is None` is how one returns a true or false value for checking the `None` value. It is similar to `null` but more so `undefined` in JS as many instances of code can return this value such as when one alters a list through a higher order function that one would not expect to return something or when a function does not return anything, it returns `None`. `isinstance(arg, int)` is used to check if the arg is an instance of a specified class. `int` in this case but something like this can also be expressed: * `isinstance(marcel, Alien)` will return true. Classes, strings, ints, and all else you expect can be checked in this way. _Ok, good. You are at 51%. Now, an interesting one. You are given a matrix. Three lists in a list, each list has four strings inside. First, make a new list associating each index of each list as so: (_`_[[[0][0], [1][0], [2][0]…],[[0][1], [1][1]…], ...]_`_) then, flatten each list to a single string, and finally join that list into one single string. You can fit all of this logic into one statement… a list comprehension._ This returns: `You must make it look this way. Very extremely, magically, important thing to do!` First: `[[row[i] for row in matrix] for i in range(4)]` . The same thing: One must think from the most outward brackets/logic in. So: `[all_the_logic]` is to say: create a new list and whatever is done inside here will determine what the list looks like in the end. `[[some_inner_logic] for i in range(4)]`: This will specify there to be 4 rows and whatever`[row[i] for row in matrix]` results in at each instance is what each row will be. `[row[i] for row in matrix]` means to use the index, i (0, 1, 2, 3) from range as be aware it is constant while the first, second, third, and fourth row is being created. During each row creation this occurs: * Loop through each row in `matrix` =>push value at `row[i]` into this newly created list => append this list to the initially created list. At this point this is what is created: `[['You’, ‘must', ‘make'], ['it', ‘look', ‘this'], ['way.', ‘Very', ‘extremely,'], ['magically', ‘important', ‘to do!']]` . A transposed matrix. Onto: `[str for sublist in [transposed_matrix] for str in sublist]` Again, outward brackets to innermost. Create new list: `[result_of_logic]` Read from the furthest-to-left for loop: `sublist in [transposed_matrix]` is to say: loop through each list within the matrix, starting at the first. Then read onto the next for loop: `for str in sublist` . This equates to saying to loop through each `str` within this `sublist`. That is the value now available to append to the list. Lastly, look at the beginning of the list comprehension: `str` . That is what is appended to the list: `['current_str', 'second_str', ...]` . So the left-most value is what is, in a way, pushed into the newly created list until the loop is finished. As if `append` automatically occurs. As for: `''.join(final_list)` , `''` is the string separator. Notice how the left-most `for` loop is what first occurs and the further to the right one goes is the nesting. _Ok, now you are at 68%, only two left to go! This one I need you to create a factory function. There will be five functions to implement._ `_append_` _(push to end of list),_ `_extend_` _(concat one list to another list),_ `_insert_` _(insert item into specific index),_ `_remove_` _(removes each instance of item specified), and_ `_pop_` _(pop off final item in list). You cannot use the higher order function equivalents and each function that you create_ **_cannot mutate the original list_**_. You are given three or four arguments._ 1. _a list_ 2. _the name of the function as a string_ 3. _the one argument the function needs, index if it needs four (for insert)_ 4. _an item (only needed for insert)_ _Ok, good luck!_ Know that each of these functions are not the optimal way to do this. Using the associated higher order function is much quicker. Also, know that the higher order functions all return `None` except `pop` which returns what was popped. `append` and `extend`: This is simply a subtlety of Python. Adding a list to another list automatically concats the two lists. `li.append(item)` and `li.extend(other_li)` is the proper syntax but these two options mutate the original list while the ones written above do not. `other_li` in `extend` is not mutated though. `insert` and `pop` both use slices in this case. I’ll focus on `insert` . Notice: `the_list[:idx]` : this means to slice the list up to the index but not including it. `the_list[idx:]` : is to say to slice from and including the index up to the last index of the list. `remove` : a simple list comprehension (they are extremely fast operations btw). `[x for x in the_list if x != item]` : `new_list = []`\=> `for x in the_list:` => `if x != item:` => `new_list.append(x)` or, but not technically `new_list += [x]` . Though, be aware that the real `li.remove(item)` solely removes the first occurrence of the item. This `remove` removes all occurrences. _Very well done, onto the next one. Your at 85% fuel, this is the last one! Next one is a bit of an oddity as it is two functions in one. I am to give you a wide assortment of keywords and arguments. Your function will be called multiple times with a random amount of arguments or no arguments. And/or a multiple assortment of keywords. I need you to store all the argument values that I give you in a non-global list, and all the keyword values in a non-global dictionary. Return a dictionary as so:_ `_{'the_list': [...], 'the_dictionary': {...}}_` _. Each time the function is called the list is altered or the dictionary depending upon the input_ **_and all values are appended to the previous calls values._** _In the end, the final calls list is unpacked as the first argument and the dictionary is unpacked as the second argument into another function._ `(*args, li=[], dic={}, **keywords)` : Notice that the two arguments that are not keywords or arguments are in between these two calls, this is required. But the really odd part, why is `li` and `dic` continually mutated during each function call? **Python does not create a copy of each argument for each function call** but holds a reference to the original default argument, and if one is not careful they can easily fall into the trap of creating a function that is not pure. As for this: `back_to_earth(*dictionary_and_list()['a_list],` : this is how one can unpack a list into a function so each item in the list becomes an individual argument. Values are grabbed with `*args`. As for `**dictionary_and_list()['a_dictionary])` : this unpacks the dictionaries values into the functions arguments. Each keyword in the function that has an associated key in the dictionary will be given that value. And what the code outputs: > _Ok, your there: 100%! Ok, you are done, it is time to leave this Python world. Congratulations on all your accomplishments! Goodbye! > Heading > 3 > back > 2 > to > 1 > earth! > 0_ Last but not least, after each function was finished I ran `liftoff.__next__()` . As you can see in the code below. One thing to know. If it is run one more time an error occurs. Why? Well, generator functions can only be read once and never again. So when the iteration is finished, there is no longer a `.__next__()` and all previous values have been garbage collected. All the code in one place: And the repl: [**repl.it - pythonIntroductionArticle by @jerrymuzsik** _All the code that was written in the article in one place. repl.it_](https://repl.it/@jerrymuzsik/pythonIntroductionArticle "https://repl.it/@jerrymuzsik/pythonIntroductionArticle")[](https://repl.it/@jerrymuzsik/pythonIntroductionArticle)  This is Guido, Python alien A few other things to be aware of: 1. Filenames, variable names, and function names are named with underscores. 2. Indentation: 4 spaces is the convention. 3. CamelCase is not used much, only in classes. 4. If the variable is globalthenitisalllowercase (if a variable is global then it is all lowercase). > Thank’s for reading. Any recommendations, ideas, comments, thoughts, claps, or whatever else you feel impelled to do in relation to this article would be greatly appreciated!