DEV Community

loading...
Cover image for Python - What I learned in 1 hour 🐍

Python - What I learned in 1 hour 🐍

firangizg profile image Firangiz Ganbarli ・7 min read

These are just my notes on the Python lecture of CS50 - Web Programming with Python and JavaScript. Please refer to other sources for complete introduction or more advanced content on the language.

Python is a high-level, interpreted language that is not compiled directly. In python, an interpreter reads through the code file line-by-line and executes each.

Variables and String Formatting

Assigning variables is shown below, along with the variable type they are:

a = 28  # int
b = 1.5  # float
c = "Hello!"  # str
d = True  # bool
e = None  # NoneType
Enter fullscreen mode Exit fullscreen mode

Using this, we can write a simple program such that the user inputs their name, and the computer outputs "Hello, [name]" like below:

name = input("Name: ")
print("Hello, " + name)
Enter fullscreen mode Exit fullscreen mode
  • In the first line, input() function asks the user for an input and this input is assigned to the variable name.
  • In the second line, '+' sign is used to concatenate the two strings, join them together.

To manipulate strings more efficiently, we can use f-strings, otherwise known as formatted strings. It is shown as:

print(f"Hello, {name}.")
Enter fullscreen mode Exit fullscreen mode

In the code above, f is added before quotes so that we can include the variable name in the string.

Conditions

Conditions should be familiar to you if you have ever programmed in another language. In Python, the syntax is pretty simple:

age = int(input("Age: "))
if num > 16:
    print("You are over 16.")
elif num < 16:
    print("You are younger than 16.")
else:
    print("You are 16 years old.")
Enter fullscreen mode Exit fullscreen mode

As you can notice, indentation is pretty important in Python. It lets the computer know what's inside and outside of the functions and loops.

Another thing you can notice is the use of int(input("Age: ")). We convert the input variable into integer, because when the user types in their age, it is considered a string first. Since we can't compare strings and integers, we have to convert the string into type int.

Sequences

There are different types of sequences of data.

Mutable sequences are changeable. We can change elements, add, or remove them.

Ordered sequences care about the order of the objects, and output the sequence of data sorted.

We will look at both mutable, immutable and ordered, unordered sequences.

Strings ➜ ordered and immutable

We can think of strings as a sequence of characters, such that we can access a character in a string. The code

name = "Firangiz"
print(name[0]) 
Enter fullscreen mode Exit fullscreen mode

prints out the first letter of the name variable which is F.

Lists ➜ ordered and mutable

We can store any variable type in lists. We can print an entire list or elements within the list. Since lists are mutable, we can also add elements to a list using .append() and sort them using .sort():

cities = ['New York', 'Baku', 'Istanbul']
print(cities) # prints the entire list
print(cities[1]) # outputs Baku
cities.append('Beijing') # adds Beijing to the list
cities.sort() # sorts the list alphabetically
print(cities) # prints out the new list
Enter fullscreen mode Exit fullscreen mode

Try the code above for yourselves and experiment with it.

Tuples ➜ ordered and immutable

Tuples are usually used to store 2 or 3 values together. They are immutable, so we can't add or remove elements of tuples. Example use of it would be to store coordinate values of a point:

point = (2.5, 8)
Enter fullscreen mode Exit fullscreen mode

Sets ➜ unordered

Sets are unordered. Lists or tuples allow duplicate elements, while sets store a value only once. If a set has the value '3', and we add it again, final set will only have one '3', not two.

# create an empty set
s = set()

# add elements
s.add(4)
s.add(2)
s.add(3)

# remove 3 from the set
s.remove(3)

print(s)

# find the size of the set
print(f"This set has {len(s)} elements.")
Enter fullscreen mode Exit fullscreen mode

Dictionaries ➜ unordered and mutable

Dictionary is a set of key-value pairs (like a literal dictionary contains word-definition pairs). Dictionary looks like this:

# defining the dict
hobby = {"Firangiz": 'Traveling', "Alice": 'Basketball'} 

# print out Firangiz's hobby
print(hobby["Firangiz"])

# add values to a dict
hobby["Gary"] = 'Photography'

# print Gary's hobby
print(hobby["Gary"])
Enter fullscreen mode Exit fullscreen mode

For loops

For loops iterate over a sequence of elements and perform an indented code for each element in the sequence. Code below outputs numbers from 0 to 5.

for i in [0, 1, 2, 3, 4, 5]:
    print(i)
Enter fullscreen mode Exit fullscreen mode

We can shorten this code using range function. Range function allows us to get a sequence of numbers easily like below:

for i in range(6):
    print(i)
Enter fullscreen mode Exit fullscreen mode

You can notice that both for loops we have written output the same code. And our elements don't have to be numbers. We can iterate over characters in a string too:

name = "Francesco"
for character in name:
    print(character)
# Outputs each character of the name in separate lines
Enter fullscreen mode Exit fullscreen mode

Functions and Modules

To write our own function, we first have to define the function.

def square(x):
    return x * x
Enter fullscreen mode Exit fullscreen mode

def is used to define a function, and we make it clear that our square function takes a single input x. Our function should return the square of the input.

To see this in action, we have to call this function.

for i in range(11):
   print(f"The square of {i} is {square(i)}")
Enter fullscreen mode Exit fullscreen mode

When we run this code, it should output the print statement with squares of every number from 0-11. (11 excluded)

In the example above, we defined and called the function in the same file. But as we work on larger files and projects, we may need to use a function we defined in another file.

Let's say we have two files, one called functions.py and the other square.py. In functions file, we will include the definition of our function and in square file, we will add the calling of the function.

Right now, the code would give an error, since it doesn't have access to functions module. That's why we have to import the square function from the functions module. This is as simple as writing from functions import square. We can also import the whole functions module, but specify the square function by using functions.square(i).

Object-Oriented Programming

Object-oriented programming is centered around objects that store information and perform actions.

Python classes are templates for a new object that can store info and perform actions. We can use a class to define a point:

class Point():
    # defines how to create a point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
# use the class above to create the object
p = Point(1, 4)

# print out x and y coordinates of the point
print(p.x)
print(p.y)
Enter fullscreen mode Exit fullscreen mode

Self keyword is necessary to represent the object we are working with and is the first argument for any method in a Python class.

Let's look into a real life case: we create a class representing airline flight, and should consider the capacity and passenger count so there is no overbooking.

class Flight():
    # create new flight with given capacity and add an empty list of passengers
    def __init__(self, capacity):
        self.capacity = capacity
        self.passengers = []

    # add a passenger to the flight and don't if there are no open seats
    def add_passenger(self, name):
        if not self.open_seats():
            return False
        self.passengers.append(name)
        return True

    # return the number of open seats
    def open_seats(self):
        return self.capacity - len(self.passengers)
Enter fullscreen mode Exit fullscreen mode

Functional Programming

In Functional Programming, functions are treated as values like any other variable

Decorators

Decorator is a higher-order function that can modify another function.

We can write a decorator that announces when a function is going to begin and when it ends.

def announce(f):
    def wrapper():
        print("About to run the function")
        f() # run the function
        print("Done with the function")
    return wrapper

@announce # apply the decorator defined above
def hello():
    print("Hello, world!")

hello() # call our function hello
""" output will be 
About to run the function
Hello, world!
Done with the function
"""
Enter fullscreen mode Exit fullscreen mode

Lambda Functions

Lambda functions allow alternate way to create functions. If we define the square function above using lambda functions, we would write:

square = lambda x: x * x
Enter fullscreen mode Exit fullscreen mode

The input stays on the left of colons and output on the right. Lambda functions are useful for expressing functions shortly instead of writing a whole separate function for a small use.

Let's say we have a list of dictionaries and we want to sort this list. We can't use list.sort() because Python doesn't know how to compare dictionaries to see if one is less than the other.

To solve this, we introduce key argument to the sort function that specifies which part of dictionary we would like to sort:

# define the list
people = [
    {"name": "Harry", "house": "Gryffindor"},
    {"name": "Cho", "house": "Ravenclaw"},
    {"name": "Draco", "house": "Slytherin"}
]

# define a function that returns the name of the people
def f(person):
    return person["name"]

# sort the list by names 
people.sort(key=f)

# print out the new list
print(people)
Enter fullscreen mode Exit fullscreen mode

This works. But, there is room for improvement. We can eliminate the f function by using lambda functions. Instead of defining f function and sorting them, we can combine them like this:

people.sort(key=lambda person: person["name"])
Enter fullscreen mode Exit fullscreen mode

Exceptions

There are some exceptions that lead to errors when we write code. As an example, let's look at the following code and see the exceptions:

x = int(input("x: "))
y = int(input("y: "))

result = x / y

print(f"{x} / {y} = {result}")
Enter fullscreen mode Exit fullscreen mode
  1. We run into problems when y = 0, since we can't divide by zero.
  2. We have ValueError when user enters nonnumerical values for x and y.

We can solve ZeroDivisionError and ValueError using Exception Handling. We will try to assign x to the first input and y to the second input, except if there is a ValueError, our program will output a print statement indicating there is an error and then exist.

Similar to this, the program will try to divide x by y to get the result, except for when there is ZeroDivisionError, in which it outputs an error line and exists. We can make the program exit by importing sys module and using sys.exit(1)

import sys

try:
    x = int(input("x: "))
    y = int(input("y: "))

except ValueError:
    print("Error: Invalid input")
    sys.exit(1)

try:
    result = x / y

except ZeroDivisionError:
    print("Error: Cannot divide by 0.")
    # Exit the program
    sys.exit(1)

print(f"{x} / {y} = {result}")

Enter fullscreen mode Exit fullscreen mode

That's it for this post, folks. I hope this was helpful. Comment any suggestions or additions! Are you taking CS50, how is it going?

Thank you!

Discussion (0)

pic
Editor guide