W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)

Video: https://youtu.be/EHi0RDZ31VA

#CS50x #Python #Computer_Science

Read more here
Related:

🔙 Previous Part | Next Part 🔜

↩️ Go Back

Table of Contents:

↩️ Go Back


A) Transitioning from C to Python

A.1) Introduction to Python


A.2) Simplifying "Hello, World" - Differences Between C and Python

Simplified Syntax: Python eliminates the need for repeated template code (e.g., no main() or curly braces).

#include <stdio.h>
int main(void) {
	printf("Hello, world\n");
}

In Python, the same result is achieved with:

print("Hello, world")

More Differences:

  1. No need to include libraries explicitly (e.g., <stdio.h> in C).
  2. No main() function is required.
  3. Syntax is cleaner—no semicolons (;) or curly braces ({}).
  4. New lines (\n) are handled automatically in print().

Summary: Differences Between C and Python

Aspect C Python
Syntax for Hello World Requires #include, main(), semicolons, printf() Simplified to print("Hello, world")
Compilation Requires clang and manual compilation steps. Directly run with python hello.py.
Libraries Must include libraries (e.g., #include <stdio.h>). Functions like print() work without explicit imports.
Semicolons Required. Not required.
Newline Character Explicit with \n. Implicit in print().
Quotes for Strings Double quotes required for strings. Supports single or double quotes.
Memory Management Manual (malloc, free). Automatic (managed by Python).

A.2.1) Compilation vs Interpretation

Example: Running Python Code

python hello.py

Note: Code is executed line-by-line using the [[python interpreter]]


A.3) Practical Demonstration: Python’s Simplicity for Problem Solving

A.3.1) Implementing a Spell Checker in Python (Comparison with C)

Example of re-implementing Problem Set 5's spell checker using Python.


  1. File Overview:

    • dictionary.py: Replaces dictionary.c.
    • speller.py: Replaces speller.c.
  2. Implementing dictionary.py:

# Global variable: a set to store words
words = set()

# Check if a word is in the dictionary
def check(word):
    return word.lower() in words

# Load the dictionary into memory
def load(dictionary):
    with open(dictionary) as file:
        words.update(file.read().splitlines())
    return True

# Get the size of the dictionary
def size():
    return len(words)

# No unload needed in Python; memory is managed automatically
def unload():
    return True

  1. Running the Program:
    • Run speller.py on holmes.txt:
python speller.py texts/holmes.txt

Python Advantages: Python's built-in data types simplify tasks.

  1. Ease of Use:
    • Functions like len() simplify tasks.
    • No need to manually manage memory.
  2. Efficiency in Development:
    • Example: Building a dictionary in Python takes significantly fewer lines of code.
  3. Rich Libraries:
    • Functions and tools readily available (e.g., splitlines() for file handling).

Python Trade-offs:


A.3.2) Image Processing with Python (using Pillow (PIL))

Python makes image manipulation simple with libraries like Python Imaging Library also known as [[PIL (Pillow)]].

A.3.2.1) Example1: Blurring an Image
    from PIL import Image, ImageFilter
    
    before = Image.open("bridge.bmp")
    after = before.filter(ImageFilter.BoxBlur(10))
    after.save("out.bmp")
python blur.py
A.3.2.2) Example2: Edge Detection

A.4) DEMO: Face Recognition with Python (AI trained models)

Using Libraries

pip install face_recognition

Detecting Faces

Recognizing Specific Faces:
Compare a known face with faces in an image,

import face_recognition

Load group and target images

group_image = face_recognition.load_image_file("office.jpg")
target_image = face_recognition.load_image_file("toby.jpg")

Encode faces

group_encodings = face_recognition.face_encodings(group_image)
target_encoding = face_recognition.face_encodings(target_image)[0]

Compare and highlight

results = face_recognition.compare_faces(group_encodings, target_encoding)
for i, match in enumerate(results):
if match:
print(f"Match found at position {i}")

```

Output:


A.5) Python vs. C: When to Use Each?

Why Python?

Aspect C Python
Performance Faster, more efficient with memory. Slower due to abstraction overhead.
Ease of Coding Requires more boilerplate code. Concise and easier to write.
Use Case Embedded systems, performance-critical tasks. Rapid prototyping, data analysis, and high-level tasks.

Python’s design emphasizes simplicity and productivity. While it trades some speed and efficiency compared to lower-level languages like C, it empowers programmers to accomplish tasks more quickly and with less code. As CS50 transitions into higher-level concepts, Python exemplifies how abstractions can streamline problem-solving without sacrificing power.


B) Comparing Scratch and C to Python (Learn Python's Basics)

B.1) Functions in Python


B.2) Libraries in Python


B.3) Variables and Data Types in Python

Variable Declaration:

  1. Variable Declaration:

    • In C:

      int counter = 0;
      
    • In Python:

      counter = 0
      

Note: Differences from C,
- No need to specify data types (int, float, etc.).
- No need to manage memory manually.

Incrementing Variables:

  1. Incrementing Variables:

    • In C:

      counter = counter + 1;  // Or: counter += 1 Or: counter++
      
    • In Python:

      counter += 1 #but counter++ is not available
      
  2. Available Data Types in Python:

    • Primitive Types:
      • bool: True, False
      • int: Integer values
      • float: Floating-point numbers
      • str: Strings
    • Advanced Types:
      • list: Similar to arrays but more flexible.
      • tuple: Immutable ordered collection.
      • dict: Dictionaries (hash tables).
      • set: Collections with unique elements.
      • range: was a built-in function that returned a list in Python 2. …and it’s a datatype in Python 3: it is an immutable sequence.

B.4) Input and String Concatenation in Python

In Scratch

  1. C Version:

    #include <cs50.h>
    #include <stdio.h>
    int main(void) {
        string answer = get_string("What's your name? ");
        printf("hello, %s\n", answer);
        return 0;
    }
    
  2. Python Version:

    from cs50 import get_string
    answer = get_string("What's your name?")
    print("hello, " + answer)
    

Note: Python: String Concatenation:

Note: Simplifying Input:


B.4.1) Example: A Simple Calculator

  1. C Implementation:

    #include <cs50.h>
    #include <stdio.h>
    int main(void) {
        int x = get_int("x: ");
        int y = get_int("y: ");
        printf("%i\n", x + y);
        return 0;
    }
    
  2. Python Implementation:

    from cs50 import get_int
    x = get_int("x: ")
    y = get_int("y: ")
    print(x + y)
    

Error1: need to convert string user input as an integer

Note: Replacing get_int() with input():


Error2: they protection from get_int and get_float from cs50
Tips: Importing Libraries in Python

But what happens if you have your own functions and they are named the same as some libraries?

You can do the following trick:

  1. Import the whole library:

    import cs50
    x = cs50.get_int("x: ")
    
  2. use cs50.get_int() to specify which function to use

    import cs50
    x = cs50.get_int("x: ")
    

B.5) Conditionals in Python

Conditionals in Python allow for decision-making in programs, analogous to the "if-else" blocks in Scratch or the "if-else" statements in C. However, Python simplifies the syntax and enforces indentation to ensure readable code.

  1. Scratch:

  2. C:

    if (x < y) 
    {
        printf("x is less than y\n");
    }
    
    • Requires:
      • Parentheses around conditions.
      • Curly braces for blocks. <-------------
      • Explicit \n for newlines.
      • Semicolons to terminate statements.

  1. Python:
    if x < y:
        print("x is less than y")
    
    • Simplifications:
      • No parentheses around conditions unless grouping is required.
      • No curly braces—indentation determines the block. <-------------
      • Colons (:) signify the start of a block.
      • No need for \n or semicolons.

Explanation:


Example: Conditionals - Compare Integers in Python

Three-Way Comparison (if, elif, else):

from cs50 import get_int

x = get_int("What's x? ")
y = get_int("What's y? ")

if x < y:
    print("x is less than y")
elif x > y:
    print("x is greater than y")
else:
    print("x is equal to y")


Example: Conditionals - String Comparison in Python

  1. C Limitation:

    if (s == t) {
        printf("Same\n");
    } else {
        printf("Different\n");
    }
    
    • Compares memory addresses of strings (char*), not their content.
    • Two identical strings in different memory locations are considered "different."
  2. Python Simplification:

    s = input("Enter first string: ")
    t = input("Enter second string: ")
    
    if s == t:
        print("Same")
    else:
        print("Different")
    
    • Python's == operator compares the content of strings, not memory addresses.

Example: Conditionals - Handling Case Insensitivity with Strings

Let's try to impement one of our C programs, but now in Python,
C Version:

#include <cs50.h>
#include <stdio.h>

int main(void) {
    char c = get_char("Do you agree? ");
    if (c == 'Y' || c == 'y') {
        printf("Agreed\n");
    } else if (c == 'N' || c == 'n') {
        printf("Not agreed\n");
    }
}

Python Version:

Problem with copying the C approach: Users may input strings with varying capitalizations (e.g., "Yes", "yes", "YES"). A robust program should account for this.

  1. New Python Approach: check in a collection of values
    if s in ["y", "yes", "Y", "YES"]:
        print("Agreed")
    elif s in ["n", "no", "N", "NO"]:
        print("Not agreed")
    
    • Use the in keyword to check if a value exists in a list
    • This approach becomes cumbersome as the number of variations increases.
Note: [[Object-Oriented Programming]] in Python (including methods in string objects)

  1. String Methods:
    • Python strings are objects with built-in methods.
    • Example: s.lower() converts a string to lowercase.
  2. Comparison to C:
    • C: Use tolower() from the ctype.h library:
      c char c = tolower(s);

    • Python: Use the method directly on the string object:
      python s = s.lower()

Note: find the documentation here,

  1. Improved Python Approach: use Lowercasing as a standard input from user with .lower()

    s = input("Do you agree? ").lower()
    
    if s in ["y", "yes"]:
        print("Agreed")
    elif s in ["n", "no"]:
        print("Not agreed")
    
  2. Chaining Method Calls:

    • Python allows chaining methods for concise code:

      s = input("Do you agree? ").strip().lower()
      
    • strip() removes leading/trailing spaces.

    • lower() converts input to lowercase.


"Agree Program" in Python vs "Agree Program" in C

C Version:

#include <cs50.h>
#include <stdio.h>

int main(void) {
    char c = get_char("Do you agree? ");
    if (c == 'Y' || c == 'y') {
        printf("Agreed\n");
    } else if (c == 'N' || c == 'n') {
        printf("Not agreed\n");
    }
}

Python Version:

s = input("Do you agree? ").lower()

if s in ["y", "yes"]:
    print("Agreed")
elif s in ["n", "no"]:
    print("Not agreed")

B.6) Loops in Python (dealing with Strings and Functions)

Loops in Python allow us to repeat actions, similar to Scratch and C. However, Python introduces some key differences that make loops more concise and intuitive.

While Loops in Python

  1. Repeat Three Times

    • Scratch: Repeat block.

    • C: Using a while loop:

      int i = 0;
      while (i < 3) {
          printf("meow\n");
          i++;
      }
      
    • Python: Simplified while loop:

      i = 0
      while i < 3:
          print("meow")
          i += 1
      
  2. Infinite Loops:

    • Scratch: Repeat forever

    • C:

      while (true) 
      {
          printf("meow\n");
      }
      
    • Python:

      while True:
          print("meow")
      
      • Note: True is capitalized in Python.

For Loops in Python

  1. Using a for Loop in Python: Python simplifies the for loop compared to C:

    for i in [0, 1, 2]:
        print("meow")
    

    Use:range(): Instead of manually specifying numbers:

    for i in range(3):
        print("meow")
    
    • range(3) generates numbers from 0 to 2.
    • No need to declare i or manually increment it.
  2. _ in Loops: If you don't use the loop variable i:

    for _ in range(3):
        print("meow")
    
    • _ signals that the variable is unused.

Example: Loops - String Manipulation in Python

  1. Uppercasing a String:

    • In C:

      for (int i = 0; i < strlen(str); i++) {
          str[i] = toupper(str[i]);
      }
      
    • In Python:

      before = input("Before: ")
      after = before.upper()
      print(f"After: {after}")
      

  1. Iterating Over a String: Strings in Python are iterable:

[[Named Parameters]]: The end Parameter in print():


Example: using Functions and Loops together in Python (create a main function)

let's improve our code by using functions,

  1. Basic Function Definition:

    • Python uses def to define functions:

      def meow():
          print("meow")
      
    • Call the function:

      meow()
      

Note: if the function is below the logic where it is called, it will cause issues

  1. Adding a main() Function: Python does not require a main() function, but it’s conventional to include one:
  1. Parameterizing Functions:
    • Pass arguments to make functions reusable:
      def meow(n):
          for _ in range(n):
              print("meow")
      
      meow(3)
      

  1. Default Arguments:
    • Define default values for parameters:
      def meow(n=3):
          for _ in range(n):
              print("meow")
      
      meow()  # Defaults to 3
      meow(5)  # Overrides default
      

Handling Numbers in Python (Truncation, Floating-Point Precision and Integer Overflow)

Python simplifies and enhances number operations compared to C.

  1. Integer Division and Truncation:

    • In C: Integer division truncates fractional parts:

      int x = 1, y = 3;
      float z = x / y; // Result: 0 (integer division)
      
    • In Python: Integer division automatically results in a float:

      x = 1
      y = 3
      z = x / y  # Result: 0.3333...
      
  2. Floating-Point Precision:

    • Python still has floating-point precision issues due to hardware limitations.
    • Example:
      z = 1 / 3
      print(f"{z:.50f}")  # Prints 50 decimal places
      

    • Solution: Use libraries like decimal for higher precision.
  3. Integer Overflow:

    • In C: Overflow occurs when exceeding the fixed bit size.
    • In Python: Integers automatically scale with memory, preventing overflow.

C) Introducing New Python Concepts

Example: Error Handling with Exceptions

Python introduces a robust mechanism to handle errors using exceptions.

Let's first write some buggy code, the calculator works fine with numbers,

but is the user inputs something else, the program shows an error,

Note: we got an [[ValueError]], we can use this value and define [[exceptions]] and handle this issue.

  1. Handling Value Errors:

    • Example: Invalid input causing a ValueError.
    try:
        x = int(input("Enter an integer: "))
    except ValueError:
        print("Not an integer!")
    
  2. Custom Input Handling:

    • Using a loop to repeatedly prompt for valid input:
    def get_int(prompt):
        while True:
            try:
                return int(input(prompt))
            except ValueError:
                print("Not an integer!")
    


Loops and Patterns in Python (Mario Pyramids)

  1. 1D Patterns:

    • Building a Column:
    for i in range(3):
        print("#")
    

    • Printing a row of characters:
      print("?" * 4)  # Outputs: ????
      

    Equivalent:

  2. 2D Patterns:

    • Printing a 3x3 grid:
      for i in range(3):
          for j in range(3):
              print("#", end="")
          print()  # Moves to the next row
      

  1. Efficient 2D Patterns:
    • Combining ideas to simplify nested loops:
      for i in range(3):
          print("#" * 3)  # Prints a row of 3 hashes
      


Dynamic Patterns with User Input

  1. Prompting for a Height:

    • Using a loop to validate input:
      while True:
          try:
              height = int(input("Height: "))
              if height > 0:
                  break
          except ValueError:
              pass
      
  2. Building a Column:

    for i in range(height):
        print("#")
    

  1. Building a Row:

    print("#" * height)
    
  2. Building a Grid:

    for i in range(height):
        print("#" * height)
    

Lists in Python

Lists in Python are flexible, dynamic, and come with built-in methods for common operations.

Note: documentation


Example: Searching in Lists

Python simplifies linear search with the in operator.


Dictionaries in Python

[[Dictionaries]] are a collection of key-value pairs and are equivalent to [[hash tables]] in C.

Read documentation:

people = {
	"Carter": "+1-617-495-1000",
	"David": "+1-617-495-1000",
	"John": "+1-949-468-2750"
}

or simplify like this:


Advantages of Python Dictionaries


Comparison: Lists vs. Dictionaries

Feature Lists Dictionaries
Data Storage Ordered collection Key-value pairs
Access Method Index-based (e.g., 0) Key-based (e.g., "name")
Usage Sequential operations Lookup and associations
Performance Slower for lookups Fast for key-based lookups
Takeaways:

Command-Line Arguments in Python (sys.argv)

Read documentation:


Exiting Programs with sys.exit()


Having Fun Using External Python Libraries

Python offers a rich ecosystem of libraries.

a. cowsay Library

b. qrcode Library


Key Takeaways: Comparing Python to C


Y) Learn more Python Here

Enroll here

Notes: ℹ️ CS50's Introduction to Python (MOC)

Playlist - 10 lectures

Related: ℹ️ IT Automation with Python - Google Professional Certificate (MOC)

Related: ℹ️ CS50's Introduction to Artificial Intelligence with Python (MOC)


🔙 Previous Part | Next Part 🔜

↩️ Go Back


Z) 🗃️ Glossary

File Definition
Uncreated files Origin Note
Dictionaries W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
exceptions W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
hash tables W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
high-level language W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
↩️ Go Back W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
Interpreted language W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
linked lists W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
named parameter W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
Named Parameters W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
Object-Oriented Programming W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
PIL (Pillow) W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
Python W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
python interpreter W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)
ValueError W6 - 👨‍🏫 Lecture - Introduction to Python (A Transition from C)