Robert Johns | 01 Aug, 2024
Fact checked by Jim Markus

30 Best Python Projects Beginner to Pro With Code [2024]

If I could go back in time to help my younger self learn Python, I'd tell them to build more Python projects!

That's exactly why I wrote this article: to share 30 Python projects to help programmers like you.

Whether you’re looking to start a career in Python development or enhance your portfolio, these Python projects are perfect for leveling up your Python skills.

I’ve personally designed each of these Python projects, including a range of step-by-step tutorials so you can follow along with me to get hands-on and code some cool stuff.

You can think of these tutorial projects as taking a free Python course while growing your Python portfolio!

I'm also regularly adding new Python projects with step-by-step tutorials, so make sure you bookmark this page and check back for the latest Python projects to grow your skills.

Without further ado, let’s dive in and start building with Python!

Plus, if you're looking for some extra help, I've also released my own course, Python with Dr. Johns, where I take an academic approach to teaching while also building portfolio-worthy Python projects.

Best Python Projects for Beginners in 2024

1. Python Hangman Game with GUI

Build your own Python Hangman Game

What is this Python project?

In this Python project, you'll build a Hangman game, an engaging and fun game that challenges users to guess words letter by letter.

I've also designed this project to be a step-by-step tutorial so you can follow along with me to build something very cool and fun!

This project also goes beyond merely creating a functional application; it serves as an excellent example of utilizing Python's simplicity and the Tkinter library to create interactive and visually appealing desktop applications.

It's also a perfect addition to your portfolio, particularly if you're looking to demonstrate your proficiency in Python development, as it showcases fundamental programming concepts in a context that's interactive while also showing your understanding of user interface design and event-driven programming.

So get ready and fire up your favorite Python IDE, and let's get building!

Python Skills Covered:

  • Game Logic: Craft the core logic for processing guesses, managing game states, and determining win or loss conditions, offering a deep dive into conditional statements and data structures.
  • Dynamic UI Updates: Utilize Tkinter to dynamically update the game interface, reflecting the progress of the game and user interactions in real-time, thus enriching the user experience.
  • Event Handling: Employ event listeners to capture user inputs such as letter guesses and actions to restart or exit the game, showcasing how to interact with GUI elements in Python.
  • User Interface Design: Use Tkinter to design a clean, intuitive interface for the Hangman game, demonstrating skills in creating visually appealing and user-friendly desktop applications.
  • Tkinter and Python Basics: Harness the power of Python and its standard GUI toolkit, Tkinter, to implement and manage the game's interface.
  • Best Practices in Python: Write clean, efficient, and well-documented Python code, adhering to best practices for code structure, readability, and maintainability.

Build This Python Project Here

2. Mad Libs Generator 

This is one of the most fun beginner Python projects, not to mention it lets you practice how to use strings, variables, and concatenation, which are essential skills for all Python applications at all skill levels.

The Mad Libs Generator gathers and manipulates user input data as an adjective, a pronoun, and a verb. The program takes this data and arranges it to build a story.

Source Code:

'''
Mad Libs Generator
-------------------------------------------------------------
'''

# Questions for the user to answer

noun = input('Choose a noun: ')

p_noun = input('Choose a plural noun: ')

noun2 = input('Choose a noun: ')

place = input('Name a place: ')

adjective = input('Choose an adjective (Describing word): ')

noun3 = input('Choose a noun: ')

# Print a story from the user input

print('------------------------------------------')

print('Be kind to your', noun, '- footed', p_noun)

print('For a duck may be somebody\'s', noun2, ',')

print('Be kind to your', p_noun, 'in', place)

print('Where the weather is always', adjective, '. \n')

print('You may think that is this the', noun3, ',')

print('Well it is.')

print('------------------------------------------')

3. Number Guessing 

This beginner Python project is a fun game that generates a random number (in a certain range) that the user must guess after receiving hints. For each wrong guess the user makes, they receive extra hints but at the cost of worsening their final score.

This program is a great way to experiment with the Python standard library, as it uses the Python random module to generate random numbers. You can also get some hands-on practice with conditional statements, print formatting, user-defined functions, and various Python operators.

Source Code:

'''
Number Guessing Game
-------------------------------------------------------------
'''

import random


def show_score(attempts_list):
    if not attempts_list:
        print('There is currently no best score,'
              ' it\'s yours for the taking!')

    else:
        print(f'The current best score is'
              f' {min(attempts_list)} attempts')


def start_game():
    attempts = 0
    rand_num = random.randint(1, 10)
    attempts_list = []

    print('Hello traveler! Welcome to the game of guesses!')
    player_name = input('What is your name? ')
    wanna_play = input(
        f'Hi, {player_name}, would you like to play '
        f'the guessing game? (Enter Yes/No): ')

    if wanna_play.lower() != 'yes':
        print('That\'s cool, Thanks!')
        exit()
    else:
        show_score(attempts_list)

    while wanna_play.lower() == 'yes':
        try:
            guess = int(input('Pick a number between 1 and 10: '))
            if guess < 1 or guess > 10:
                raise ValueError(
                    'Please guess a number within the given range')

            attempts += 1

            if guess == rand_num:
                attempts_list.append(attempts)
                print('Nice! You got it!')
                print(f'It took you {attempts} attempts')
                wanna_play = input(
                    'Would you like to play again? (Enter Yes/No): ')
                if wanna_play.lower() != 'yes':
                    print('That\'s cool, have a good one!')
                    break
                else:
                    attempts = 0
                    rand_num = random.randint(1, 10)
                    show_score(attempts_list)
                    continue
            else:
                if guess > rand_num:
                    print('It\'s lower')
                elif guess < rand_num:
                    print('It\'s higher')

        except ValueError as err:
            print('Oh no!, that is not a valid value. Try again...')
            print(err)


if __name__ == '__main__':
    start_game()

4. Rock Paper Scissors

This Rock Paper Scissors program simulates the universally popular game with functions and conditional statements. So, what better way to get these critical concepts under your belt? You'll also be using the Python list to store a collection of valid responses, which you can then use to create an elegant and Pythonic conditional statement.

As one of many Python coding projects that imports additional libraries, this program uses the standard library’s random, os, and re modules.

Take a look at the code below, and you’ll see that this Python project idea asks the user to make the first move by passing in a character to represent rock, paper, or scissors. After evaluating the input string, the conditional logic checks for a winner.

Updated! I've recently updated this rock paper scissors python project to include a score-keeping system. It tracks the user's score and the computer's score. It also displays that score between rounds and at the end of the game.

There's one more update here. I wanted to accept a single letter "Y" for those who want to keep playing. Before, you had to type of out "yes". I've left off the ability to accept "N" for "no". That's an easy challenge for those who want to improve my rock paper scissors python project.

Source Code:

'''
Rock Paper Scissors
-------------------------------------------------------------
'''


import random
import os
import re


def check_play_status():
  valid_responses = ['yes', 'no', 'y']
  while True:
      try:
          response = input('Do you wish to play again? (Yes or No): ')
          if response.lower() not in valid_responses:
              raise ValueError('Yes or No only')

          if response.lower() == 'yes':
              return True
          elif response.lower() =='y':
              return True
          else:
              os.system('cls' if os.name == 'nt' else 'clear')
              print('Thanks for playing!')
              print(f'Final Score - You: {user_score}, Computer: {computer_score}')
              exit()

      except ValueError as err:
          print(err)


def play_rps():
    user_score = 0
    computer_score = 0
    play = True

    while play:
       os.system('cls' if os.name == 'nt' else 'clear')
       print('')
       print('Rock, Paper, Scissors - Shoot!')

       user_choice = input('Choose your weapon'
                           ' [R]ock], [P]aper, or [S]cissors: ')

       if not re.match("[SsRrPp]", user_choice):
           print('Please choose a letter:')
           print('[R]ock, [P]aper, or [S]cissors')
           continue

       print(f'You chose: {user_choice}')

       choices = ['R', 'P', 'S']
       opp_choice = random.choice(choices)

       print(f'I chose: {opp_choice}')

       if opp_choice == user_choice.upper():
           print('Tie!')
           print(f'Score - You: {user_score}, Computer: {computer_score}')
           play = check_play_status()
       elif opp_choice == 'R' and user_choice.upper() == 'S':
           print('Rock beats scissors, I win!')
           computer_score += 1
           print(f'Score - You: {user_score}, Computer: {computer_score}')
           play = check_play_status()
       elif opp_choice == 'S' and user_choice.upper() == 'P':
           print('Scissors beats paper! I win!')
           computer_score += 1
           print(f'Score - You: {user_score}, Computer: {computer_score}')
           play = check_play_status()
       elif opp_choice == 'P' and user_choice.upper() == 'R':
           print('Paper beats rock, I win!')
           computer_score +=1
           print(f'Score - You: {user_score}, Computer: {computer_score}')
           play = check_play_status()
       else:
           print('You win!\n')
           user_score += 1
           print(f'Score - You: {user_score}, Computer: {computer_score}')
           play = check_play_status()

if __name__ == '__main__':
   play_rps()

5. Dice Roll Generator

As one of the most relatable Python projects for beginners with code, this program simulates rolling one or two dice. It’s also a great way to solidify your understanding of user-defined functions, loops, and conditional statements. These are fundamental skills for Python beginners and are likely to be some of the first things you’d learn, whether that’s from an online course or a Python book.

As one of our easy Python projects, it’s a fairly simple program that uses the Python random module to replicate the random nature of rolling dice. You’ll also notice that we use the os module to clear the screen after you’ve rolled the dice.

Note that you can change the maximum dice value to any number, allowing you to simulate polyhedral dice often used in many board and roleplaying games.

Source Code:

'''
Dice Roll Generator
-------------------------------------------------------------
'''


import random
import os


def num_die():
  while True:
      try:
          num_dice = input('Number of dice: ')
          valid_responses = ['1', 'one', 'two', '2']
          if num_dice not in valid_responses:
              raise ValueError('1 or 2 only')
          else:
              return num_dice
      except ValueError as err:
          print(err)


def roll_dice():
   min_val = 1
   max_val = 6
   roll_again = 'y'

   while roll_again.lower() == 'yes' or roll_again.lower() == 'y':
       os.system('cls' if os.name == 'nt' else 'clear')
       amount = num_die()

       if amount == '2' or amount == 'two':
           print('Rolling the dice...')
           dice_1 = random.randint(min_val, max_val)
           dice_2 = random.randint(min_val, max_val)

           print('The values are:')
           print('Dice One: ', dice_1)
           print('Dice Two: ', dice_2)
           print('Total: ', dice_1 + dice_2)

           roll_again = input('Roll Again? ')
       else:
           print('Rolling the die...')
           dice_1 = random.randint(min_val, max_val)
           print(f'The value is: {dice_1}')

           roll_again = input('Roll Again? ')


if __name__ == '__main__':
   roll_dice()

6. Password Strength Checker

If you fancy learning how to create an app, this Python project could be a great addition, as it lets you check whether your password is strong enough.

It does this by checking the number of letters, numbers, special characters, and whitespace characters within a given password and generating a score based on these results. So, it’s another great way to learn about conditional statements, functions, and string formatting.

We also use the string and getpass modules from the Python standard library. This allows us to access the full range of string characters to compare with our password’s character composition, while the .getpass() function lets us hide our password when we enter it.

Source Code:

'''
Password Strength Checker
-------------------------------------------------------------
'''


import string
import getpass


def check_password_strength():
   password = getpass.getpass('Enter the password: ')
   strength = 0
   remarks = ''
   lower_count = upper_count = num_count = wspace_count = special_count = 0

   for char in list(password):
       if char in string.ascii_lowercase:
           lower_count += 1
       elif char in string.ascii_uppercase:
           upper_count += 1
       elif char in string.digits:
           num_count += 1
       elif char == ' ':
           wspace_count += 1
       else:
           special_count += 1

   if lower_count >= 1:
       strength += 1
   if upper_count >= 1:
       strength += 1
   if num_count >= 1:
       strength += 1
   if wspace_count >= 1:
       strength += 1
   if special_count >= 1:
       strength += 1

   if strength == 1:
       remarks = ('That\'s a very bad password.'
           ' Change it as soon as possible.')
   elif strength == 2:
       remarks = ('That\'s a weak password.'
           ' You should consider using a tougher password.')
   elif strength == 3:
       remarks = 'Your password is okay, but it can be improved.'
   elif strength == 4:
       remarks = ('Your password is hard to guess.'
           ' But you could make it even more secure.')
   elif strength == 5:
       remarks = ('Now that\'s one hell of a strong password!!!'
           ' Hackers don\'t have a chance guessing that password!')

   print('Your password has:-')
   print(f'{lower_count} lowercase letters')
   print(f'{upper_count} uppercase letters')
   print(f'{num_count} digits')
   print(f'{wspace_count} whitespaces')
   print(f'{special_count} special characters')
   print(f'Password Score: {strength / 5}')
   print(f'Remarks: {remarks}')


def check_pwd(another_pw=False):
   valid = False
   if another_pw:
       choice = input(
           'Do you want to check another password\'s strength (y/n) : ')
   else:
       choice = input(
           'Do you want to check your password\'s strength (y/n) : ')

   while not valid:
       if choice.lower() == 'y':
           return True
       elif choice.lower() == 'n':
           print('Exiting...')
           return False
       else:
           print('Invalid input...please try again. \n')


if __name__ == '__main__':
   print('===== Welcome to Password Strength Checker =====')
   check_pw = check_pwd()
   while check_pw:
       check_password_strength()
       check_pw = check_pwd(True)

7. Number to Words

This Python project idea converts an integer number provided via user input to its equivalent words. This program is set up to support numbers with a maximum of 12 digits, but feel free to modify the program to handle larger numbers (hint: requires conditional statements and loops).

As an easy-to-understand example of basic Python projects, this simple but effective program can expand your skills with loops, user input, and conditional statements, not to mention Python tuples and lists.

You’ll also be able to experiment with some mathematical operations that may be new to you like the modulo (%) operator to return the remainder from integer division.

If any of these techniques are new to you, you might consider installing an AI coding assistant in your Python IDE to help offer help with any code blocks you find challenging to understand.

Source Code:

'''
Numbers To Words
-------------------------------------------------------------
'''


ones = (
   'Zero', 'One', 'Two', 'Three', 'Four',
   'Five', 'Six', 'Seven', 'Eight', 'Nine'
   )

twos = (
   'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen',
    'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen'
   )

tens = (
   'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty',
    'Seventy', 'Eighty', 'Ninety', 'Hundred'
   )

suffixes = (
   '', 'Thousand', 'Million', 'Billion'
   )

def fetch_words(number, index):
   if number == '0': return 'Zero'

   number = number.zfill(3)
   hundreds_digit = int(number[0])
   tens_digit = int(number[1])
   ones_digit = int(number[2])

   words = '' if number[0] == '0' else ones[hundreds_digit]
  
   if words != '':
       words += ' Hundred '

   if tens_digit > 1:
       words += tens[tens_digit - 2]
       words += ' '
       words += ones[ones_digit]
   elif(tens_digit == 1):
       words += twos[((tens_digit + ones_digit) % 10) - 1]
   elif(tens_digit == 0):
       words += ones[ones_digit]

   if(words.endswith('Zero')):
       words = words[:-len('Zero')]
   else:
       words += ' '

   if len(words) != 0:
       words += suffixes[index]
      
   return words


def convert_to_words(number):
   length = len(str(number))
   if length > 12:
       return 'This program supports a maximum of 12 digit numbers.'

   count = length // 3 if length % 3 == 0 else length // 3 + 1
   copy = count
   words = []

   for i in range(length - 1, -1, -3):
       words.append(fetch_words(
           str(number)[0 if i - 2 < 0 else i - 2 : i + 1], copy - count))
      
       count -= 1

   final_words = ''
   for s in reversed(words):
       final_words += (s + ' ')

   return final_words

if __name__ == '__main__':
   number = int(input('Enter any number: '))
   print('%d in words is: %s' %(number, convert_to_words(number)))

8. Tic-Tac-Toe Game

Tic-Tac-Toe is a classic two-player game that involves a nine-square grid. Each player alternately marks their space with an O or an X, and whichever player manages to mark three Os or Xs diagonally, horizontally, or vertically wins. Each player must also block their opponent while attempting to make their chain.

This is a really fun Python project that’s unique for beginners, as it uses object-oriented programming. 

This is one of the most essential Python concepts to learn, and in this project, you will create a new class called TicTacToe. We’ll then use this to represent the game's features via the class attributes and methods.

Carefully study these methods to see how we can use object-oriented programming to neatly package the various behaviors needed to simulate this game.

Some new aspects of this Python project idea for beginners include nested loops to check the grid's columns, rows, and diagonals for a winning state, along with the Python set data type, which is used to contain unique values. This program also uses the Python random module to select a random player to start the game, but this is more familiar to you now.

Source Code:

 

'''
Tic Tac Toe
-------------------------------------------------------------
'''


import random


class TicTacToe:

   def __init__(self):
       self.board = []

   def create_board(self):
       for i in range(3):
           row = []
           for j in range(3):
               row.append('-')
           self.board.append(row)

   def get_random_first_player(self):
       return random.randint(0, 1)

   def fix_spot(self, row, col, player):
       self.board[row][col] = player

   def has_player_won(self, player):
       n = len(self.board)
       board_values = set()

       # check rows
       for i in range(n):
           for j in range(n):
               board_values.add(self.board[i][j])

           if board_values == {player}:
               return True
           else:
               board_values.clear()

       # check cols
       for i in range(n):
           for j in range(n):
               board_values.add(self.board[j][i])

           if board_values == {player}:
               return True
           else:
               board_values.clear()

       # check diagonals
       for i in range(n):
           board_values.add(self.board[i][i])
       if board_values == {player}:
           return True
       else:
           board_values.clear()
      
       board_values.add(self.board[0][2])
       board_values.add(self.board[1][1])
       board_values.add(self.board[2][0])
       if board_values == {player}:
           return True
       else:
           return False

   def is_board_filled(self):
       for row in self.board:
           for item in row:
               if item == '-':
                   return False
       return True

   def swap_player_turn(self, player):
       return 'X' if player == 'O' else 'O'

   def show_board(self):
       for row in self.board:
           for item in row:
               print(item, end=' ')
           print()

   def start(self):
       self.create_board()
       player = 'X' if self.get_random_first_player() == 1 else 'O'
       game_over = False

       while not game_over:
           try:
               self.show_board()
               print(f'\nPlayer {player} turn')

               row, col = list(
                   map(int, input(
                       'Enter row & column numbers to fix spot: ').split()))
               print()

               if col is None:
                   raise ValueError(
                       'not enough values to unpack (expected 2, got 1)')

               self.fix_spot(row - 1, col - 1, player)

               game_over = self.has_player_won(player)
               if game_over:
                   print(f'Player {player} wins the game!')
                   continue

               game_over = self.is_board_filled()
               if game_over:
                   print('Match Draw!')
                   continue

               player = self.swap_player_turn(player)

           except ValueError as err:
               print(err)

       print()
       self.show_board()


if __name__ == '__main__':
  tic_tac_toe = TicTacToe()
  tic_tac_toe.start()

9. Calculator

Another of our easy Python projects, this program creates a basic calculator application with addition, subtraction, multiplication, and division functions.

This is one of the Python practice projects that are great for learning how to use loops, functions, conditional statements, user input, and string formatting. We’ve also used the Python os module to clear the screen after the user completes their calculation actions.

Once you have the concepts under your belt with this project, consider ways to extend the features to include exponentiation or other more complicated calculations.

If you’re already using an AI coding assistant like GitHub Copilot or Amazon CodeWhisperer, you could also consider experimenting with this to add new features. Try to do it yourself first though!

Sample Code:

'''
Calculator
-------------------------------------------------------------
'''


import os


def addition():
   os.system('cls' if os.name == 'nt' else 'clear')
   print('Addition')

   continue_calc = 'y'

   num_1 = float(input('Enter a number: '))
   num_2 = float(input('Enter another number: '))
   ans = num_1 + num_2
   values_entered = 2
   print(f'Current result: {ans}')

   while continue_calc.lower() == 'y':
       continue_calc = (input('Enter more (y/n): '))
       while continue_calc.lower() not in ['y', 'n']:
           print('Please enter \'y\' or \'n\'')
           continue_calc = (input('Enter more (y/n): '))

       if continue_calc.lower() == 'n':
           break
       num = float(input('Enter another number: '))
       ans += num
       print(f'Current result: {ans}')
       values_entered += 1
   return [ans, values_entered]


def subtraction():
   os.system('cls' if os.name == 'nt' else 'clear')
   print('Subtraction')

   continue_calc = 'y'

   num_1 = float(input('Enter a number: '))
   num_2 = float(input('Enter another number: '))
   ans = num_1 - num_2
   values_entered = 2
   print(f'Current result: {ans}')

   while continue_calc.lower() == 'y':
       continue_calc = (input('Enter more (y/n): '))
       while continue_calc.lower() not in ['y', 'n']:
           print('Please enter \'y\' or \'n\'')
           continue_calc = (input('Enter more (y/n): '))

       if continue_calc.lower() == 'n':
           break
       num = float(input('Enter another number: '))
       ans -= num
       print(f'Current result: {ans}')
       values_entered += 1
   return [ans, values_entered]


def multiplication():
   os.system('cls' if os.name == 'nt' else 'clear')
   print('Multiplication')

   continue_calc = 'y'

   num_1 = float(input('Enter a number: '))
   num_2 = float(input('Enter another number: '))
   ans = num_1 * num_2
   values_entered = 2
   print(f'Current result: {ans}')

   while continue_calc.lower() == 'y':
       continue_calc = (input('Enter more (y/n): '))
       while continue_calc.lower() not in ['y', 'n']:
           print('Please enter \'y\' or \'n\'')
           continue_calc = (input('Enter more (y/n): '))

       if continue_calc.lower() == 'n':
           break
       num = float(input('Enter another number: '))
       ans *= num
       print(f'Current result: {ans}')
       values_entered += 1
   return [ans, values_entered]


def division():
   os.system('cls' if os.name == 'nt' else 'clear')
   print('Division')

   continue_calc = 'y'

   num_1 = float(input('Enter a number: '))
   num_2 = float(input('Enter another number: '))
   while num_2 == 0.0:
       print('Please enter a second number > 0')
       num_2 = float(input('Enter another number: '))

   ans = num_1 / num_2
   values_entered = 2
   print(f'Current result: {ans}')

   while continue_calc.lower() == 'y':
       continue_calc = (input('Enter more (y/n): '))
       while continue_calc.lower() not in ['y', 'n']:
           print('Please enter \'y\' or \'n\'')
           continue_calc = (input('Enter more (y/n): '))

       if continue_calc.lower() == 'n':
           break
       num = float(input('Enter another number: '))
       while num == 0.0:
           print('Please enter a number > 0')
           num = float(input('Enter another number: '))
       ans /= num
       print(f'Current result: {ans}')
       values_entered += 1
   return [ans, values_entered]


def calculator():
   quit = False
   while not quit:
       results = []
       print('Simple Calculator in Python!')
       print('Enter \'a\' for addition')
       print('Enter \'s\' for substraction')
       print('Enter \'m\' for multiplication')
       print('Enter \'d\' for division')
       print('Enter \'q\' to quit')

       choice = input('Selection: ')

       if choice == 'q':
           quit = True
           continue

       if choice == 'a':
           results = addition()
           print('Ans = ', results[0], ' total inputs: ', results[1])
       elif choice == 's':
           results = subtraction()
           print('Ans = ', results[0], ' total inputs: ', results[1])
       elif choice == 'm':
           results = multiplication()
           print('Ans = ', results[0], ' total inputs: ', results[1])
       elif choice == 'd':
           results = division()
           print('Ans = ', results[0], ' total inputs: ', results[1])
       else:
           print('Sorry, invalid character')


if __name__ == '__main__':
   calculator()

10. Countdown Clock and Timer

This Python project idea is fun! Here, we’ve created a countdown timer that asks the user for a number of seconds via user input, and it then counts down, second by second, until it displays a message.

We’ve used the Python time module’s .sleep() function to pause for 1-second intervals. We combine this with some nifty string formatting to produce the countdown display.

Source Code:

'''
Countdown Timer
-------------------------------------------------------------
'''


import time


def countdown(user_time):
   while user_time >= 0:
       mins, secs = divmod(user_time, 60)
       timer = '{:02d}:{:02d}'.format(mins, secs)
       print(timer, end='\r')
       time.sleep(1)
       user_time -= 1
   print('Lift off!')


if __name__ == '__main__':
   user_time = int(input("Enter a time in seconds: "))
   countdown(user_time)

Intermediate Python Projects With Source Code

11. Binary Search Algorithm

It’s a rite of passage for all aspiring coders to tackle Binary Search in one of their Python programming projects at some point! I know when I was starting out, some of my most common Python mistakes involved classic algorithms like this.

This Python project for binary search takes in a sorted list (array), then continually compares a search value with the middle of the array.

Depending on whether the search value is less than or greater than the middle value, the list is split (divide and conquer strategy) to reduce the search space, which hones in on the given search value. This continual division results in logarithmic time complexity.

If you look at the code below, you’ll see that we’ve implemented two solutions: conditional loops and recursion. Both approaches are elegant, so feel free to experiment with each.

If you’re new to recursion, this is a great introduction as it demonstrates how we ‘reduce’ the size of the problem with each recursive call, namely by splitting the list to one side of the current middle element.

We’ve also defined the recursive base case as the point when the middle element equals the search element. In this case, the recursion will stop and return the True value up through the call stack.

If this all sounds alien to you, consider using something like GitHub Copilot to make more sense of this classic algorithm.

 

Source Code:

'''
Binary Search
-------------------------------------------------------------
'''


def binary_search(a_list, an_item):
   first = 0
   last = len(a_list) - 1

   while first <= last:
       mid_point = (first + last) // 2
       if a_list[mid_point] == an_item:
           return True
       else:
           if an_item < a_list[mid_point]:
               last = mid_point - 1
           else:
               first = mid_point + 1
   return False


def binary_search_rec(a_list, first, last, an_item):
   if len(a_list) == 0:
       return False
   else:
       mid_point = (first + last) // 2
       if a_list[mid_point] == an_item:
           return True
       else:
           if an_item < a_list[mid_point]:
               last = mid_point - 1
               return binary_search_rec(a_list, first, last, an_item)
           else:
               first = mid_point + 1
               return binary_search_rec(a_list, first, last, an_item)


if __name__ == '__main__':
   a_list = [1, 4, 7, 10, 14, 19, 102, 2575, 10000]
  
   print('Binary Search:', binary_search(a_list, 4))
   print('Binary Search Recursive:',
       binary_search_rec(a_list, 0, len(a_list) -1, 4))

12. Merge Sort Algorithm

Merge Sort is another popular coding challenge faced by aspiring coders when looking for things to do in Python.

This divide-and-conquer strategy uses division to separate a list of numbers into equal parts, and these are then recursively sorted before being recombined to generate a sorted list.

If you’ve just completed the Binary Search example, you might notice some similarities with division and reducing a problem’s size. You’d be right, which means you’ve likely realized we need to use recursion.

This Python implementation of Merge Sort uses recursion to handle the divide and conquer process. The continual reduction of the problem size allows the problem to be solved when the recursive base case is reached, namely when the problem size is one element or less.

In essence, this Python program continues to recursively divide the list until it reaches the base case. At this point it begins sorting the smaller parts of the problem, resulting in smaller sorted arrays that are recombined to eventually generate a fully sorted array. If you’re familiar with Big O notation, you’ll be curious to know that Merge Sort has a Big O of (n logn).

Source Code:

'''
Merge Sort
-------------------------------------------------------------
'''


def merge_sort(a_list):
   print("Dividing ", a_list)
  
   if len(a_list) > 1:
       mid_point = len(a_list)//2
       left_half = a_list[:mid_point]
       right_half = a_list[mid_point:]

       merge_sort(left_half)
       merge_sort(right_half)

       i=0
       j=0
       k=0

       while i < len(left_half) and j < len(right_half):
           if left_half[i] <= right_half[j]:
               a_list[k] = left_half[i]
               i += 1
           else:
               a_list[k] = right_half[j]
               j += 1
           k += 1

       while i < len(left_half):
           a_list[k] = left_half[i]
           i += 1
           k += 1

       while j < len(right_half):
           a_list[k] = right_half[j]
           j += 1
           k += 1
  
   print("Merging ", a_list)


if __name__ == '__main__':
   a_list = [45, 7, 85, 24, 60, 25, 38, 63, 1]
   merge_sort(a_list)
   print(a_list)

13. Password Generator

This is an interesting Python project that uses the secrets and string modules to generate a strong and secure password, much like you can with popular password managers.

The string module obtains all possible letters, digits, and special characters, while the secrets module allows us to obtain cryptographically secure passwords.

The code for this project is relatively simple as it uses a loop to continually generate passwords until it contains at least one special character and two digits. You can, of course, modify this to fit your own super-strong password rules!

Source Code:

'''
Password Generator
-------------------------------------------------------------
'''


import secrets
import string


def create_pw(pw_length=12):
   letters = string.ascii_letters
   digits = string.digits
   special_chars = string.punctuation

   alphabet = letters + digits + special_chars
   pwd = ''
   pw_strong = False

   while not pw_strong:
       pwd = ''
       for i in range(pw_length):
           pwd += ''.join(secrets.choice(alphabet))

       if (any(char in special_chars for char in pwd) and
               sum(char in digits for char in pwd) >= 2):
           pw_strong = True

   return pwd


if __name__ == '__main__':
   print(create_pw())

14. Currency Converter

This is one of several Python project ideas that require us to install one of the most popular Python libraries, which in this case, is the requests module. This is not included with the Python standard library, so use the pip command shown in the source code to install it on your system.

With the requests module, we can make HTTP requests to the Fixer API, allowing us to convert one currency to another. You’ll likely notice that we’re using a 3rd party API, so you’ll need to sign up to get a free API key. You can then enter your API key into the field shown in the source code, and you’ll be ready to go!

This project allows you to gain some more practice with loops and user input, but it expands on this with HTTP requests to retrieve API data in JSON format.

If you’re unfamiliar with JSON, it’s very similar to a Python dictionary, meaning we can access key-value pairs to fetch the data we’re after. In this case, we are looking for the currency conversion result from the API call.

Look at the docs on the Fixer API site for more details on the different data you can retrieve.

Source Code:

'''
Currency Converter
-------------------------------------------------------------
pip install requests
'''


import requests


def convert_currency():
   init_currency = input('Enter an initial currency: ')
   target_currency = input('Enter a target currency: ')

   while True:
       try:
           amount = float(input('Enter the amount: '))
       except:
           print('The amount must be a numeric value!')
           continue

       if not amount > 0:
           print('The amount must be greater than 0')
           continue
       else:
           break

   url = ('https://api.apilayer.com/fixer/convert?to='
          + target_currency + '&from=' + init_currency +
          '&amount=' + str(amount))

   payload = {}
   headers = {'apikey': 'YOUR API KEY'}
   response = requests.request('GET', url, headers=headers, data=payload)
   status_code = response.status_code

   if status_code != 200:
       print('Uh oh, there was a problem. Please try again later')
       quit()

   result = response.json()
   print('Conversion result: ' + str(result['result']))


if __name__ == '__main__':
   convert_currency()

15. Automatic Birthday Mail Sending

This Python project uses the standard smtplib, EmailMessage, and datetime modules, in addition to pandas and openpyxl (these need to be pip installed, as shown below) to send automated birthday emails.

This program reads from an Excel sheet that contains all of your friends’ details (see Excel sheet format in source code below). It then sends them an email if today is their big day before making a note in your spreadsheet to say they’ve received their email.

We’ve used the smtplib and EmailMessage modules to create an SSL connection to our email account and message. We’ve then used a pandas dataframe to store spreadsheet-style data within the Python program (an essential skill for data scientists). Finally, we used date formatting with the datetime module’s .strftime() function.

So, lots of new skills to get to grips with!

Important note: since May 2022, Google has tightened its restrictions on ‘less secure apps’ accessing Gmail. You’ll need to follow some extra steps to use this code with your Gmail account. But don’t worry, they’re easy to do, and we’ve listed them for you.

  • Go to the ‘manage account’ page for your google account
  • Click on Security
  • Enable 2FA (use whichever method you prefer)
  • Click on ‘App Passwords’
  • Click on ‘Select App’ and select ‘Mail’
  • Click on ‘Select Device’ & select ‘Other (custom name)’, enter ‘Python Birthday App’
  • Click on ‘Generate’ then save this password

You can now use this app password in the code below to access your Gmail account with no trouble!

Source Code:

'''
Birthday Email Sender
-------------------------------------------------------------
pip install pandas openpyxl
excel file cols:
Name, Email, Birthday (MM/DD/YYYY), Last Sent (YYYY)
'''


import pandas as pd
from datetime import datetime
import smtplib
from email.message import EmailMessage


def send_email(recipient, subject, msg):
   GMAIL_ID = 'your_email_here'
   GMAIL_PWD = 'your_password_here'

   email = EmailMessage()
   email['Subject'] = subject
   email['From'] = GMAIL_ID
   email['To'] = recipient
   email.set_content(msg)

   with smtplib.SMTP_SSL('smtp.gmail.com', 465) as gmail_obj:
       gmail_obj.ehlo()
       gmail_obj.login(GMAIL_ID, GMAIL_PWD)
       gmail_obj.send_message(email)
   print('Email sent to ' + str(recipient) + ' with Subject: \''
         + str(subject) + '\' and Message: \'' + str(msg) + '\'')


def send_bday_emails(bday_file):
   bdays_df = pd.read_excel(bday_file)
   today = datetime.now().strftime('%m-%d')
   year_now = datetime.now().strftime('%Y')
   sent_index = []

   for idx, item in bdays_df.iterrows():
       bday = item['Birthday'].to_pydatetime().strftime('%m-%d')
       if (today == bday) and year_now not in str(item['Last Sent']):
           msg = 'Happy Birthday ' + str(item['Name'] + '!!')
           send_email(item['Email'], 'Happy Birthday', msg)
           sent_index.append(idx)

   for idx in sent_index:
       bdays_df.loc[bdays_df.index[idx], 'Last Sent'] = str(year_now)

   bdays_df.to_excel(bday_file, index=False)


if __name__ == '__main__':
   send_bday_emails(bday_file='your_bdays_list.xlsx')

16. Queue

This Python project creates a new class to implement a Queue. This is a common data structure in computer science when you need to handle First-In-First-Out (FIFO) scenarios, such as message queues, CPU tasks, etc.

The code is straightforward and offers some more practice with object-oriented programming. Test out the queue to get your head around how it works, and then you’ll be ready to use this data structure in your other projects.

Source Code:

'''
Queue Data Structure
-------------------------------------------------------------
'''


class Queue:

   def __init__(self):
       self.items = []

   def __repr__(self):
       return f'Queue object: data={self.items}'

   def is_empty(self):
       return not self.items

   def enqueue(self, item):
       self.items.append(item)

   def dequeue(self):
       return self.items.pop(0)

   def size(self):
       return len(self.items)

   def peek(self):
       return self.items[0]


if __name__ == '__main__':
   q = Queue()
   print(q.is_empty())
   q.enqueue('First')
   q.enqueue('Second')
   print(q)
   print(q.dequeue())
   print(q)
   print(q.size())
   print(q.peek())

17. Pascal’s Triangle

This Python project prints out Pascal’s Triangle using conditional statements and loops. It also uses the standard library’s math module and factorial function to evaluate the ‘number of combinations’ equation used to generate the values in the triangle.

Experiment with the seed number for the triangle to examine how the ‘combinations’ equation is used to generate successive values in the triangle. 

Source Code:

'''
Pascal's Triangle
-------------------------------------------------------------
Number of combinations via "n choose k" or nCk = n! / [k! * (n-k)!]
'''


from math import factorial


def pascal_triangle(n):
   for i in range(n):
       for j in range(n-i+1):
           print(end=' ')

       for j in range(i+1):
          
           print(factorial(i)//(factorial(j)*factorial(i-j)), end=' ')

       print()


if __name__ == '__main__':
   pascal_triangle(5)

18. Blackjack

As one of the coolest Python projects, this will appeal to anyone who enjoys card games, as we will emulate Blackjack. This is a super popular card game with relatively simple rules: the most important being you need 21 to win, or you need a higher score than the dealer without going bust!

This is the largest project on the list so far. It combines most of the skills we’ve already covered in previous projects, including creating classes, loops, conditional statements, importing modules, accepting user input, and string formatting.

Take your time to work through the different sections of this code, and relate it to the earlier projects to see how the different techniques work together. There’s nothing you haven’t seen before; it’s just been packaged slightly differently and combined to create a fully functional game emulator.

And we should say, try not to spend all day playing with it! But we totally understand if you do!

Source Code:

'''
Blackjack
-------------------------------------------------------------
'''


import random
import os


class Card:

   def __init__(self, card_face, value, symbol):
       self.card_face = card_face
       self.value = value
       self.symbol = symbol


def show_cards(cards, hidden):
   s = ''
   for card in cards:
       s = s + '\t ________________'
   if hidden:
       s += '\t ________________'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|                |'
   if hidden:
       s += '\t|                |'
   print(s)

   s = ''
   for card in cards:
       if card.card_face in ['J', 'Q', 'K', 'A']:
           s = s + '\t|  {}             |'.format(card.card_face)
       elif card.value == 10:
           s = s + '\t|  {}            |'.format(card.value)
       else:
           s = s + '\t|  {}             |'.format(card.value)

   if hidden:
       s += '\t|                |'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|                |'
   if hidden:
       s += '\t|      * *       |'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|                |'
   if hidden:
       s += '\t|    *     *     |'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|                |'
   if hidden:
       s += '\t|   *       *    |'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|                |'
   if hidden:
       s += '\t|   *       *    |'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|       {}        |'.format(card.symbol)
   if hidden:
       s += '\t|          *     |'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|                |'
   if hidden:
       s += '\t|         *      |'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|                |'
   if hidden:
       s += '\t|        *       |'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|                |'
   if hidden:
       s += '\t|                |'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|                |'
   if hidden:
       s += '\t|                |'
   print(s)

   s = ''
   for card in cards:
       if card.card_face in ['J', 'Q', 'K', 'A']:
           s = s + '\t|            {}   |'.format(card.card_face)
       elif card.value == 10:
           s = s + '\t|           {}   |'.format(card.value)
       else:
           s = s + '\t|            {}   |'.format(card.value)
   if hidden:
       s += '\t|        *       |'
   print(s)

   s = ''
   for card in cards:
       s = s + '\t|________________|'
   if hidden:
       s += '\t|________________|'
   print(s)
   print()


def deal_card(deck):
   card = random.choice(deck)
   deck.remove(card)
   return card, deck


def play_blackjack(deck):
   player_cards = []
   dealer_cards = []
   player_score = 0
   dealer_score = 0
   os.system('clear')

   while len(player_cards) < 2:
       player_card, deck = deal_card(deck)
       player_cards.append(player_card)
       player_score += player_card.value

       # If dealt a second Ace, adjust player score
       if len(player_cards) == 2:
           if player_cards[0].value == 11 and player_cards[1].value == 11:
               player_cards[0].value = 1
               player_score -= 10

       print('PLAYER CARDS: ')
       show_cards(player_cards, False)
       print('PLAYER SCORE = ', player_score)

       input('Continue...')

       dealer_card, deck = deal_card(deck)
       dealer_cards.append(dealer_card)
       dealer_score += dealer_card.value

       # If dealt a second Ace, adjust dealer score
       # Note: adjusts 2nd card to hide that the dealer has an Ace
       if len(dealer_cards) == 2:
           if dealer_cards[0].value == 11 and dealer_cards[1].value == 11:
               dealer_cards[1].value = 1
               dealer_score -= 10

       print('DEALER CARDS: ')
       if len(dealer_cards) == 1:
           show_cards(dealer_cards, False)
           print('DEALER SCORE = ', dealer_score)
       else:
           show_cards(dealer_cards[:-1], True)
           print('DEALER SCORE = ', dealer_score - dealer_cards[-1].value)

       input('Continue...')

   if player_score == 21:
       print('PLAYER HAS A BLACKJACK!!!!')
       print('PLAYER WINS!!!!')
       quit()
   os.system('clear')

   print('DEALER CARDS: ')
   show_cards(dealer_cards[:-1], True)
   print('DEALER SCORE = ', dealer_score - dealer_cards[-1].value)
   print()
   print('PLAYER CARDS: ')
   show_cards(player_cards, False)
   print('PLAYER SCORE = ', player_score)

   while player_score < 21:
       choice = input('Enter H to Hit or S to Stand: ').upper()
       if len(choice) != 1 or (choice not in ['H', 'S']):
           os.system('clear')
           print('Invalid choice!! Try Again...')
           continue

       if choice.upper() == 'S':
           break
       else:
           player_card, deck = deal_card(deck)
           player_cards.append(player_card)
           player_score += player_card.value
           card_pos = 0

           # If dealt an Ace, adjust score for each existing Ace in hand
           while player_score > 21 and card_pos < len(player_cards):
               if player_cards[card_pos].value == 11:
                   player_cards[card_pos].value = 1
                   player_score -= 10
                   card_pos += 1
               else:
                   card_pos += 1
          
           if player_score > 21:
               break

           os.system('clear')
           print('DEALER CARDS: ')
           show_cards(dealer_cards[:-1], True)
           print('DEALER SCORE = ', dealer_score - dealer_cards[-1].value)
           print()
           print('PLAYER CARDS: ')
           show_cards(player_cards, False)
           print('PLAYER SCORE = ', player_score)

   os.system('clear')
   print('PLAYER CARDS: ')
   show_cards(player_cards, False)
   print('PLAYER SCORE = ', player_score)
   print()
   print('DEALER IS REVEALING THEIR CARDS....')
   print('DEALER CARDS: ')
   show_cards(dealer_cards, False)
   print('DEALER SCORE = ', dealer_score)

   if player_score == 21:
       print('PLAYER HAS A BLACKJACK, PLAYER WINS!!!')
       quit()

   if player_score > 21:
       print('PLAYER BUSTED!!! GAME OVER!!!')
       quit()

   input('Continue...')
   while dealer_score < 17:
       os.system('clear')
       print('DEALER DECIDES TO HIT.....')
       dealer_card, deck = deal_card(deck)
       dealer_cards.append(dealer_card)
       dealer_score += dealer_card.value

       # If dealt an Ace, adjust score for each existing Ace in hand
       card_pos = 0
       while dealer_score > 21 and card_pos < len(dealer_cards):
           if dealer_cards[card_pos].value == 11:
               dealer_cards[card_pos].value = 1
               dealer_score -= 10
               card_pos += 1
           else:
               card_pos += 1

       print('PLAYER CARDS: ')
       show_cards(player_cards, False)
       print('PLAYER SCORE = ', player_score)
       print()
       print('DEALER CARDS: ')
       show_cards(dealer_cards, False)
       print('DEALER SCORE = ', dealer_score)
       if dealer_score > 21:
           break
       input('Continue...')

   if dealer_score > 21:
       print('DEALER BUSTED!!! YOU WIN!!!')
       quit()
   elif dealer_score == 21:
       print('DEALER HAS A BLACKJACK!!! PLAYER LOSES!!!')
       quit()
   elif dealer_score == player_score:
       print('TIE GAME!!!!')
   elif player_score > dealer_score:
       print('PLAYER WINS!!!')
   else:
       print('DEALER WINS!!!')


def init_deck():
   suits = ['Spades', 'Hearts', 'Clubs', 'Diamonds']
   # UNICODE values for card symbol images
   suit_symbols = {'Hearts': '\u2661', 'Diamonds': '\u2662',
                   'Spades': '\u2664', 'Clubs': '\u2667'}
   cards = {'A': 11, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6,
            '7': 7, '8': 8, '9': 9, '10': 10, 'J': 10, 'Q': 10, 'K': 10}
   deck = []
   for suit in suits:
       for card, value in cards.items():
           deck.append(Card(card, value, suit_symbols[suit]))
   return deck


if __name__ == '__main__':
   deck = init_deck()
   play_blackjack(deck)

19. Reddit Bot

This Python project creates an automated Reddit bot with some new modules, namely praw and enchant (see the pip install commands).

This is a fairly simple concept as the program checks every comment in a selected subreddit and then replies to any comments that contain a predefined ‘trigger phrase’. To do this, we use the praw module to interact with Reddit, and enchant to generate similar words to the comment, allowing us to make an appropriate reply.

This idea is really useful if you’re looking for Python projects to learn how to answer questions in your own subreddit. You’d just need to expand this code to include automated responses for predefined questions (you’ve probably already noticed this being used by others on Reddit!). 

Important note: You’ll need to check out these instructions to get hold of a client_id, client_secret, username, password, and user_agent. You’ll need this information to make comments to Reddit via the API interface.

Source Code:

'''
Reddit Reply Bot
-------------------------------------------------------------
pip install praw pyenchant
'''


import praw
import enchant


def reddit_bot(sub, trigger_phrase):
   reddit = praw.Reddit(
       client_id='your_client_id',
       client_secret='your_client_secret',
       username='your_username',
       password='your_pw',
       user_agent='your_user_agent'
   )

   subreddit = reddit.subreddit(sub)
   dict_suggest = enchant.Dict('en_US')

   for comment in subreddit.stream.comments():
       if trigger_phrase in comment.body.lower():
           word = comment.body.replace(trigger_phrase, '')
           reply_text = ''
           similar_words = dict_suggest.suggest(word)
           for similar in similar_words:
               reply_text += (similar + ' ')
           comment.reply(reply_text)


if __name__ == '__main__':
   reddit_bot(sub='Python', trigger_phrase='useful bot')

20. Fibonacci Generator

The Fibonacci numbers may be some of the most important numbers in our lives as they appear so often in nature.

The Python code below generates the Fibonacci numbers up to a certain length using recursion (yes, more recursion!). To stop the computation times from getting out of hand, we’ve implemented memoization to cache values as we calculate them.

You’ll notice that for this recursive algorithm, the base case is set to check whether the given Fibonacci sequence value is already stored in the cache. If so, it returns this (which is a constant time complexity operation), which saves a tremendous amount of computation time.

Source Code:

'''
Fibonacci Sequence
-------------------------------------------------------------
'''

fib_cache = {}


def fib_memo(input_val):
   if input_val in fib_cache:
       return fib_cache[input_val]

   if input_val == 0:
       val = 0
   elif input_val < 2:
       val = 1
   else:
       val = fib_memo(input_val - 1) + fib_memo(input_val - 2)

   fib_cache[input_val] = val
   return val


if __name__ == '__main__':
   print('======== Fibonacci Series ========')
   for i in range(1, 11):
       print(f'Fibonacci ({i}) : {fib_memo(i)}')

Advanced Python Project Ideas

21. Chatbot

This Python project uses the chatterbot module (see pip install instructions below) to train an automated chatbot to answer any question you ask! I know; we’re now using AI!

You’ll see that the program is one of the relatively small Python projects in this list, but feel free to explore the ChatterBot documentation along with the broader field of AI chatbots if you’d like to learn more or expand the code’s features.

If this has whet your appetite for building AI bots, check out our 24-Hour Python Chatbot course to learn how to build an AI-powered chatbot with the same tools that power OpenAI’s ChatGPT.

And if you're hungry for even more AI goodness, check out OpenAI,'s latest feature that lets you build your own GPT.

Important note: ChatterBot is no longer being actively maintained. This means you need to make a small change to the tagging.py file located in the ‘Lib/site-packages/chatterbot’ directory of your Python installation folder.

Don’t worry; it’s straightforward to do, and we’ve included the exact source code you need to use, as shown below.

Source Code:

'''
Chat Bot
-------------------------------------------------------------
1) pip install ChatterBot chatterbot-corpus spacy
2) python3 -m spacy download en_core_web_sm
   Or... choose the language you prefer
3) Navigate to your Python3 directory
4) Modify Lib/site-packages/chatterbot/tagging.py
  to properly load 'en_core_web_sm'
'''


from chatterbot import ChatBot
from chatterbot.trainers import ChatterBotCorpusTrainer


def create_chat_bot():
   chatbot = ChatBot('Chattering Bot')
   trainer = ChatterBotCorpusTrainer(chatbot)
   trainer.train('chatterbot.corpus.english')

   while True:
       try:
           bot_input = chatbot.get_response(input())
           print(bot_input)

       except (KeyboardInterrupt, EOFError, SystemExit):
           break


if __name__ == '__main__':
   create_chat_bot()

Modify tagging.py:

Find the first code snippet, which is part of the __init__ method for the PosLemmaTagger class. Replace this with the if/else statement.

Note: this example is for the English library we used in our example, but feel free to switch this out to another language if you’d prefer.

# Replace this:
self.nlp = spacy.load(self.language.ISO_639_1.lower())

# With this:
if self.language.ISO_639_1.lower() == 'en':
   self.nlp = spacy.load('en_core_web_sm')
else:
   self.nlp = spacy.load(self.language.ISO_639_1.lower())

22. Text to Speech

This Python project uses a range of new libraries to convert an existing article into a playable mp3 file. You’ll need to install nltk (natural language toolkit), newspaper3k, and gtts (see pip install instructions).

You’ll see that the program is simple, as we simply pass in a URL for an article to convert, then let the function we’ve defined handle the text-to-speech conversion with our newly installed modules.

So, consider trying this out the next time you fancy turning an article into a playable podcast as it’s definitely one of the cool Python codes to copy! 

Source Code:

'''
Text To Speech
-------------------------------------------------------------
pip install nltk newspaper3k gtts
'''


import nltk
from newspaper import Article
from gtts import gTTS


def text_to_speech(url):
   article = Article(url)
   article.download()
   article.parse()
   nltk.download('punkt')
   article.nlp()
   article_text = article.text
   language = 'en'
   my_obj = gTTS(text=article_text, lang=language, slow=False)
   my_obj.save("read_article.mp3")


if __name__ == '__main__':
   text_to_speech(
       url='https://hackr.io/blog/top-tech-companies-hiring-python-developers'
   )

23. Library Management System

As one of the more advanced Python projects, this program uses object-oriented programming to simulate a library management system.

In this example, we create a Library and Student class, which we can use to create our library system and its users. We’ve then implemented a simple user interface that asks users to select from a range of standard library actions, like borrowing or returning books. 

This is a simple yet powerful example of how you can build out real-world systems via Python and object-oriented programming. Feel free to expand the classes to include other useful features, like unique book IDs, multiple copies of the same book, return dates, fees for returning books late, or any other features you think a library should have!

Source Code:

'''
Library
-------------------------------------------------------------
'''


class Library:

   def __init__(self, books):
       self.books = books

   def show_avail_books(self):
       print('Our Library Can Offer You The Following Books:')
       print('================================================')
       for book, borrower in self.books.items():
           if borrower == 'Free':
               print(book)

   def lend_book(self, requested_book, name):
       if self.books[requested_book] == 'Free':
           print(
               f'{requested_book} has been marked'
               f' as \'Borrowed\' by: {name}')
           self.books[requested_book] = name
           return True
       else:
           print(
               f'Sorry, the {requested_book} is currently'
               f' on loan to: {self.books[requested_book]}')
           return False

   def return_book(self, returned_book):
       self.books[returned_book] = 'Free'
       print(f'Thanks for returning {returned_book}')


class Student:
   def __init__(self, name, library):
       self.name = name
       self.books = []
       self.library = library

   def view_borrowed(self):
       if not self.books:
           print('You haven\'t borrowed any books')
       else:
           for book in self.books:
               print(book)

   def request_book(self):
       book = input(
           'Enter the name of the book you\'d like to borrow >> ')
       if self.library.lend_book(book, self.name):
           self.books.append(book)

   def return_book(self):
       book = input(
           'Enter the name of the book you\'d like to return >> ')
       if book in self.books:
           self.library.return_book(book)
       else:
           print('You haven\'t borrowed that book, try another...')


def create_lib():
   books = {
       'The Last Battle': 'Free',
       'The Hunger Games': 'Free',
       'Cracking the Coding Interview': 'Free'
   }
   library = Library(books)
   student_example = Student('Your Name', library)

   while True:
       print('''
           ==========LIBRARY MENU===========
           1. Display Available Books
           2. Borrow a Book
           3. Return a Book
           4. View Your Books
           5. Exit'''
             )

       choice = int(input('Enter Choice: '))
       if choice == 1:
           print()
           library.show_avail_books()
       elif choice == 2:
           print()
           student_example.request_book()
       elif choice == 3:
           print()
           student_example.return_book()
       elif choice == 4:
           print()
           student_example.view_borrowed()
       elif choice == 5:
           print('Goodbye')
           exit()


if __name__ == '__main__':
   create_lib()

24. Pong Arcade Game

This is a really fun and interesting project, as we’ve used the Python turtle module to emulate the classic arcade game Pong!

We’ve used various methods from the turtle module to create our game components and detect ball collisions with the player paddles. We’ve also defined a range of keybindings to set the user controls for the left and right player paddles. Feel free to experiment with the game’s settings to better understand how each setting works and affects the overall game.

Outside of these newly introduced turtle graphics functions, we’ve used string formatting to output the current scoreboard and user-defined functions to keep our code tidy. These are concepts you should be familiar with at this stage.

Source Code:

'''
Pong Arcade Game
-------------------------------------------------------------
'''


import turtle


def update_score(l_score, r_score, player, score_board):
   if player == 'l':
       l_score += 1
   else:
       r_score += 1

   score_board.clear()
   score_board.write('Left Player: {} -- Right Player: {}'.format(
       l_score, r_score), align='center',
       font=('Arial', 24, 'normal'))
   return l_score, r_score, score_board


def setup_game():
   screen = turtle.Screen()
   screen.title('Pong Arcade Game')
   screen.bgcolor('white')
   screen.setup(width=1000, height=600)

   l_paddle = turtle.Turtle()
   l_paddle.speed(0)
   l_paddle.shape('square')
   l_paddle.color('red')
   l_paddle.shapesize(stretch_wid=6, stretch_len=2)
   l_paddle.penup()
   l_paddle.goto(-400, 0)

   r_paddle = turtle.Turtle()
   r_paddle.speed(0)
   r_paddle.shape('square')
   r_paddle.color('black')
   r_paddle.shapesize(stretch_wid=6, stretch_len=2)
   r_paddle.penup()
   r_paddle.goto(400, 0)

   ball = turtle.Turtle()
   ball.speed(40)
   ball.shape('circle')
   ball.color('blue')
   ball.penup()
   ball.goto(0, 0)
   ball.dx = 5
   ball.dy = -5

   score_board = turtle.Turtle()
   score_board.speed(0)
   score_board.color('blue')
   score_board.penup()
   score_board.hideturtle()
   score_board.goto(0, 260)
   score_board.write('Left Player: 0 -- Right Player: 0',
                     align='center', font=('Arial', 24, 'normal'))

   return screen, ball, l_paddle, r_paddle, score_board


def pong_game():
   game_components = setup_game()
   screen = game_components[0]
   ball = game_components[1]
   l_paddle = game_components[2]
   r_paddle = game_components[3]
   score_board = game_components[4]
   l_score = 0
   r_score = 0

   def l_paddle_up():
       l_paddle.sety(l_paddle.ycor() + 20)

   def l_paddle_down():
       l_paddle.sety(l_paddle.ycor() - 20)

   def r_paddle_up():
       r_paddle.sety(r_paddle.ycor() + 20)

   def r_paddle_down():
       r_paddle.sety(r_paddle.ycor() - 20)

   screen.listen()
   screen.onkeypress(l_paddle_up, 'e')
   screen.onkeypress(l_paddle_down, 'x')
   screen.onkeypress(r_paddle_up, 'Up')
   screen.onkeypress(r_paddle_down, 'Down')

   while True:
       screen.update()
       ball.setx(ball.xcor()+ball.dx)
       ball.sety(ball.ycor()+ball.dy)

       if ball.ycor() > 280:
           ball.sety(280)
           ball.dy *= -1

       if ball.ycor() < -280:
           ball.sety(-280)
           ball.dy *= -1

       if ball.xcor() > 500:
           ball.goto(0, 0)
           ball.dy *= -1
           l_score, r_score, score_board = update_score(
               l_score, r_score, 'l', score_board)
           continue

       elif ball.xcor() < -500:
           ball.goto(0, 0)
           ball.dy *= -1
           l_score, r_score, score_board = update_score(
               l_score, r_score, 'r', score_board)
           continue

       if ((ball.xcor() > 360) and
           (ball.xcor() < 370) and
           (ball.ycor() < r_paddle.ycor()+40) and
               (ball.ycor() > r_paddle.ycor()-40)):
           ball.setx(360)
           ball.dx *= -1

       if ((ball.xcor() < -360) and
               (ball.xcor() > -370) and
               (ball.ycor() < l_paddle.ycor()+40) and
               (ball.ycor() > l_paddle.ycor()-40)):
           ball.setx(-360)
           ball.dx *= -1


if __name__ == '__main__':
   pong_game()

25. Speed Typing Test

This is an interesting Python project that tests how quickly you can accurately type out a sentence.

This program requires us to create a graphical user interface (GUI) via the tkinter module. If you’re new to GUIs, this example is a nice introduction as we use a range of simple labels, buttons, and entry fields to create a window. We’ve also used the Python timeit module to handle the timing aspect of our typing test, and the random module to randomly select a test phrase.

We’ve only added two test phrases to this example, but feel free to experiment with more or even integrate a 3rd party dictionary for a wider array of examples.

Source Code:

'''
Speed Typing Test
-------------------------------------------------------------
'''


import tkinter
from timeit import default_timer as timer
import random


def speed_test():
   speed_test_sentences = [
       'This is a random sentence to check speed.',
       'Speed, I am lightning mcqueen.'
   ]

   sentence = random.choice(speed_test_sentences)
   start = timer()
   main_window = tkinter.Tk()
   main_window.geometry('600x400')

   label_1 = tkinter.Label(main_window, text=sentence, font='times 20')
   label_1.place(x=150, y=10)

   label_2 = tkinter.Label(main_window, text='Start Typing', font='times 20')
   label_2.place(x=10, y=50)

   entry = tkinter.Entry(main_window)
   entry.place(x=280, y=55)

   def check_result():
       if entry.get() == sentence:
           end = timer()
           label_3.configure(text=f'Time: {round((end-start), 4)}s')
       else:
           label_3.configure(text='Wrong Input')

   button_1 = tkinter.Button(main_window, text='Done',
                             command=check_result, width=12, bg='grey')
   button_1.place(x=150, y=100)

   button_2 = tkinter.Button(main_window, text='Try Again',
                             command=speed_test, width=12, bg='grey')
   button_2.place(x=250, y=100)

   label_3 = tkinter.Label(main_window, text='', font='times 20')
   label_3.place(x=10, y=300)

   main_window.mainloop()


if __name__ == '__main__':
   speed_test()

26. Text Editor

Building on our last tkinter example, this fun Python project creates a GUI to simulate our very own text editor. This example also uses standard GUI components, including labels, buttons, and entry fields.

However, we’ve also added the ability to open and save files like a real text editor. If you’re new to file handling, this Python project is a great way to understand how to read-in and save files.

Experiment with the code below to solidify your understanding, and see if you can expand on this code to create other features you’re used to using with a text editor, like a ‘find word’ function.

Source Code:

'''
Text Editor
-------------------------------------------------------------
'''


import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename


def text_editor():
   def open_file():
       filepath = askopenfilename(
           filetypes=[('Text Files', '*.txt'), ('All Files', '*.*')]
       )

       if not filepath:
           return

       txt_edit.delete(1.0, tk.END)
       with open(filepath, 'r') as input_file:
           text = input_file.read()
           txt_edit.insert(tk.END, text)
       window.title(f'TextEditor - {filepath}')

   def save_file():
       filepath = asksaveasfilename(
           defaultextension='txt',
           filetypes=[('Text Files', '*.txt'), ('All Files', '*.*')],
       )

       if not filepath:
           return

       with open(filepath, 'w') as output_file:
           text = txt_edit.get(1.0, tk.END)
           output_file.write(text)
       window.title(f'Text Editor - {filepath}')

   window = tk.Tk()
   window.title('Text Editor')
   window.rowconfigure(0, minsize=800, weight=1)
   window.columnconfigure(1, minsize=800, weight=1)

   txt_edit = tk.Text(window)
   fr_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)
   btn_open = tk.Button(fr_buttons, text='Open', command=open_file)
   btn_save = tk.Button(fr_buttons, text='Save As...', command=save_file)

   btn_open.grid(row=0, column=0, sticky='ew', padx=5, pady=5)
   btn_save.grid(row=1, column=0, sticky='ew', padx=5)

   fr_buttons.grid(row=0, column=0, sticky='ns')
   txt_edit.grid(row=0, column=1, sticky='nsew')

   window.mainloop()


if __name__ == '__main__':
  text_editor()

27. Sudoku Solver

This Python project uses the pygame library (see pip install instructions) to implement a GUI for automatically solving sudoku puzzles. We use several user-defined functions to create the GUI, as shown below.

To solve a sudoku puzzle, this program uses a backtracking algorithm that incrementally checks for solutions, either adopting or abandoning the current solution if it’s not viable.

This step of abandoning a solution is the defining feature of a backtracking approach, as the program steps back to try a new solution until it finds a valid one. This process is incrementally carried out until the entire grid has been correctly filled.

Feel free to experiment with different sudoku problems, and even think about expanding the size of the problem grid (you’ll need a new base image if you do this).

Source Code:

'''
Sudoku Solver
-------------------------------------------------------------
pip install pygame
image link:
https://www.pngitem.com/pimgs/m/210-2106648_empty-sudoku-grid-grid-6x6-png-transparent-png.png
'''


import pygame


pygame.font.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption('SUDOKU SOLVER USING BACKTRACKING')
img = pygame.image.load('icon.png')
pygame.display.set_icon(img)
font1 = pygame.font.SysFont('comicsans', 40)
font2 = pygame.font.SysFont('comicsans', 20)
x = 0
y = 0
dif = 500 / 9
val = 0

# Default Sudoku Board
grid = [
   [7, 8, 0, 4, 0, 0, 1, 2, 0],
   [6, 0, 0, 0, 7, 5, 0, 0, 9],
   [0, 0, 0, 6, 0, 1, 0, 7, 8],
   [0, 0, 7, 0, 4, 0, 2, 6, 0],
   [0, 0, 1, 0, 5, 0, 9, 3, 0],
   [9, 0, 4, 0, 6, 0, 0, 0, 5],
   [0, 7, 0, 3, 0, 0, 0, 1, 2],
   [1, 2, 0, 0, 0, 7, 4, 0, 0],
   [0, 4, 9, 2, 0, 6, 0, 0, 7]
]


def get_coord(pos):
   x = pos[0] // dif
   y = pos[1] // dif


def draw_box():
   for i in range(2):
       pygame.draw.line(screen, (255, 0, 0), (x * dif-3, (y + i)
                        * dif), (x * dif + dif + 3, (y + i)*dif), 7)
       pygame.draw.line(screen, (255, 0, 0), ((x + i) * dif,
                        y * dif), ((x + i) * dif, y * dif + dif), 7)


def draw():
   for i in range(9):
       for j in range(9):
           if grid[i][j] != 0:
               pygame.draw.rect(screen, (0, 153, 153),
                                (i * dif, j * dif, dif + 1, dif + 1))
               text1 = font1.render(str(grid[i][j]), 1, (0, 0, 0))
               screen.blit(text1, (i * dif + 15, j * dif + 15))

   for i in range(10):
       if i % 3 == 0:
           thick = 7
       else:
           thick = 1
       pygame.draw.line(screen, (0, 0, 0), (0, i * dif),
                        (500, i * dif), thick)
       pygame.draw.line(screen, (0, 0, 0), (i * dif, 0),
                        (i * dif, 500), thick)


def draw_val(val):
   text1 = font1.render(str(val), 1, (0, 0, 0))
   screen.blit(text1, (x * dif + 15, y * dif + 15))


def raise_error_1():
   text1 = font1.render('WRONG !!!', 1, (0, 0, 0))
   screen.blit(text1, (20, 570))


def raise_error_2():
   text1 = font1.render('Wrong !!! Not a valid Key', 1, (0, 0, 0))
   screen.blit(text1, (20, 570))


def valid(m, i, j, val):
   for it in range(9):
       if m[i][it] == val:
           return False
       if m[it][j] == val:
           return False

   it = i // 3
   jt = j // 3

   for i in range(it * 3, it * 3 + 3):
       for j in range(jt * 3, jt * 3 + 3):
           if m[i][j] == val:
               return False
   return True


def solve(grid, i, j):
   while grid[i][j] != 0:
       if i < 8:
           i += 1
       elif i == 8 and j < 8:
           i = 0
           j += 1
       elif i == 8 and j == 8:
           return True

   pygame.event.pump()
   for it in range(1, 10):
       if valid(grid, i, j, it) == True:
           grid[i][j] = it
           x = i
           y = j
           screen.fill((255, 255, 255))
           draw()
           draw_box()
           pygame.display.update()
           pygame.time.delay(20)

           if solve(grid, i, j) == 1:
               return True
           else:
               grid[i][j] = 0
           screen.fill((255, 255, 255))

           draw()
           draw_box()
           pygame.display.update()
           pygame.time.delay(50)
   return False


def instruction():
  text1 = font2.render(
      'PRESS D TO RESET TO DEFAULT / R TO EMPTY\n', 1, (0, 0, 0))
  text2 = font2.render(
      'ENTER VALUES AND PRESS ENTER TO VISUALIZE\n', 1, (0, 0, 0))
  screen.blit(text1, (20, 520))
  screen.blit(text2, (20, 540))


def result():
  text1 = font1.render('FINISHED PRESS R or D\n', 1, (0, 0, 0))
  screen.blit(text1, (20, 570))


run = True
flag_1 = 0
flag_2 = 0
rs = 0
error = 0
while run:
   screen.fill((255, 255, 255))
   for event in pygame.event.get():
       if event.type == pygame.QUIT:
           run = False
       if event.type == pygame.MOUSEBUTTONDOWN:
           flag_1 = 1
           pos = pygame.mouse.get_pos()
           get_coord(pos)
       if event.type == pygame.KEYDOWN:
           if event.key == pygame.K_LEFT:
               x -= 1
               flag_1 = 1
           if event.key == pygame.K_RIGHT:
               x += 1
               flag_1 = 1
           if event.key == pygame.K_UP:
               y -= 1
               flag_1 = 1
           if event.key == pygame.K_DOWN:
               y += 1
               flag_1 = 1
           if event.key == pygame.K_1:
               val = 1
           if event.key == pygame.K_2:
               val = 2
           if event.key == pygame.K_3:
               val = 3
           if event.key == pygame.K_4:
               val = 4
           if event.key == pygame.K_5:
               val = 5
           if event.key == pygame.K_6:
               val = 6
           if event.key == pygame.K_7:
               val = 7
           if event.key == pygame.K_8:
               val = 8
           if event.key == pygame.K_9:
               val = 9
           if event.key == pygame.K_RETURN:
               flag_2 = 1

           # If R pressed clear sudoku board
           if event.key == pygame.K_r:
               rs = 0
               error = 0
               flag_2 = 0
               grid = [
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0]
               ]

           # If D pressed reset board to default
           if event.key == pygame.K_d:
               rs = 0
               error = 0
               flag_2 = 0
               grid = [
                   [7, 8, 0, 4, 0, 0, 1, 2, 0],
                   [6, 0, 0, 0, 7, 5, 0, 0, 9],
                   [0, 0, 0, 6, 0, 1, 0, 7, 8],
                   [0, 0, 7, 0, 4, 0, 2, 6, 0],
                   [0, 0, 1, 0, 5, 0, 9, 3, 0],
                   [9, 0, 4, 0, 6, 0, 0, 0, 5],
                   [0, 7, 0, 3, 0, 0, 0, 1, 2],
                   [1, 2, 0, 0, 0, 7, 4, 0, 0],
                   [0, 4, 9, 2, 0, 6, 0, 0, 7]
               ]

   if flag_2 == 1:
       if solve(grid, 0, 0) == False:
           error = 1
       else:
           rs = 1
       flag_2 = 0

   if val != 0:
       draw_val(val)
       if valid(grid, int(x), int(y), val) == True:
           grid[int(x)][int(y)] = val
           flag_1 = 0
       else:
           grid[int(x)][int(y)] = 0
           raise_error_2()
       val = 0

   if error == 1:
       raise_error_1()
   if rs == 1:
       result()
   draw()
   if flag_1 == 1:
       draw_box()
   instruction()

   pygame.display.update()

28. Site Connectivity Checker

This Python project uses the urllib and tkinter modules to test website connectivity.

We’ve used the tkinter module to create a GUI allowing users to enter a web address. Much like our previous examples, this includes labels, buttons, and entry fields.

After we’ve collected the user’s web address, we pass this to our user-defined function to return an HTTP status code for the current website via the urllib module’s .getcode() function.

For this example, we simply determine whether the HTTP code is 200. If it is, we know the site is working; otherwise, we inform the user that it is unavailable.

You could expand this code to consider a more granular approach to handling the various HTTP response codes, so feel free to add this!

Source Code:

'''
Site Connectivity Checker
-------------------------------------------------------------
Enter websites as http(s)://www.yourwebsite.com
'''


import urllib.request
import tkinter as tk


def test_connectivity():
  window = tk.Tk()
  window.geometry('600x400')
  head = tk.Label(window, text='Website Connectivity Checker',
                  font=('Calibri 15'))
  head.pack(pady=20)

  def check_url():
      web = (url.get())
      status_code = urllib.request.urlopen(web).getcode()
      website_is_up = status_code == 200

      if website_is_up:
          tk.Label(window, text='Website Available',
                   font=('Calibri 15')).place(x=260, y=200)
      else:
          tk.Label(window, text='Website Not Available',
                   font=('Calibri 15')).place(x=260, y=200)

  url = tk.StringVar()
  tk.Entry(window, textvariable=url).place(x=200, y=80, height=30, width=280)
  tk.Button(window, text='Check', command=check_url).place(x=285, y=150)
  window.mainloop()


if __name__ == '__main__':
  test_connectivity()

29. Language Detector

This Python project uses the langdetect module (see pip install instructions) to help us identify the language that has been entered. This can be really useful if you’re unsure which language you’re dealing with. 

This is another example where we’ve used tkinter to create a simple GUI involving labels, buttons, and an entry field. We can then collect text from the entry field and process this with the langdetect to determine which language was entered. Finally, we print this result to the GUI to let the user know the result.

Note that the results returned by langdetect are abbreviated language codes. For example, if we enter English text, we will see ‘en’ as the return value.

Source Code:

'''
Language Detector
-------------------------------------------------------------
pip install langdetect
'''


from langdetect import detect
import tkinter as tk


def detect_lang():
   window = tk.Tk()
   window.geometry('600x400')
   head = tk.Label(window, text='Language Detector', font=('Calibri 15'))
   head.pack(pady=20)

   def check_language():
       new_text = text.get()
       lang = detect(str(new_text))
       tk.Label(window, text=lang, font=('Calibri 15')).place(x=260, y=200)

   text = tk.StringVar()
   tk.Entry(window, textvariable=text).place(
       x=200, y=80, height=30, width=280)
   tk.Button(window, text='Check Language',
             command=check_language).place(x=285, y=150)
   window.mainloop()


if __name__ == '__main__':
   detect_lang()

30. Netflix Recommendation System

To cap it all off, we’ve saved a particularly exciting Python project for last! This is a Netflix recommendation system, ideal for aspiring data scientists. In fact, if you’re considering a machine learning course, this is a great project to reinforce your new skills.

To create this project, you’ll need to import a range of modules, including tkinter, re, nltk, pandas, and numpy (see pip install instructions for new modules). You’ll also need to download a Kaggle dataset containing Netflix movies and TV shows. 

We’ll use tkinter to create our GUI, which will use labels, buttons, and entry fields. The user will then be able to enter a TV show or movie they enjoyed on Netflix to return recommendations based on their taste. 

The recommendation engine uses cast, director, ratings, country, and genres as machine learning (ML) ‘features’. The code then uses the ‘cosine similarity’ approach to find similar results based on user input. This extensively uses pandas and numpy to clean the data and prepare it for processing.

There is a lot to unpack in this example, as it uses lots of Python concepts for data science.

The best approach is to slowly work through the code and then carry out further research on Machine Learning (ML), ‘features’, and ‘cosine similarity’. 

You’ll then be able to understand how to use a dataset to derive recommendations based on similarities. If you’re an aspiring data scientist, this is a terrific project to get your feet wet!

Source Code:

'''
Netflix Recommendation Engine
-------------------------------------------------------------
pip install pandas numpy nltk
'''


from nltk.tokenize import word_tokenize
import numpy as np
import pandas as pd
import re
import nltk
import tkinter as tk
from nltk.corpus import stopwords
nltk.download('stopwords')

data = pd.read_csv('netflixData.csv')
data = data.dropna(subset=['Cast', 'Production Country', 'Rating'])
movies = data[data['Content Type'] == 'Movie'].reset_index()
movies = movies.drop(['index', 'Show Id', 'Content Type', 'Date Added',
                    'Release Date', 'Duration', 'Description'], axis=1)
movies.head()
tv = data[data['Content Type'] == 'TV Show'].reset_index()
tv = tv.drop(['index', 'Show Id', 'Content Type', 'Date Added',
            'Release Date', 'Duration', 'Description'], axis=1)
tv.head()
actors = []
for i in movies['Cast']:
   actor = re.split(r', \s*', i)
   actors.append(actor)
flat_list = []

for sublist in actors:
   for item in sublist:
       flat_list.append(item)

actors_list = sorted(set(flat_list))
binary_actors = [[0] * 0 for i in range(len(set(flat_list)))]
for i in movies['Cast']:
   k = 0
   for j in actors_list:
       if j in i:
           binary_actors[k].append(1.0)
       else:
           binary_actors[k].append(0.0)
       k += 1

binary_actors = pd.DataFrame(binary_actors).transpose()
directors = []
for i in movies['Director']:
   if pd.notna(i):
       director = re.split(r', \s*', i)
       directors.append(director)

flat_list_2 = []
for sublist in directors:
   for item in sublist:
       flat_list_2.append(item)

directors_list = sorted(set(flat_list_2))
binary_directors = [[0] * 0 for i in range(len(set(flat_list_2)))]
for i in movies['Director']:
   k = 0
   for j in directors_list:
       if pd.isna(i):
           binary_directors[k].append(0.0)
       elif j in i:
           binary_directors[k].append(1.0)
       else:
           binary_directors[k].append(0.0)
       k += 1

binary_directors = pd.DataFrame(binary_directors).transpose()
countries = []
for i in movies['Production Country']:
   country = re.split(r', \s*', i)
   countries.append(country)

flat_list_3 = []
for sublist in countries:
   for item in sublist:
       flat_list_3.append(item)

countries_list = sorted(set(flat_list_3))
binary_countries = [[0] * 0 for i in range(len(set(flat_list_3)))]
for i in movies['Production Country']:
   k = 0
   for j in countries_list:
       if j in i:
           binary_countries[k].append(1.0)
       else:
           binary_countries[k].append(0.0)
       k += 1

binary_countries = pd.DataFrame(binary_countries).transpose()
genres = []
for i in movies['Genres']:
   genre = re.split(r', \s*', i)
   genres.append(genre)

flat_list_4 = []
for sublist in genres:
   for item in sublist:
       flat_list_4.append(item)

genres_list = sorted(set(flat_list_4))
binary_genres = [[0] * 0 for i in range(len(set(flat_list_4)))]
for i in movies['Genres']:
   k = 0
   for j in genres_list:
       if j in i:
           binary_genres[k].append(1.0)
       else:
           binary_genres[k].append(0.0)
       k += 1

binary_genres = pd.DataFrame(binary_genres).transpose()
ratings = []
for i in movies['Rating']:
   ratings.append(i)

ratings_list = sorted(set(ratings))
binary_ratings = [[0] * 0 for i in range(len(set(ratings_list)))]
for i in movies['Rating']:
   k = 0
   for j in ratings_list:
       if j in i:
           binary_ratings[k].append(1.0)
       else:
           binary_ratings[k].append(0.0)
       k += 1

binary_ratings = pd.DataFrame(binary_ratings).transpose()
binary = pd.concat([binary_actors, binary_directors,
                  binary_countries, binary_genres], axis=1, ignore_index=True)
actors_2 = []
for i in tv['Cast']:
  actor2 = re.split(r', \s*', i)
  actors_2.append(actor2)

flat_list_5 = []
for sublist in actors_2:
   for item in sublist:
       flat_list_5.append(item)

actors_list_2 = sorted(set(flat_list_5))
binary_actors_2 = [[0] * 0 for i in range(len(set(flat_list_5)))]
for i in tv['Cast']:
   k = 0
   for j in actors_list_2:
       if j in i:
           binary_actors_2[k].append(1.0)
       else:
           binary_actors_2[k].append(0.0)
       k += 1

binary_actors_2 = pd.DataFrame(binary_actors_2).transpose()
countries_2 = []
for i in tv['Production Country']:
   country2 = re.split(r', \s*', i)
   countries_2.append(country2)

flat_list_6 = []
for sublist in countries_2:
   for item in sublist:
       flat_list_6.append(item)

countries_list_2 = sorted(set(flat_list_6))
binary_countries_2 = [[0] * 0 for i in range(len(set(flat_list_6)))]
for i in tv['Production Country']:
   k = 0
   for j in countries_list_2:
       if j in i:
           binary_countries_2[k].append(1.0)
       else:
           binary_countries_2[k].append(0.0)
       k += 1

binary_countries_2 = pd.DataFrame(binary_countries_2).transpose()
genres_2 = []
for i in tv['Genres']:
   genre2 = re.split(r', \s*', i)
   genres_2.append(genre2)

flat_list_7 = []
for sublist in genres_2:
   for item in sublist:
       flat_list_7.append(item)

genres_list_2 = sorted(set(flat_list_7))
binary_genres_2 = [[0] * 0 for i in range(len(set(flat_list_7)))]
for i in tv['Genres']:
   k = 0
   for j in genres_list_2:
       if j in i:
           binary_genres_2[k].append(1.0)
       else:
           binary_genres_2[k].append(0.0)
       k += 1

binary_genres_2 = pd.DataFrame(binary_genres_2).transpose()
ratings_2 = []
for i in tv['Rating']:
   ratings_2.append(i)

ratings_list_2 = sorted(set(ratings_2))
binary_ratings_2 = [[0] * 0 for i in range(len(set(ratings_list_2)))]
for i in tv['Rating']:
   k = 0
   for j in ratings_list_2:
       if j in i:
           binary_ratings_2[k].append(1.0)
       else:
           binary_ratings_2[k].append(0.0)
       k += 1

binary_ratings_2 = pd.DataFrame(binary_ratings_2).transpose()
binary_2 = pd.concat([binary_actors_2, binary_countries_2,
                    binary_genres_2], axis=1, ignore_index=True)

window = tk.Tk()
window.geometry('600x600')
head = tk.Label(window, text='Enter Movie / TV Show on Netflix For Recommendations', font=('Calibri 15'))
head.pack(pady=20)


def netflix_recommender(search):
   cs_list = []
   binary_list = []

   if search in movies['Title'].values:
       idx = movies[movies['Title'] == search].index.item()
       for i in binary.iloc[idx]:
           binary_list.append(i)

       point_1 = np.array(binary_list).reshape(1, -1)
       point_1 = [val for sublist in point_1 for val in sublist]
       for j in range(len(movies)):
           binary_list_2 = []
           for k in binary.iloc[j]:
               binary_list_2.append(k)
           point_2 = np.array(binary_list_2).reshape(1, -1)
           point_2 = [val for sublist in point_2 for val in sublist]
           dot_product = np.dot(point_1, point_2)
           norm_1 = np.linalg.norm(point_1)
           norm_2 = np.linalg.norm(point_2)
           cos_sim = dot_product / (norm_1 * norm_2)
           cs_list.append(cos_sim)

       movies_copy = movies.copy()
       movies_copy['cos_sim'] = cs_list
       results = movies_copy.sort_values('cos_sim', ascending=False)
       results = results[results['title'] != search]
       top_results = results.head(5)
       return (top_results)

   elif search in tv['Title'].values:
       idx = tv[tv['Title'] == search].index.item()
       for i in binary_2.iloc[idx]:
           binary_list.append(i)

       point_1 = np.array(binary_list).reshape(1, -1)
       point_1 = [val for sublist in point_1 for val in sublist]
       for j in range(len(tv)):
           binary_list_2 = []
           for k in binary_2.iloc[j]:
               binary_list_2.append(k)

           point_2 = np.array(binary_list_2).reshape(1, -1)
           point_2 = [val for sublist in point_2 for val in sublist]
           dot_product = np.dot(point_1, point_2)
           norm_1 = np.linalg.norm(point_1)
           norm_2 = np.linalg.norm(point_2)
           cos_sim = dot_product / (norm_1 * norm_2)
           cs_list.append(cos_sim)

       tv_copy = tv.copy()
       tv_copy['cos_sim'] = cs_list
       results = tv_copy.sort_values('cos_sim', ascending=False)
       results = results[results['Title'] != search]
       top_results = results.head(5)
       return (top_results)

   else:
       return ('Title not in dataset. Please check spelling.')


def call_recommender():
  subject = text.get()
  recommendation = netflix_recommender(subject)
  txt = ''
  for i in recommendation.iterrows():
      txt += 'Title: ' + str(i[1][0]) + '\n'
  tk.Label(window, text=txt, font=('Calibri 15')).place(x=195, y=150)


text = tk.StringVar()
tk.Entry(window, textvariable=text).place(x=200, y=80, height=30, width=280)
tk.Button(window, text='Find Recommendations',
         command=call_recommender).place(x=285, y=150)
window.mainloop()

 Bonus Project: Age Calculator

I recently made a new project based on a reader request. The novice programmer wanted to make an age calculator in Python, but he was having trouble. That's why I wrote this article.

Like my projects above, this one contains source code and an explanation about why I used the code I used.

How to Build an Age Calculator in Python

Where To Start With Python

Today, we’re experiencing an ever-growing adoption of Artificial Intelligence (AI), Machine Learning (ML), and data science across the vast majority of business sectors. One of the main things these fields have in common is that they use the Python programming language in one way or another.

When it comes to learning Python in 2024, you have so many choices. Plus, if you'd prefer an in-depth and interactive learning experience, we’d also recommend our new Python course

What Should I Build Using Python?

This is a great question, especially if you’re brand new to coding in Python.

Well, first things first, you should know that there are so many Python applications in various disciplines, so you have lots of options.

Of course, Python has developed a solid reputation for data science, data analysis, machine learning, and AI, but it doesn’t end there.

It’s also really good when it comes to web development, thanks to popular web application frameworks like Django and Flask.

Equally, it’s also ideal for automating repetitive tasks, hence its origin as a scripting language.

To put it simply, you can build a lot with Python, but if you’re looking for inspiration, you’re in the right place!

That's why I put together 30 Python projects for you to get stuck into, ranging from beginner to advanced.

Wrapping Up

And there we have it! If you've taken the time to build these 30 Python projects, you should be feeling much more competent and confident with Python.

You'll also have a burgeoning Python portfolio that's packed full of interesting and practical Python projects, each demonstrating your dedication and abilities.

I also hope you enjoyed following along with my step-by-step tutorial in the first Python project!

My motivation with these Python tutorials is to guide you through the nuances of Python development while also giving you hands-on experience that you'd usually only get when taking a Python course.

Here at hackr.io, we're huge fans of project-based learning, so I hope these Python projects have bolstered your confidence and sparked a deeper interest in web development or any other form of Python development.

Remember, the journey doesn't end here!

With new projects and step-by-step tutorials regularly added to this page, be sure to check back often for new opportunities to refine your Python skills and expand your portfolio.

Happy coding!

Enjoyed tackling these Python projects and are ready to dive deeper into Python? Check out:

Our Python Masterclass - Python with Dr. Johns

Frequently Asked Questions

1. Is Python Suitable for Large Projects?

Although there is the argument that Python is slower than other popular languages like C and C++, Python is still widely used by many top tech companies because it is super versatile, easily maintainable, and offers a ton of libraries and support from the community.

2. What Should My First Python Project Be?

Check out any of the Python beginner projects we’ve covered above, including Mad Libs, Rock Paper Scissors, Hangman, or Tic-Tac-Toe!

People are also reading:

References

1. Bureau of Labor Statistics, U.S. Department of Labor. Occupational Outlook Handbook, Software Developers [Internet]. [updated 2021 Sep 8; cited 2024 Jan 15]. Available from: https://www.bls.gov/ooh/computer-and-information-technology/software-developers.htm

2. apilayer. FIXER API - Pricing [Internet]. apilayer; [date unknown; cited 2024 Jan 15]. Available from: https://apilayer.com/marketplace/fixer-api#pricing

3. [no author]. OAuth2 Quick Start Example [Internet]. GitHub; [updated 2016 Apr 26; cited 2024 Jan 15]. Available from: https://github.com/reddit-archive/reddit/wiki/OAuth2-Quick-Start-Example#first-steps

4. Makhija, S. Netflix Movies and TV Shows 2021 [dataset]. Kaggle; 2021. Available from: https://www.kaggle.com/datasets/satpreetmakhija/netflix-movies-and-tv-shows-2021?resource=download

 
By Robert Johns

Technical Editor for Hackr.io | 15+ Years in Python, Java, SQL, C++, C#, JavaScript, Ruby, PHP, .NET, MATLAB, HTML & CSS, and more... 10+ Years in Networking, Cloud, APIs, Linux | 5+ Years in Data Science | 2x PhDs in Structural & Blast Engineering

View all post by the author

Subscribe to our Newsletter for Articles, News, & Jobs.

I accept the Terms and Conditions.

Disclosure: Hackr.io is supported by its audience. When you purchase through links on our site, we may earn an affiliate commission.

In this article

Learn More

Please login to leave comments

Akib Dewan

all codes has so many mistakes

3 years ago

Robert Johns

Thanks for pointing this out. If you take a look at our latest projects, they should be all bug-free.

1 year ago

Robert Johns

Thanks for pointing this out. If you take a look at our latest projects, they should be all bug-free.

1 year ago

Esther Ndosi

Thank you for all these cool projects. Its great to start a year with them. On the second project I think the attempts should be appended after the guess == rand_num as it always print 1 and i think it should be the lowest attempts the user has. thank you.

9 months ago

Robert Johns

Thanks for taking the time to build these projects and spotting that. The second project has been updated, check it out and see what you think.

9 months ago

Robert Johns

Thanks for taking the time to build these projects and spotting that. The second project has been updated, check it out and see what you think.

9 months ago

Akash Roy

Embarking on a Python journey with these hands-on projects feels like unlocking a treasure trove of coding adventures!

5 months ago