Learn Python Series - Intro

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@scipio·
0.000 HBD
Learn Python Series - Intro
# Learn Python Series - Intro

![python_logo.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1519652370/js1cxnvwrcvgvg4klmkk.png)

#### What Will I Learn?
- You will learn how to install and run a Python 3.6 "Anaconda Distribution" 
- You will learn you can use Jupyter Notebooks for both learning Python and publish on Utopian using them as well!
- You will learn all the fundamentals of Python 3 programming

#### Requirements
- A working modern computer running macOS, Windows or Ubuntu
- A decent internet connection to download the (large) Anaconda Distribution
- The ambition to learn Python programming

#### Difficulty
- Basic / Intermediate

# Learn Python Series - Intro
This tutorial episode, regarding the programming language Python 3, is the first of many, all being a part of my **Learn Python Series**, which will gradually evolve into an **interactive book**. This series is intended for anybody interested in Python programming; it doesn't matter if you're an absolute beginner programmer in Python, or even any programming language, if you already have an intermediate skillset, or if you are already a very proficient Python programmer. (Regarding the latter, of course the first few tutorial episodes won't cover anything new for you, but to make things a bit more interesting, I'll try to cover a few lesser-known _fun facts_ here and there.)

For those who are absolute beginners, in this Intro episode I'll briefly cover the very most fundamental Python programming mechanisms. To avoid making this first Intro episode extremely lengthy, I must mind brevity. But rest assured that everything that's barely touched upon in this Intro, will be expanded and discussed in-depth in the following episodes. If you have questions about anything, feel free to express yourself in the comment section; I'll be happy to reply!

### Why this **"Learn Python Series"**?
There are a few reasons why I decided to spend **a lot of time** on writing this **Learn Python Series**:

* I've went over the already accepted Python tutorial contributions on [Utopian.io](https://utopian.io/), and I came to the conclusion that most Python tutorials were either about the `steem-python` package (well-covered for example by @amosbastian, @steempytutorials (including @amosbastian), and @emrebeyler), or not written in English, or were "loose sand" covering only some bits and pieces, or were just "dropping some code" apparently assuming the student / reader to understand what's what, without meticulously explaining the topics at hand.
* The Python syntax is one of a kind: related code blocks are indented instead of using `{ curly braces }` which looks really clean, and (some) code can be almost like plain English,
* Python runs anywhere, it's a general purpose language meaning you can use it for an enormous amount of programming tasks, the language itself has evolved substantially over the past +/- 30 years, lots and lots of external modules exist that you can freely import to power your own code, and its user-base is vast, including academic circles. Still I feel Python could be even more popular than it is today, via better marketing (not all Python module websites "_look cool_") and via tutorials that explain things **both in-depth and easy-to-understand**.
* Python is Dutch, I'm Dutch, and as they say "_If it ain't Dutch, it ain't much!_" ;-)
* I want to encourage beginner programmers, and programmers coming from other languages / environments, such as PHP, nodeJS, C# and Java to learn Python. **Python rocks, so become a _Pythonista_ too!**

# Set-up your Python 3 environment
**Anaconda Distribution of Python 3.6:**

I'll be covering **Python 3**, which is not (entirely) compatible with Python 2 (that will be deprecated in about 2 years from now). Operating systems like macOS and Ubuntu by default contain out-of-the-box pre-installed Python 2 interpreters, so in order to use Python 3 you'll first need to install a Python 3 (virtual) environment. I could spend one or even more tutorial episodes on "how-to install Python 3", because several Python distributions exist, all with their pros and cons, and for every operating system the installation procedure is slightly different.

If you're an experienced programmer, I'm sure you won't need me explaining how to install Python 3 on your system. And in case you're a beginner, I recommend using the Python 3.6 [Anaconda Distribution](https://www.anaconda.com/download/). For macOS and Windows the Anaconda auto-installer is self-explanatory. And for Ubuntu Linux, the Anaconda installation procedure has been covered as well by @amosbastian in [this article, but only execute the procedure as explained in "Step 2"](https://utopian.io/utopian-io/@amosbastian/how-to-install-steem-python-the-official-steem-library-for-python).

PS: The Anaconda Distribution is quite large, and can be extended with additional modules as well, some of which are for scientific use. Although you probably won't be using the entire distribution, I still recommend using it because it manages package inter-dependencies really well: Anaconda **just works**.

**Jupyter / iPython Notebooks:**

Anaconda includes a number of additional Python tools, including the **Anaconda Navigator**. Open the Anaconda Navigator application, click the "Home" icon (which is selected by default), and **Launch** a new **Jupyter Notebook**, thereby creating a new (iPython) `.ipynb` Notebook document: that's a JSON-like document that runs your Python code inside what's called a "cell", and can include **MarkDown** (just like you're posting on Utopian.io and Steemit.com) and therefore text formatting, hyperlinks, images, and video players. Jupyter Notebooks are used by (data) scientists to share their research (results) in a reproducable fashion, but Jupyter Notebooks **also** function as a great environment, to write and test your own Python scripts, and/or add your own notes to your scripts so you can remember what you learned, at a later date. As a matter of fact **I am writing this tutorial inside a Jupyter Notebook**!

**Code editor: Visual Studio Code, or PyCharm Community Edition:**

Jupyter Notebooks are great for learning new things, publishing and sharing of tutorials and research results, but in case you want to program multi-file / multi-module working programs, you need another type of code editor or IDE (Integrated Development Environment). If you properly configure your code editor to work with the right (virtual) environment per project, after installing and importing certain Python modules, the code editor / IDE can "assist" you with (among other things) **code auto-completion** and **suggestions**. From the Open Source world, I recommend you download and install either [PyCharm Community](https://www.jetbrains.com/pycharm/download/) or [Visual Studio Code](https://code.visualstudio.com/download).

**PS: From here on, unless specified otherwise, I'm assuming you will be using iPython / a Jupyter Notebook. Of course you may as well use the command line, or a Python IDE, to edit and run your code.**

# Essential Python 3 mechanisms
Every book needs a beginning, and since I'm **also** (yet not exclusively) addressing beginning Python programmers, this `Learn Python Series` will kick off by briefly explaining the most important Python mechanisms.

### Indenting of code blocks as a language requirement, not just coding style
A **block of code** can be considered as the grouping of programmatic statements, which may or may not include inner-code blocks as well. Code blocks are intended to treat multiple statements as if they are one statement. Codeblocks also function as a means to limit scope (of objects, functions, methods, attributes, properties, variables).

In many programming languages **curly braces** `{ }` are used to group code blocks and **semi colons** `;` to denote the end of an individual statement. In jQuery (a well-known JavaScript library) for example, this piece of code works fine:


```python
// a jQuery IIFE syntax example
(function animateMobileMenu() { $('body').on('click', 'div.hamburger.closed', function() { 
$('div#mobilemenu').css({right: "0px"}); $(this).removeClass('closed').addClass('open');     
$('body').addClass('menu-active'); }); })();
```

... it might work fine, but is this easy to read? I'd say no.

In Python, code blocks are structured **by indentation**: all code statements that directly follow each other and have the same "gap from the left", are on "the same level of indentation", belong to the same group. Indentation in Python is a language requirement, not just a matter of coding style. If you, by accident, wrongly indent a statement, your script / program won't run at all.

Let me give you a Python code snippet as an example to explain the indentation grouping mechanism. (How the snippet works exactly, doesn't matter for now, as long as you understand the indentation mechanism):


```python
# This is a comment, an explanation inside code
# Please observe the indentation depth for every statement below

garage = ['Fiat', 'Lamborghini', 'Ferrari', 'Mercedes', 'Lada']
for each_car in garage:
    if len(each_car) > 4:
        if 'i' in each_car:
            message = ' is an expensive Italian car!'            
        else:
            message = ' is an expensive car, but not from Italy!'
    else:
        message = ' is an affordable car!'
    print(each_car + message)
            
# Output:           
# Fiat is an affordable car!
# Lamborghini is an expensive Italian car!
# Ferrari is an expensive Italian car!
# Mercedes is an expensive car, but not from Italy!
# Lada is an affordable car!
```

    Fiat is an affordable car!
    Lamborghini is an expensive Italian car!
    Ferrari is an expensive Italian car!
    Mercedes is an expensive car, but not from Italy!
    Lada is an affordable car!


### The `print()` function (previously: print statement)
Compared to Python 2, in Python 3, the print "string" statement was replaced with a `print()` function which accepts a number of comma-delimited arguments. For example:


```python
print('Hello World!')                     # pass in a string
# Hello World!

str1 = 'You can pass me as an argument'
print(str1)                               # pass in a string variable
# You can pass me as an argument

str2 = 'The answer of 3*3:'             
print(str2, 3*3)                          # pass in more variables, or expressions
# The answer of 3*3: 9
```

    Hello World!
    You can pass me as an argument
    The answer of 3*3: 9


### Commonly used Data Types
Python has a number of standard, built-in, data types. We can categorize them as:

* numerics
* mappings
* sequences
* classes
* instances
* exceptions

All different objects can be subject to **Truth Value testing**, and (almost all can) be converted to a string (which is implicitly done when being passed to the `print()` function).

Let's hereby, for brevity in this Intro episode, briefly introduce some commonly used Data Types, and discuss how to use them far more in-depth in the forthcoming episodes.


```python
my_bool = True
your_bool = False
my_integer = 8
my_float = 9.2
my_string = 'A string is a sequence of characters'             # a string is a sequence as well!
my_list1 = [1, 2, 3, 4, 5]                                     # a sequence of mutable elements
my_list2 = ['Audi', 8, 9.2]                                    # list elements can be of different types!
my_tuple = ('Python', 'JavaScript', 'C', 'GoLang')             # tuples are lists, but immutable
my_dictionary = {'one': 1, 'two': 2, 'three': 3}               # dictionaries contain `key : value` pairs
your_dictionary = {                                            # dictionaries can be nested as well!
    'platforms': [
        {'name': 'Facebook', 'url': 'https://facebook.com'},
        {'name': 'Twitter' , 'url': 'https://twitter.com'},
        {'name': 'Steemit' , 'url': 'https://steemit.com'}
    ]
}
```

### Arithmetic Operators
To apply mathematical operations, the following built-in operators can be used with respect to all numeric data types:


```python
a = 10 + 3    # addition `10 + 3 == 13`
b = 10 - 3    # subtraction `10 - 3 == 7`
c = 10 * 3    # multiplication `10 * 3 == 30`
d = 10 / 3    # division `10 / 3 == 3.33333`, returns a float in Python 3 unlike in Python 2
e = 10 ** 3   # exponentiation `10 ** 3 == 1000`
f = 10 % 3    # modulo, the remainder of a division `10 % 3 == 1`
g = 10 // 3   # truncation division, also called floor division `10 // 3 == 3` 
```

### Assignment Operators
Assignment operators are used to assign values to variables. `a = 5` is the simplest form, but how do you change the value of `a`, for example how to add 3 to the current value? This could be done of course with the expression `a = a + 3`, but there are more "shorthand" assignment operators available in Python. 

Please observe the following code:


```python
a = 5     # initial assignment of value `5` to `a`
a += 1    # equivalent to `a = a + 1`
          # Please note that `++` is not available in Python!
a -= 2    # equivalent to `a = a - 1`
a *= 4    # equivalent to `a = a * 4`
a /= 5    # equivalent to `a = a / 5`
a **= 2   # equivalent to `a = a ** 2`
a %= 2    # equivalent to `a = a % 2`
a //= 2   # equivalent to `a = a // 4`
```

### Truth Value Testing and Control Flow
In order to make "decisions", **conditions** are evaluated (tested) for being either `True` or `False`, and actions can be taken based on those evaluations. This allows for decision structures and **control flow** via (nested) `if`, `elif`, and `else` statements, and provided that the evaluated object is **iterable**, the loop statements `for` and `while`.

Please observe the following example statements, and the explanation inside the code denoted as comments:


```python
quiz_threshold = 38
moderator_scores = [45, 44, 37, 38, 41]

for score in moderator_scores:      # moderator_scores is a list, therefore iterable
                                    # The `for` loop continues, evaluates to True, as long
                                    # as `score in moderator_scores` evaluates to True,
                                    # ergo: for every element in the list.
    if score >= quiz_threshold:     # The condition `score >= quiz_threshold` evaluates to
                                    # either True or False (for every `score`)
        print('Sufficient score')     # if `True`, then print `'Sufficient score'`
    else:
        print('Insufficient score')   # and if `False`, then print `'Insufficient score'`
        
# Output:        
# Sufficient score
# Sufficient score
# Insufficient score
# Sufficient score
# Sufficient score
```

    Sufficient score
    Sufficient score
    Insufficient score
    Sufficient score
    Sufficient score


**Nota bene 1:** For truth value testing, Python includes three **Boolean operations**, being `and`, `or`, `not`, and includes eight **Comparison operations**, being `<`, `<=`, `>`, `>=`, `==`, `!=`, `is` and `is not`.

**Nota bene 2:** Python uses so-called **loop control statements** to change the normal sequential code execution:

* `break` is used to terminate the loop statement,
* `continue` is used to first skip the remaining iteration body and continue with retesting the loop condition. If True, the next loop iteration will be executed,
* `pass` is used as a stub, or when a statement is needed but its code execution is not.

### Commonly used Built-in functions
Python comes with a number of built-in functions that are always available. I will hereby briefly mention some that are most commonly used.

* Type conversion functions


```python
a = float(8)          # converts the int 8 to float 8.0
b = int(4.2)          # converts the float 4.2 to int 4
c = str(4*5)          # converts the expression (= `4*5`) result to string
d = list('Hello!')    # converts the string `Hello!` to a list ['H','e','l','l','o','!']
                      # NB: `list()` is actually a mutable sequence type rather than a function
e = tuple('Hello!')   # converts to an immutable tuple ('H','e','l','l','o','!')
                      # NB: `tuple()` is an immutable sequence type, rather than a function
f = range(10)         # Arguments of a range constructor must be integers; the range is iterable
```

* Sequence operation functions


```python
g = len('Hello!')     # `len()` returns the length, the number of items, of an iterable
h = min([1,2,3])      # `min()` returns the smallest item of an iterable,
i = min(1,2,3)        # ... or of multiple arguments given
j = max([1,2,3])      # `max()` returns the smallest item of an iterable,
k = max(1,2,3)        # ... or of multiple arguments given
l = sum([1,2,3])      # returns the total of an numerical iterable
```

* Various functions


```python
m = type({'foo': 'bar'})         # `type()` returns the data type of an object
n = list(zip('abc', [1,2,3]))    # `zip()` returns an iterator of tuples,
                                 # [('a', 1), ('b', 2), ('c', 3)]
file_obj = open('results.txt')   # `open()` opens a file and returns a file object
```

### Defining and calling your own functions
In Python you create self-built functions with the `def()` keyword (short for **function definition**), followed by the name of the function, double parenthesis `()` holding the formal function parameter definitions, and a colon `:`. The body of the function starts at the next line and must be indented. 

Functions are used to group a set of statements, so you can use them multiple times, simply by calling the function instead of copying the statements. Usings functions in your Python code is very useful and common practise to structure and organize your code.

It is possible to define functions that have zero parameters, and it's also possible to add default values to parameters, which are called **optional or default parameters**. Calling a function without explicitly passing in argument values for those default parameters is therefore possible as well. Calling a function by using **keyword arguments** is valid as well, but is used mostly with optional parameters. If you use keyword arguments only for some of the function's arguments, then make sure the positional arguments are used first in the order of how the function is defined.

Please observe the following function example:


```python
# First we define a function named `greeter1()`,
# it doesn't have any arguments
def greeter1():
    print('Hello! How are you doing?')
    
greeter1() # This is how to call a function, in order to execute its code statements
# Hello! How are you doing?

# ----------------------------

# Next we define another function named `greeter2()`,
# which has one argument `name`
def greeter2(name):
    print('Hello ' + name + '! How are you doing?')
    
greeter2('Scipio') # Now we call `greeter2()` by passing a string as `name` argument
# Hello Scipio! How are you doing?

# ----------------------------

# Now we're defining `greeter3()`, having the same code body as `greeter2()`,
# except we're now implementing `name='Everybody` as a default parameter.
def greeter3(name='Everybody'):
    print('Hello ' + name + '! How are you doing?')
    
greeter3() # It's now possible to omit the `name` argument, then its default value is used
# Hello Everybody! How are you doing?

greeter3('Paulag') # But you can of course still pass in a positional value, `'Paulag'` in this case
# Hello Paulag! How are you doing?

greeter3(name='Elear') # You can also call a function using keyword arguments
# Hello Elear! How are you doing?
```

    Hello! How are you doing?
    Hello Scipio! How are you doing?
    Hello Everybody! How are you doing?
    Hello Paulag! How are you doing?
    Hello Elear! How are you doing?


### Returning values
A function can optionally `return` an object, which is usually just one value, but could be multiple values. In case you want to return multiple values, you could for example construct a list or dictionary, but it's also possible to return multiple comma-delimited values. Technically, in the latter case, a tuple will be returned.

Functions are particularly useful for assigning the returned values to a variable, which can be then processed further and/or passed to another function.

Please observe the following examples, regarding returning values:


```python
# Let's make a Fibonacci generating function, 
# which is a sequence where every number in the sequence after the first two
# is the sum of the two preceding numbers.

def fibonacci(max):          # function definition, with an integer `max` argument
    seq = []                 # create an empty list
    a, b = 0, 1              # initialize
    while a <= max:          # execute the iteration as long as the condition 
                             # `a <= max` evaluates to True
        seq.append(a)        # first append the current value of `a` to the list
        a, b = b, a+b        # change `a` to `b` and then set `b` to what `a` was
    return seq               # when `a <= max`` evaluates to False, return the list `seq`

result = fibonacci(1000)     # call `fibonacci()` with a maximum of 1000,
                             # and assign the returned list to the variable `result`
print(result)
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]

# Now let's make a function that returns two values,
# and we can use this to further process the Fibonacci sequence

def evenodd(seq):              # function definition, with a sequence as passed-in argument
    if len(list(seq)) > 0:     # check if the list is not empty
        even = []              # create empty even and odd lists
        odd = []
        for i in list(seq):    # iterate over all elements in the list
            if i%2 == 0:       # this condition evaluates to True for even numbers, false to odds
                even.append(i) # append all numbers to the correct list
            else:
                odd.append(i)
        return even, odd       # return TWO values, which are internally bundled as a tuple

tup = evenodd(result)          # call the `evenodd()` function, pass in the 0..1000 fibonacci sequence

print(type(tup), tup)          # and indeed, the returned values are in tuple form
# <class 'tuple'> ([0, 2, 8, 34, 144, 610], [1, 1, 3, 5, 13, 21, 55, 89, 233, 377, 987])
```

    [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
    <class 'tuple'> ([0, 2, 8, 34, 144, 610], [1, 1, 3, 5, 13, 21, 55, 89, 233, 377, 987])


### Classes
Python is object oriented inside-out, through and through. Even though the section regarding functions might not _seem_ object-oriented, it is indeed. Look for example at the `append()` function (or method) I've been using: it's available to use, because the variables `seq`, `even` and `odd` in the example code above are indeed **objects** of type **list**, and a list, being a sequence, inherits the sequence function (method) `append()`.

Despite this Intro episode already being of a substantial length, I will hereby still briefly touch upon creating and using self-defined Python classes.

Please observe the following code example:


```python
class Utopian:
    '''This is an optional documentation string,
    which could contain a lot of info on how to use
    the class and its attributes.
    '''
    
    userCount = 0
    
    def __init__(self, name, role):
        self.name = name
        self.role = role
        Utopian.userCount += 1
        
    def showProfile(self):
        print('Name:', self.name, ', Role:', self.role)
        
    def getUserTotal(self):
        return self.userCount
    
user1 = Utopian('Scipio', 'Advisor')
user2 = Utopian(role='Moderator', name='Stoodkev')
user3 = Utopian('Mcfarhat', 'Supervisor')
                
user1.showProfile()
print(Utopian.userCount, "Utopians are currently active")
print(Utopian.__doc__)

# Name: Scipio , Role: Advisor
# 3 Utopians are currently active
# This is an optional documentation string,
#   which could contain a lot of info on how to use
#   the class and its attributes.
```

    Name: Scipio , Role: Advisor
    3 Utopians are currently active
    This is an optional documentation string,
        which could contain a lot of info on how to use
        the class and its attributes.
        


**Explanation:**

* the `class` statement, immediately followed by the **class name** `Utopian` creates the class,
* next an optional multi-line documentation string is defined, which is meant to explain to programmers how to use the class. It's a good practise to include **docstrings** in your classes,
* the remainder of the class is called the **class_suite**,
* then the **class variable** `userCount` is defined, holding a value which can be shared by all **class instances**,
* `__init__()` is called the **class constructor**, which Python calls whenever a new class instance is created,
* the other **class methods** are like "normal" functions but need (in the method definition, not in the method call) `self` as its first argument. (In other languages often called `this`).

# What will be covered in the remainder of this Learn Python Series?
A lot! Even though this turned out to be quite a lengthy introduction to the Python 3 programming language, believe me: we've only barely scratched the surface of what can be done using Python. This tutorial series aims to cover just about anything that can be covered about Python. I'll first continue with covering topics bit-by-bit (such as how to deal with string manipulation, handle JSON data, interface with document datastores, visualise data, complex mathematical operations, cryptography, networking, web development, creating command line interfaces, etc. etc.) and explaining how things work. Later on we'll use the knowledge covered in the early episodes to program larger projects (or re-usable modules). We could for example build a web crawler, or an advanced bot interacting with one (or more) blockchains, create a messaging app, a game ... anything! :-)

### Thank you for your time and I hope to see you in the next tutorial episodes!


<br /><hr/><em>Posted on <a href="https://utopian.io/utopian-io/@scipio/learn-python-series-intro">Utopian.io -  Rewarding Open Source Contributors</a></em><hr/>
👍 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,