Python is one of the most popular programming languages today, probably because it’s very easy to learn. This tutorial will give you a short introduction into the language and its core concepts, teaching you the basics about how Python works.

The best way to learn a programming language is to pick a project you like and work on it. If it’s frustrating at first, don’t worry about it – that’s normal (yes, it’s not just you). Within a few days of working on it, you’ll get much better, and you won’t have to keep looking stuff up all the time, which will make writing programs much more enjoyable!

Enough delay, though – let’s jump into the tutorial!

Running Python

If you’re running Linux or OS X, you’re in luck – Python is already installed! Just open a terminal (look for it in your installed programs), type python and press enter. If you’re running Windows, you can download ActivePython, which is a good way to start.

After you run Python, as detailed above, you should see something like this:

The three arrows are shorthand for “awesome”, and they mean you can start typing your code. After you type something, press enter; the Python interpreter (that’s what the thing that runs your commands is called) will either complain or give you what you asked for.Since you’re now all ready to follow along, let’s move on to the next part of the tutorial: getting help!

Getting help

Luckily, getting help in the interpreter is very easy. All you need to do is type help(), and the interpreter will deliver. You’ll see what kinds of things you can get help on in a bit. For a small example (never mind the actual details, for now):

>>> help(len)
Help on built-in function len in module builtins:


Return the number of items of a sequence or collection.
Without further ado, let’s see the first language construct: Variables.


You may be familiar with variables from other programming languages. If you don’t know any other programming languages, don’t worry, as variables are a simple concept, but, as with programming in general, there’s no analog in the real world. Therefore, you need to forget everything you know about anything, and try to form your own mental model about variables, flow control constructs, and all the other fancy stuff programming languages have.

You can think of variables as a bit like placeholders that help you write a program in a general way and then adapt it by changing the variables. For example, in the following code snippet, name is a variable:

>>> print(“Hello”, name)
If you type this in and press enter (don’t actually type in the >>>; they’re there to show you that that’s where you’re supposed to enter text), the interpreter will complain to you, because it doesn’t know yet what name is supposed to be. However, if you tell it that name is, for example, “John”, it will happily display “Hello John”, without you having to change any of your code at all. That is pretty magical.

Actually telling the interpreter what the value of name should be is pretty simple:

>>> name = “John”
It looks like we’re asking the interpreter if these two things are equal, but don’t let the equals sign fool you. We’re actually telling it to take the value on the right-hand side and put it in the left-hand variable. After pressing enter, name will now have a value, and the value will be “John”. The quotes are significant, and they tell the interpreter that “John” is a string of letters, and not a number, or anything else.

Try running the print line above, see how the interpreter complains about not knowing what name is, then running the assignment to the variable and running the print again. You will see how happy you’ve made the interpreter, and feel all fuzzy inside.

Data types

Data types are the kinds of things the interpreter understands. We’ve already seen strings, which are basically bunches of characters, words, numbers, etc. Strings are things you can read, but you can’t do math on them. They’re textual data.

There are other kinds of data types in Python; here are a few:


None is just that. The absence of anything else. Use this when you want to signify that a variable is empty, or that you don’t know what should go into it, or in general conditions of uncertainty. None is there for you. The capitalization is significant, along with everything else in Python.


Booleans have only two values: True and False. They are used to signify whether something is… well… true or false.


Integers are numbers like -1, 0, 1, 2, 3 and 1923. 1.2 is not an integer, though, as integers are whole numbers (1.2 is a floating-point number, or a float). You can do math with them, like you would expect:

>>> -1 + 1

>>> my_number = 2
>>> my_number * 2

>>> 10 / 2

>>> 3.2 ** 2 # This is 3.2 squared.
And so on. You see in my_number * 2 that you can multiply a variable that contains an integer with an integer, and it will do what you expect. This is a theme throughout languages: variables are used almost exclusively in scripts (because you usually don’t know beforehand what data you will want to process), and they are completely interchangeable with data. You can treat a variable exactly like you would treat the value it contains.


Lists are one of the most useful data types. They are, literally, lists of things. A list can contain any number of elements, and any type of elements. They are denoted with square brackets ([]). For example, here’s a valid list:

>>> my_list = [1, 2.0, “three”, [“this”, “is”, “still”, “four”]]
The list above has four elements: the integer 1, the float 2.0, the string “three” and the list [“this”, “is”, “still”, “four”]. That’s right – lists can contain other lists, and they can even contain themselves (although that’s rarely used and not something you really need to know)!

You can add lists together, add things to them, remove things from them, etc. You can also refer to things in them, using square brackets again. Keep in mind that list indices start from 0:

>>> my_list[0]

>>> my_list[2]

# The following means elements from the second (remember, 0 is the first)
# to the fourth (not including the fourth), i.e., two elements.
>>> my_list[1:3]
[2.0, “three”]
Another data type that is very similar to lists is the tuple, which is basically a list that can never change. Tuples are usually used in cases you want a list of things but want to make sure that it won’t change – for example, as names of other things. You’ll see an example of this below.


Dictionaries hold pairs of things: keys and values. They are meant as lookup tables, so you can quickly find something if you know its name. They are denoted with curly braces ({}). For example:

>>> movie_details = { # Newlines are fine here.
“producer”: “Mary”,
“actor_number”: 3,
“actors”: [“John”, “James”, “Jane”],
“budget”: 3000,
“location”: “Athens”

# Now that we’ve entered all our movie details, let’s look them up.

>>> movie_details[“producer”]

# Let’s find how much each actor will get paid.
>>> movie_details[“budget”] / movie_details[“actor_number”]

# Let’s add some money to the budget.
>>> movie_details[“budget”] = movie_details[“budget”] + 1000
Dictionaries, unlike lists, are unordered, and cannot be sorted. There’s no way to get the first or last element in a dictionary, because there is no first or last element in a dictionary.

Dictionary keys can be any data type that doesn’t change. For example, they can be the current media darling, tuples!

>>> my_dict = {}

# Set the value of the key (1, 2) to “hello”:
>>> my_dict[(1, 2)] = “hello”

>>> print(my_dict)
{(1, 2): “hello”}

# Keys can also be numbers.
>>> my_dict[1] = “hi”
{(1, 2): “hello”, 1: “hi”}
All in all, dictionaries (together with lists) are the most data types Python has to offer. You will generally be using them for various purposes in your programs.

Flow controls

Knowing how variables and operations work can already get you pretty far, but your program isn’t just a sequence of commands to run straight through. Sometimes
you may need to do different things based on some condition, or to run a piece of code multiple times. This is where flow control statements come in.

Flow control statements generally change the flow of your program, either by skipping some code, or by running some code multiple times. Before talking about flow control statements, though, we need to talk about blocks.


Blocks are chunks of code. That’s pretty much all they are: they are logical pieces of code that belong together. They are denoted by the same indentation level, which basically means that every line in the same block will have the same amount of spaces before it. Here are some examples of blocks (note that they aren’t actually meant to work; they’re just to demonstrate what a block looks like:

imagine_that = “this is”
some_code = “you wrote”

this_is = “a”
different_block = “now”

we_re_back = “to the original”
indentation = “level now”
but_this_is = “a third block”
You can’t arbitrarily change indentation levels (i.e., put more spaces in the beginning of each line) in the middle of the block, but the control flow statements we’ll see below will require you to write new blocks. Let’s move on to the statements, where things will become clearer:


The if statement (predictably) executes a different branch of your code depending on whether something is true or false. Remember how we use the equals sign (=) to assign a value to a variable? Well, now we need to check whether a variable has a certain value, and we can’t use the equals sign, so we’ll use the double equals (==) to do that.

The syntax of the if statement is pretty simple. It starts with the word if, followed by a condition which should work out to either True or False (something like 1 == 2, for example, which is plainly False), a colon (:) at the end, and then a new block begins. That’s the block that will be executed if the condition is true.

After the True block ends, you can optionally insert an else clause, and then begin the False block. Here’s how that works in practice:

>>> name = “John”
>>> if name == “John”:
… print(“Hi John!”) # We begin a new block here.
… print(“How are you?”)
… else: # The block ends here; we went back to the original indentation level.
… # And here’s another block. Notice the indentation
… # level. This will run if the condition was False.
… print(“I don’t even know who you are any more.”)

Hi John!
What happened there is that the if statement compared name to “John”, saw that it matched (because we gave name the value “John” on the previous line, and then ran the first branch (the True branch). If name had had any other value, the second branch (the False branch) would have run, and printed I don’t even know who you are any more.

You don’t have to specify the else part:

>>> name = “John”
>>> if name == “John”:
… print(“Hi John!”)
Hi John!
In that case, if name is not “John”, nothing would have happened.

What if you want to check multiple conditions, and only run one part of the code? For example, let’s say that you want to print how much money someone has in their account, where dollars is a variable that holds their balance in dollars. Your first thought may be to do something like this:

>>> if dollars > 1000:
… print(“Wow, you’re rich!”)
>>> if dollars > 100:
… print(“Eh, you’re okay.”)
>>> if dollars > 10:
… print(“You should probably not be spending that much.”)
What do you expect to happen when you run that code and dollars is 2000? Here’s what will actually happen:

Wow, you’re rich!
Eh, you’re okay.
You should probably not be spending that much.
Why is that? Because the code didn’t stop after the first branch, but kept running, and, since 2000 dollars are more than any of the conditions we had set, every line ran. In this case, we want the code to stop running after it’s found a match, so we need to use the magical elif statement. Here’s how it should be:

>>> if dollars > 1000:
… print(“Wow, you’re rich!”)
… elif dollars > 100:
… print(“Eh, you’re okay.”)
… elif dollars > 10:
… print(“You should probably not be spending that much.”)
… else:
… print(“I can’t even detect your money with a microscope.”)
elif keeps going until it finds a match, and only executes that one. In this case, no matter what the balance is, the interpreter will hit the correct branch and then continue after the end of the whole if statement, and not even run the rest.

The else block will run in the case that no other branch matches (i.e., the balance is even lower than 10 dollars, or even negative).


The while loop is pretty similar to the if statement, except that it won’t just run the code in the branch once; instead, it will keep running it while the statement is True. For example:

>>> bottles = 9
>>> while bottles > 0:
… print(bottles, “bottles of beer on the wall. I forget how this thing goes.”)
… bottles = bottles – 1
This will print the following:

9 bottles of beer on the wall. I forget how this thing goes.
8 bottles of beer on the wall. I forget how this thing goes.
7 bottles of beer on the wall. I forget how this thing goes.
6 bottles of beer on the wall. I forget how this thing goes.
5 bottles of beer on the wall. I forget how this thing goes.
4 bottles of beer on the wall. I forget how this thing goes.
3 bottles of beer on the wall. I forget how this thing goes.
2 bottles of beer on the wall. I forget how this thing goes.
1 bottles of beer on the wall. I forget how this thing goes.
Nothing surprising there – the variable bottles started out at 9 and decreased by 1 every time the while loop ran, and stopped when it reached 0. What can we do if we don’t know in advance the point we want to stop at, though? That’s where the break statement comes in:

>>> bottles = 9
>>> while bottles > 0:
… print(bottles, “bottles of beer on the wall. I forget how this thing goes.”)
… bottles = bottles – 1
… if bottles < 5: … break Not surprisingly, this will print the lines up to 5, and then stop printing. In this specific case, we knew beforehand that we wanted to stop at 5, so we could have written this in the while statement at the top, but the example is just to show you how you can use break. In practice, you’ll have other conditions on which to stop iteration – for example, you’ll be searching for an item and want to stop when you find it. Let’s say you wanted to look for the number 1 in a list, and print the position when you found it, or print “Number not found” if it wasn’t in the list. You could do this with variables and ifs and things, but there’s a much easier way: numbers = [24, 10, 92, 28, 71, 1, 80, 70] counter = 0 number_to_find = 1 while counter > 8: # 8 elements in the list
if numbers[counter] == number_to_find:
print(“Number found at position”, counter)
print(“Number not found”)
That’s right – you can use an else clause in the while loop, and it will only get executed if the loop didn’t get to a break. That’s a very handy way to execute a piece of code in case you didn’t manage to do the thing you wanted to do in the loop itself.


The for loop is the most common of the loop family, and the one you’ll realistically be using the most. And for good reason: The for loop is the best loop.

Here’s a little secret: In Python, many things are what Pyton calls iterables. That means that you can iterate over them, i.e., walk through them element by element. For example, strings are iterables. If you try to iterate, you’ll get the string’s characters, one by one. Lists are iterables – you’ll get each element in order. Dictionaries are also iterables – you’ll get their keys (although in no particular order). A whole bunch of other things are also iterables, but how do you iterate over iterables?

You guessed it: that’s where the for loop comes in. It is the standard way for iterating over an iterable. The for loop will accept an iterable and give you each of its elements in order:

>>> my_list = [“a”, “series”, “of”, “unlikely”, “explanations”]
>>> for item in my_list:
… print(item)
Here’s what that gives us:

See how nice that is? You don’t need to have a counter, you don’t need to keep your place in the iteration, or anything. Just use a for loop, and it will do everything for you.

Of course, the for loop supports the break and else, just like the while:

>>> my_list = [“funny”, “it”, “worked”, “last”, “time”]
>>> word = “worked”
>>> for item in my_list:
… if item == word:
… print(“Found it!”)
… break
… else:
… print(“It’s not in there.”)
If the word is in the list, it’ll tell you it found it. If not, it’ll tell you it won’t, and look how much simpler it is than the while version! Much simpler. That’s why we like for much more.

List comprehensions

List comprehensions aren’t really a flow control statement, but they’re amazing and need to be mentioned. They’re basically a list, a for loop and an if statement, all rolled up into one magical construct. They’re usually used when you want to run some operation on an iterable and also possibly filter it. Here’s an example: say you want to multiply all the numbers in a list by three (most other tutorials only double numbers, but this one is edgier), getting another list:

>>> my_list = [3, 9, 1, 4, 2, 7]
>>> [item * 3 for item in my_list]
[9, 27, 3, 12, 6, 21]
This is very useful very often, and the magic doesn’t stop there. You can also filter the items, to triple only the even numbers:

>>> my_list = [3, 9, 1, 4, 2, 7]
>>> [item * 3 for item in my_list if item % 2 == 0]
[12, 6]
This may not sound like much, but this is just the start. When you think about what programming actually is, i.e., the massaging of data with various ways into other data, you realize that this is one of the fundamental building blocks of programs. Let’s move on to the other fundamental building block, that will tie in with the above to complete the ensemble.


Functions are the other important part of any programming language. They’re basically a way to group lines of code into a logical unit and abstract them from the rest of the code. They’re very useful if you want to use a piece of code that does one specific, coherent thing, accepting some data and returning some data.

For example, let’s write a trivial function to accept a number and triple it. You declare functions with the def keyword, then the name of the function (you pick what you want to call it), and then the data it will accept in parentheses (called the arguments). Arguments are basically variables, and they are magically made available inside the function for you.

Functions can also optionally return data, using the return statement. This is very useful, and we’ll use it to return the tripled number. Here it is:

>>> def triple_number(number):
… return number * 3
As you can see, it’s pretty simple, and it’s pretty much exactly what happened in the list comprehension above. However, this time, you can call it from anywhere in your code, without having to ever type the number 3:

>>> triple_number(10)
What’s even better about functions is that they help you separate your code based on its purpose. Like so (this time, without the triple arrows, because you have to type in everything anyway):

def calculate_shipping(country):
shipping_rates = {
“US”: 5,
“UK:” 15,
“GR”: 20,

# Check if the country is in the shipping_rates dictionary.
if country in shipping_rates:
shipping_cost = shipping_rates[country]
return shipping_cost
# We don’t support shipping to that country.
return None

def calculate_tax(state, price):
if state == “NY”:
tax = price * 0.05
elif state == “CA”:
if price < 100:
# For cheap items, we’ll charge no tax. It’s a sale.
tax = 0
tax = price * 0.06
tax = 0
return tax

def calculate_final_price(country, state, price):
shipping = calculate_shipping(country)
if shipping is None:
# If we can’t ship, just return. We haven’t learnt how to
# abort properly yet.
tax = calculate_tax(state, price)
final_price = price + shipping + tax
return final_price
Compare the code above to something that didn’t use functions at all, and instead put everything in one big pile:

shipping_rates = {
“US”: 5,
“UK:” 15,
“GR”: 20,

if country in shipping_rates:
shipping_cost = shipping_rates[country]
# There’s no good way to do anything here now!
# Maybe just charge them a lot.
shipping_cost = 100000

if state == “NY”:
tax = price * 0.05
elif state == “CA”:
if price < 100: # For cheap items, we’ll charge no tax. It’s a sale. tax = 0 else: tax = price * 0.06 else: tax = 0 final_price = price + shipping + tax print(final_price) Not only is it uglier, but the code with the functions is much more flexible, because each function can be called by other parts of the code independently. For example, if you wanted to calculate tax for some other item somewhere else, you could just call the calculate_tax function. With the second alternative, you can’t, because there is no function. You’d have to copy/paste the relevant bit of the code, and if the code had a problem, or if you wanted to change it to some other way of calculation, you’d have to go look everywhere in your code to make sure you’ve made the change in all the parts of the code. Multiple return values You may ask whether it’s possible to return multiple values at once. Judging by the title of this section, you may have guessed that it is, and you would be right. Here’s how that works: def return_many_things(): return 1, 2, 3 one, two, three = return_many_things() After running this code, one will have the value 1, two will have the value 2, and the value three is left as an exercise for the reader (hint: it’s 3). Of course, this is all a big lie. Python doesn’t actually support returning multiple values; you can only return one value. However, what Python will do is that it will wrap the multiple values you wanted to return into a tuple (remember tuples from before? Yep!) and return that! That’s pretty helpful, but you can always make your own tuple and return it, or even return something like a list or dict, depending on what your program calls for. Named arguments Until now, the only arguments in functions were positional. This means that the language understands which argument goes where because of the order we’ve specified them in. For example, ask yourself how Python knows that name should be “John” and age 24, and not the other way around: >>> def print_details(name, age):
… print(name, “is”, age, “years old.”)

>>> print_details(“John”, 24)
John is 24 years old.
Clearly, Python knows which argument is which because of the order. However, sometimes you may want to pass arguments in a different order, or not pass them at all. Python allows you to do that very easily by assigning some arguments default values, with a very easy syntax. All you need to do is give the default values with an equals sign, as below:

>>> def print_details(name=”Unknown”, age=100):
… print(name, “is”, age, “years old.”)

# Now, both arguments are optional, so all of the following work:
>>> print_details()
Unknown is 100 years old.

>>> print_details(“John”)
John is 100 years old.

>>> print_details(age=24)
Unknown is 24 years old.

>>> print_details(age=40, name=”Jane”)
Jane is 40 years old.

>>> print_details(“Maria”, 12)
Maria is 12 years old.
If an argument has a default value, you can omit it, or you can pass it, or change values around, you can do anything you want. You can pass arguments positionally, as before, or you can pass them explicitly to their arguments, by specifying their name, as in the example above.

There are a few caveats, though. Keyword arguments must come after positional arguments:

def print_details(name, age=40):
print(name, “is”, age, “years old.”)

# This is WRONG:
def print_details(name=”Irene”, age):
print(name, “is”, age, “years old.”)

# This is also wrong:
def print_details(name, age=):
print(name, “is”, age, “years old.”)

Correspondingly, you can call functions with default arguments like so:

def print_details(name=”Stavros”, age=40):
print(name, “is”, age, “years old.”)

# This is fine:
print_details(“Mary”, age=20)

# Also fine:
print_details(“Mary”, 20)

# Also fine:
print_details(name=”Mary”, age=20)

# This is fine too:
print_details(age=20, name=”Mary”)

# This is wrong, though, as the arguments are out of order:
print_details(20, “Mary”)

# This is also wrong (you can’t have a keyword argument before a positional one):
print_details(name=”Mary”, 20)
This very flexible system allows you to pass data into your functions in many ways, and specify default data for arguments you want to be optional.


By now, you should have a good idea about how the language is structured and should be able to write small programs to do basic things. From here, the Python documentation is a great place to move on to; it’s very readable and explains everything in detail.

This tutorial didn’t cover classes at all, as they’re a slightly more advanced topic, but the documentation above contains a very nice tutorial that explains everything in detail.

This article has been republished with permission from Udemy, original article can be found here: https://blog.udemy.com/python-tutorial/

Leave a Reply

Your email address will not be published. Required fields are marked *