Download as pdf or txt
Download as pdf or txt
You are on page 1of 20

Get CS and Programming Tips for Beginners email address Subscribe

Best Way to Learn Python (Step-by-Step Guide)

Python is a very popular language.

It’s also one of the languages that I recommend for beginners to start with.

But how do you go about learning this language?

The best way to learn Python is to understand the big picture of all what you need to learn
before you dive in and start learning.

In this article, I divide the path of learning Python into 6 levels.


Each level covers a subset of the language that you need to master before you move on
to the next one.

My focus on this article is for you to be a competent well-rounded programmer so you


can easily get a job at any tech company that you choose.

But don’t worry, you don’t need to go all the way to level 6 in order to get your first job ‫ق‬

Let’s get started.

Level 0: The Beginnings


This is the level you begin at if you are an absolute beginner.

And by absolute beginner, I mean someone who has never coded before in Python or
any other programming language for that matter.

If you are coming from a different programming language, then you should skip to level 1.

In this level, most of the concepts you will be learning are general programming concepts.
The fundamental skills that will bootstrap you as a programmer.

This means that these concepts are not really exclusive to Python but can be extended to
other programming languages as well.

You see, a lot of programming languages are very similar and knowing what’s common
(and what’s not) between programming languages will help you transition into a different
one in the future.

If you are at this level, then I highly recommend this course on Udemy.
So what are some of these general programming concepts that I am talking about?

Some of these fundamental concepts are variables, data types, operations, functions,
conditionals, and loops.

If you understand what these concepts are, then skip to level 1.

Otherwise, Let me give you a very brief introduction about what these concepts mean.

Variables

Variables are essentially storage for data in your program.

More accurately, it’s a way of giving a name for data for later use.

Let’s look at an example.

# variables
msg = "Hello World!"
print(msg)
# this code outputs Hello World! on the screen

In the Python snippet above, we define a variable msg that stores the value Hello World!

This allows us to later print Hello World! on the screen by just using the variable name that
stores this value instead of having to type the value Hello World! every time we want to
use it.

Data Types

We talked about variables as storage for data, now let’s talk about data.
In Python, data has types.

For example, in the code snippet above, the data Hello World! has a specific type that
Python (and other programming languages) call string.

A String is simply a sequence of characters.

But strings aren’s the only data type in Python, there are also integers, floating-point
numbers, boolean, lists, tuples, and dictionaries.

By the end of level 0, you need to be comfortable with these data types and understand
when (and how) to use them in your program.

Operations

Operations is how you manipulate and change data in your program.

In other words, your programs need to operate on data and produce more data, that you
also operate on, until you reach the final outcome.

This is just the lifecycle of any program.

In Python and all programming languages, there exists at least Arithmetic, Comparison,
and Logic operations.

# an example of an arithmetic operation


x = 5 + 2

# an example of a comparison operation


y = 3 > 4
# an example of a logic operation
z = True or False

Conditionals

In order to write any program that is useful, you almost always will need the ability to
check conditions and change the behavior of the program accordingly.

Conditional statements using if , if else , or if elsif else gives you this ability.

Here is an example of an if-else statement in Python.

>>> if 3 > 5:
... print('3 is greater than 5')
... else:
... print('3 is not greater than 5')
...
3 is not greater than 5
Functions

A function is essentially a block of Python code that only runs when it is called.

You can pass parameters into a function as input and a function can return data as output.

In Python, you define a function using the def keyword.

Here is an example of a hello world program using a function say_hello

def say_hello(msg):
# this is the function
# msg is the input parameter
print(f'hello {msg}')

# calling the say_hello function


say_hello('world')

# output:
# hello world

So this was an example of the fundamental concepts that you should learn at this level.

But most importantly, what you really need to do in order to master this level is to use the
above concepts to solve problems.

You will never be a good programmer if all that you do is read books or take courses.

You need to practice solving problems so get your hands dirty and start solving simple
problems using Python. You can start by solving Project Euler problems.

I can’t stress enough the importance of mastering level 0.


The reason for that is, this level lays the foundation and the fundamental concepts for not
only mastering Python but mastering any other programming language as well.

So even though this is level 0, don’t take it lightly.

Level 1: Object-oriented Programming

Everything in Python is an object.

You either heard this already, or you are destined to hear about it ‫ق‬
But wait a minute, what exactly is an object?

There are many different ways, models, or paradigms to write computer programs.

One of the most popular programming paradigms is called object-oriented programming


(OOP).

In object-oriented programming, an object refers to a particular instance of a Class.

And a Class is like a blueprint of the state and actions that an object can take.

For example, in Python, a Person Class might look something like this.

class Person:
def __init__(self, name, age):
self.name = name
self.age = age

def get_name(self):
return self.name

The class declared above describes the state and actions of any Person object.

For example, any Person object will have a name and an age. These two fields are what
determines the state of the object.

In OOP’s terminology, name and age are called the object attributes.

You can also call get_name() on any Person object to return the name of the person.

We call get_name a method.


And this method, in addition to any other methods that we define, is what determines the
object’s actions.

In other words, a Python object has attributes and methods that are defined in the object’s
Class.

Here’s how to create a Person object

>>> p = Person('Alice', 22)


>>> p.get_name()
'Alice'

Object-oriented programming is essentially one way of structuring and designing your


code.

However, I want you to understand that it is not the only way, and it is not necessarily the
best way.

In order to learn OOP in Python, you need to progress through a few steps.

Step 1: Learn the concepts of OOP

As I mentioned earlier, OOP is a programming paradigm, a way of structuring and


designing your code.

OOP concepts are not exclusive to Python so the concepts you will learn will easily
transition to any other programming language.

Some examples of these concepts are inheritance, encapsulation, and polymorphism.

So make sure you understand these concepts at an abstract level first before you jump
into Python’s OOP.
Step 2: Learn about Python’s Classes and Objects

In this step, you need to apply the abstract concepts you learned in the previous step but
specifically in Python.

Get comfortable with writing Classes and creating Objects.

Write classes that inherit from other classes and investigate the attributes and methods of
the objects created.

Step 3: Solve Python problems using OOP

This is a crucial step.

In this step, you want to learn how to use OOP to design and structure your code.

And as a matter of fact, this step is more of an art than a science. That means the only way
to get better is through practice, practice, and more practice.

Again keep solving more problems using Python, but try to structure your solutions in an
object-oriented way.

The more you practice, the more you will feel at ease with OOP.

Here is a good course on Udemy that pretty much covers level 1.


Level 2: Concurrent and Parallel Programming

The days of single-core processors are far gone.

Nowadays whether you are buying an off-the-shelf laptop or a high-end server for your
business, your processor will definitely have multiple cores.

And sometimes, your program needs to take advantage of these multiple cores to run
things in parallel.

This can potentially lead to increased throughput, higher performance, and better
responsiveness.

But let me be clear about one thing here.


If high performance and increased throughput are absolutely crucial, Python wouldn’t be
the best language to support parallel programming.

In this situation, I would personally prefer golang instead (or good old C).

But since this is an article about Python, let’s keep our focus on Python.

Before you dive in and write your first parallel program, there are some parallel
processing concepts that you should learn about first.

Here are some of these concepts.

Mutual Exclusion

When you have some data that is shared across multiple threads or processes, it is
important to synchronize access to these shared resources.

If you don’t, a race condition can happen which might lead to unexpected and sometimes
disastrous consequences. I will talk more about race conditions later.

Mutual exclusion means that one thread blocks the further progress of other concurrent
threads that require the use of the shared resource.

Locks

Locks is one of the various implementations of mutual exclusion.

To understand what locks are, you can think about them from a conceptual perspective.

If a thread wants to access a shared resource, this thread must grab a lock before it’s
granted access to that resource.
And after it’s done with the resource, it releases this lock.

If the lock is not available because it is grabbed by another thread, then the thread has to
wait for the lock to be released first.

This simple concept guarantees that at most one thread can have access to a shared
resource at a time.

Deadlocks

A deadlock is when your program comes to a complete halt because some of the threads
can’t progress further because they can’t acquire a lock.

For example, imagine Thread A is waiting on Thread B to release a lock. At the same time,
Thread B is waiting on Thread A to release another lock that Thread A is currently holding.

In this dire situation, neither Thread A nor Thread B can progress any further so your
program is hosed!

This is what a deadlock is.

And it happens more often than you think.

To make the situation worse, it’s also one of the hardest problems to debug.

Race conditions

As I mentioned earlier, a race condition is a situation that arises when accessing a shared
resource isn’t protected (for example, by locks).

This can lead to disastrous unexpected outcomes.


Take a look at this example.

import threading
# x is a shared value
x = 0
COUNT = 1000000

def inc():
global x
for _ in range(COUNT):
x += 1

def dec():
global x
for _ in range(COUNT):
x -= 1

t1 = threading.Thread(target=inc)
t2 = threading.Thread(target=dec)
t1.start()
t2.start()
t1.join()
t2.join()

print(x)

Here is what the code above does. There is a shared global variable x that is initialized to
0.

Two functions inc and dec run in parallel. inc() increments the value of x 1 million times
whereas dec() decrements the value of x 1 million times.
By quickly going through the code, it can be concluded that the final value of x should be
0… but is it?

Here is what I get when I run the above code.

$ python3 race.py
158120
$ python3 race.py
137791
$ python3 race.py
-150265
$ python3 race.py
715644

The reason why this is happening is that the shared resource x is not protected (by locks
for example).

Python’s Parallel Programming

Only after you’re comfortable with the concepts discussed above that you are ready to
learn how to write concurrent programs in Python.

First, you should learn how Python’s definition of multiprocessing is different from
multithreading. (By the way, this is completely unrelated to threads and processes from an
OS perspective).

To understand this distinction between multiprocessing and multithreading from Python’s


view, you will need to learn and understand the global interpreter lock (GIL).

You will also need to learn about the threading, queue, and multiprocessing Python
modules.
All of these modules provide you with the primitives you need to write parallel programs.

Here is a good article about multiprocessing in Python.

Level 3: Socket Programming

By now you should be very comfortable writing Python code that runs on a single
machine.

But what if you want to write code that communicates with other machines over a
network?
If you want to do that, then you need to learn about socket programming.

And for that I highly recommend you learn about the basics of computer networks
first. Here’s my favorite book.

After you learn the basic networking concepts, you can use Python’s libraries to write
code on one machine that communicates with code on another.

It’s like magic. I still remember the exhilaration I felt the first time I had two laptops
communicating back and forth to each other over a Wifi network.

Follow these three steps to get started.

Step 1: Write an Echo Program

In this step, you will use Python’s socket module to write a simple TCP server on one
machine and a TCP client on another.

Make sure they are two different computers and that both of them are connected to your
home network.

The idea of the Echo program is simple. The client-side reads a message from the user
and sends this message to the server over the network.

At the server-side, when this message is received, the server echoes the same message
back to the client.

Think of the Echo program as the Hello World program but for socket programming.

After that, you can move on to more complex programs.

Step 2: Play around with HTTP


Once you’re comfortable with writing simple TCP client-server applications, you can start
using Python’s requests module to send and receive HTTP messages.

This is especially useful because the vast majority of web services these days provide an
HTTP API interface that you can interact with programmatically. For example, Facebook,
Twitter, and Google maps all have HTTP API interfaces that your code can communicate
with.

And if you feel a little more adventurous and want to take this a bit further, you can also
scrape the web with BeautifulSoup.

Step 3: Know thy tools

Like any other program, sometimes when you write a networking program, your program
will not work from the first attempt.

However, debugging networking programs is a little different than debugging regular


programs.

That’s why you need to equip yourself with the tools necessary to troubleshoot what’s
going on.

Here are some of the most popular networking tools that you will need.

ping is used to check the connectivity between your machine and another one.
netstat is a versatile networking tool that allows you to, among other things, monitor
network connections both incoming and outgoing.

tcpdump is one of my favorite tools for learning networks. It tools allows you to listen to,
capture, and analyze real packets going into and out of your computer through any
network interface.

Wireshark is a nice GUI interface that does pretty much everything that tcpdump can do. I
recommend starting out with Wireshark before moving on to tcpdump just because it’s a
little more user-friendly.

You might also like