Python Crash Course

This crash course uses Python 3 because Python 2 has been dead since 2020. The difference between Python 3 and 2 syntax is slightly different, but I don't want to go into that here. This course allows you to learn Python without experience or to warm up your Python skills.

Just like Ruby, Python's syntax is also simple. Python inspired Ruby's syntax because Python is older than Ruby. But, Python is not dead yet. Python is a multipurpose programming language and has a large community. Python touches almost every aspect of software. It could be for the back end of the web with its famous framework, Django. It could be for the back end of desktop applications, video games, or the Internet of Things (IoT). The most popular Python use case today is Data Science. One more thing, Python is also popular in competitive programming.

Whatever game you want to play with Python, you need to master its syntax first, don't skip the basics.

Installation

pyenv

We need Python version management for local development because each project has its own version of Python. I recommend pyenv. You can follow the installation instructions there. I think the instruction is clear enough.

You can add the Python path to the system if you can't set the Python by command. Here is the location, ~/.pyenv/versions/x.x.x/bin. is home. Replace x.x.x with your installed Python version.

Pipenv

It is better to isolate the environment because each project has its versions of Python and packages. That is called a virtual environment. I recommend Pipenv. My reason is it works well with pyenv. You can open the website to look at other reasons why Pipenv and the installation instructions.

The pipenv command is not found? You should add ∼/.local/bin to your system path.

Variables

number = 9
decimal = 9.99
hello1 = "Hello!"
hello2 = 'Hello!'
is_active = false
not_is_active = !is_active

String

print("Hello {}!".format("John Doe")) # Hello John Doe!
print("Hello {name}!".format(name="John Doe")) # Hello John Doe!
print("Hello {name}!".format("John Doe")) # KeyError

print(1 + " + " + 1 + " = " + 2) # TypeError
print("1" + " + " + '1' + " = " + str(2)) # 1 + 1 = 2

print("Paragraph 1\nParagraph 2\nParagraph 3")
print('Paragraph 1\nParagraph 2\nParagraph 3')
print("Paragraph 1\\nParagraph 2\\nParagraph 3") # Paragraph 1\nParagraph 2\nParagraph 3
print("Paragraph 1\nParagraph 2\nParagraph 3') # SyntaxError

print("h" in "hello") # True
print('o' in 'HELLO') # False

hello = "hello"
for c in hello:
  print(c)
for i in range(len(hello)):
  print(hello[i])

Operations

Arithmetic

print(1 + 1) # 2
print(2 - 1) # 1
print(2 / 1) # 1
print(2 * 2) # 4
print(2 ** 3) # 8
print(8 // 3) # 2
print(4 % 2) # 0

Bitwise

print(~7) # -8
print(5 & 3) # 1
print(5 | 3) # 7
print(5 ^ 3) # 6
print(4 >> 1) # 2
print(4 << 1) # 8

and / or

print(True and False) # False
print(True or False) # True

Control

if score >= 100:
  print("Perfect!")
elif score >= 80:
  print("Good!")
elif score >= 70:
  print("Okay.")
else:
  print("Sad...")

print("Passed" if score >= 70 else "Not qualified!")
if score >= 70: print("Congratulations!")

Match

match score:
  case "A":
    print("Very good!")
  case "B":
    print("Good!")
  case default:
    print("Not qualified!")

There is a match syntax in Python 3 (>= 3.10). It is just like the switch in other programming languages. Before 3.10, people prefer to use a dictionary to do the trick.

Try and Except

try:
  print(1 / 0)
except:
  print("sorry, there is an error")

We can use try and except to handle errors or exceptions. It is like Try and Catch in other programming languages like Java and PHP.

try:
  print(1 / 1)
except ZeroDivisionError as e:
  print("cannot be divided by zero")
  print(e)
except (NameError, ValueError):
  print("did you miss something?")
except:
  print("sorry, there is an error")
else:
  print("yes, no error!")
finally:
  print("ah, finally...")

Looping

for i in range(1, 4):
  print(i) # 123

for i in [1, 2, 3]:
  print(i) # 123

i = 1
while i < 4:
  print(i) # 123
  i += 1

i = 1
while True:
  if i > 3:
    break
  print(i) # 123
  i += 1

for i in range(1, 9):
  if i % 2 == 1:
    continue
  print(i)

List

numbers = [1, 2, 3, 4, 5]
unrestricted = [1, 2.3, True, "Hello", 'World!']

numbers.append(6)
unrestricted += [6]

print(numbers[-1])
print(unrestricted[-3:-1])

Sorting

numbers = [3, 4, 1, 5, 2]
numbers.sort() # [1, 2, 3, 4, 5]
numbers.sort(reverse=True) # [5, 4, 3, 2, 1]

Dictionary

map = {
  "a": 1,
  "b": 2,
  "c": 3
}
  
set = {
  1: True,
  2: False,
  3: True
}

print(map["a"]) # 1
print(set.get(1)) # True

print(set.pop(2)) # False
print(set) # {1: True, 3: True}

print(map.keys()) # dict_keys(['a', 'b', 'c'])
print(map.values()) # dict_values([1, 2, 3])
print(map.items()) # dict_items([('a', 1), ('b', 2), ('c', 3)])

map.update(set)
print(map) # {'a': 1, 'b': 2, 'c': 3, 1: True, 3: True}

Method

def power(number, value):
  return number ** value

print(power(2, 3)) # 8
print(power(value=3, number=2)) # 8

Arguments

def sum(*args):
  result = 0
  for number in args:
    result += number
  return result

def my_print(**kwargs):
  print(kwargs)

print(sum(1, 2, 3)) # 6
my_print(a=1, b=2, c=3) # {'a': 1, 'b': 2, 'c': 3}

With an asterisk (*), we can pass several arguments. An asterisk (*) will make a list. Double asterisks (**) will make a dictionary.

Lambda

power = lambda number, value : number ** value

print(power(2, 3)) # 8

Hm, Lambda is about a function in one line.

Built-Ins

There are built-in methods in Python, such as len() to get the length of the list, zip() to combine lists and make them an object, etc. Ever wonder how to get available built-in methods in Python? print(dir(__builtins__)) to get them. Here is the result of Python 3.12.4. It showed all of the error types too.

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BaseExceptionGroup', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EncodingWarning', 'EnvironmentError', 'Exception', 'ExceptionGroup', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

Special Methods

class Number:
  def __init__(self, value):
    self.value = value
  
  def __repr__(self):
    return str(self.value)
  
  def __add__(self, value):
    self.value += value

  def __sub__(self, value):
    self.value -= value

  def __mul__(self, value):
    self.value *= value

  def __truediv__(self, value):
    self.value /= value

number = Number(9)
number + 1
number - 2
number * 3
number / 4

print(number)

There are built-in methods with double underscores (double at the start and double at the end) in Python. From the example above, we can see that the representation of __add__ is +, __sub__ is -, __mul__ is *, and __truediv__ is /. You can visit https://docs.python.org/3/reference/datamodel.html#special-method-names to list all available special methods, especially in Python 3.

Strict

class Number:
  def __init__(self, value: int):
    self.value = value
  
  def __repr__(self) -> str:
    return str(self.value)
  
  def __add__(self, value: int):
    self.value += value

  def __sub__(self, value: int):
    self.value -= value

  def __mul__(self, value: int):
    self.value *= value

  def __truediv__(self, value: int):
    self.value /= value

number = Number(9)
number + 1
number - 2
number * 3
number / 4

print(number)

We can be strict in Python 3. We can set the data types on arguments and returns, but they are optional, just like PHP 8 and TypeScript. You can visit https://docs.python.org/3/library/stdtypes.html to list all available data types.

unittest

import unittest
import number

class TestNumber(unittest.TestCase):
  def test_repr(self):
    num = number.Number(9)
    self.assertEqual(repr(num), "9")
  
  def test_add(self):
    num = number.Number(9)
    num + 1
    self.assertEqual(repr(num), "10")

  def test_sub(self):
    num = number.Number(9)
    num - 1
    self.assertEqual(repr(num), "8")

  def test_mul(self):
    num = number.Number(9)
    num * 3
    self.assertEqual(repr(num), "27")

  def test_truediv(self):
    num = number.Number(9)
    num / 3
    self.assertEqual(repr(num), "3.0")

unittest.main()

Let's write a unit test for the example above. You can save the script from the example above as number.py and this unit test script as number_test.py, then run python number_test.py to execute it.

You can visit https://docs.python.org/3/library/unittest.html for more details.

Object-Oriented Programming

from abc import ABC, abstractmethod

class Animal(ABC):
  def __init__(self, name, feets, has_paws):
    self._name = name
    self._feets = feets
    self._has_paws = has_paws
  
  @property
  def name(self):
    return self._name
  
  @name.setter
  def name(self, name):
    self._name = name
  
  @name.deleter
  def name(self):
    del self._name
  
  @property
  def feets(self):
    return self._feets
  
  @feets.setter
  def feets(self, feets):
    self._feets = feets
  
  @feets.deleter
  def feets(self):
    del self._feets
  
  @property
  def has_paws(self):
    return self._has_paws
  
  @has_paws.setter
  def has_paws(self, has_paws):
    self._has_paws = has_paws
  
  @has_paws.deleter
  def has_paws(self):
    del self._has_paws
  
  @abstractmethod
  def print(self):
    print("{} has {} feets".format(self._name, self._feets))
    if self._has_paws:
      print("{} has paws.".format(self._name))

class Monster(Animal):
  def __init__(self, name, feets, has_paws, abilities):
    super().__init__(name, feets, has_paws)
    self._abilities = abilities
  
  def print(self):
    print("{} is a monster!!!".format(self._name))
    print("{} has:".format(self._name))
    for ability in self._abilities:
      print("- {}".format(ability))

monster = Monster("Dragon", 4, True, ["Nuclear blast", "Ice smoke"])
monster.print()

Multiple Inheritance

...

class Legend:
  def __init__(self, story):
    self.__story = story
  
  def tale(self):
    print("Here is the story...")
    print(self.__story)

class Monster(Animal, Legend):
  def __init__(self, name, feets, has_paws, abilities, story):
    super().__init__(name, feets, has_paws)
    Legend.__init__(self, story)
    self._abilities = abilities
  
  def print(self):
    print("{} is a monster!!!".format(self._name))
    print("{} has:".format(self._name))
    for ability in self._abilities:
      print("- {}".format(ability))

monster = Monster("Dragon", 4, True, ["Nuclear blast", "Ice smoke"], "One day...")
monster.print()
monster.tale()

Python supports multiple inheritance. That means one class can have multiple parents. As we can see in the example above, the first parent of Monster is Animal, that's why super() is for Animal. To call other parents, we need to call their class names instead of super().

Related Articles