The if statement


The if statement is used for conditional execution:


Syntax:

if <condition>:
       # write code here with indent
elif <condition>:
       # write code here with indent
                ….
else:
       # write code here with indent


Example:

num = input('Enter a Number: ')
num = int(num)

if num <= 0:
    print('Invalid Number')
elif num % 2 == 0:
    print('Even Number')
else:
    print('Odd Number')

print('End of the program')



Match Statements


A match statement takes an expression and compares its value to successive patterns given as one or more case blocks. This is superficially similar to a switch statement in C, Java or JavaScript (and many other languages), but it’s more similar to pattern matching in languages like Rust or Haskell. Only the first pattern that matches gets executed and it can also extract components (sequence elements or object attributes) from the value into variables.


The simplest form compares a subject value against one or more literals:


colour = input("Enter a colour: ")

match colour:
    case "red":
        print("You chose red")
    case "green"|"Green":
        print("You chose green")
    case "blue":
        print("You chose blue")
    case _:
        print("Colour not available")


for Statement and range() function


The for statement in Python differs a bit from what you may be used to in C or Pascal. Rather than always iterating over an arithmetic progression of numbers (like in Pascal), or giving the user the ability to define both the iteration step and halting condition (as C), Python’s for statement iterates over the items of any sequence (a list or a string), in the order that they appear in the sequence. 


If you do need to iterate over a sequence of numbers, the built-in function range() comes in handy. 


Syntax:

#FOR Loop Syntax:-

for variable in <seq_list/range>:
    #statements come here

# Range Syntax:-

#the range starts from 0 and ends with (end_num-1)
range(<end_num>)

#you can control the starting number like this
range(<start_num>,<end_num>)


Example:

name='Christopher'

# A string becomes a character array by default
for c in name:
    print(c)

for i in range(7,10):
    print(i)


While Loop, break and continue statements


Python while loop is used to run a block code until a certain condition is met.


while <condition>:
    #statements come here


The break statement, like in C, breaks out of the innermost enclosing for or while loop.

The continue statement, also borrowed from C, continues with the next iteration of the loop.


Example:

i = 0
while i < 5:
    print(i)
    i += 1

i = 0
while True:
    i += 1
    if i == 10:
        break
    elif i % 2 == 0:
        continue
    print(i)



Pass


In Python, the pass statement, much like a comment, is considered a null statement, meaning that it doesn't result in any Python operations. 


The only difference between a comment and a pass statement is that while a comment is completely ignored by the interpreter, the pass statement is not (but, like a comment statement, nothing is executed because of a pass).


Example:

i=0

while i <= 3:
    if i == 2:
        pass
    print(i)
    i += 1

String indexing and slicing


Indexing


The characters in strings exist in specific locations. In other words, their order counts. The index is a numerical representation of where each character is located. The first character is at index 0, the second character is at index 1, the third character is at index 2, and so on. 


Note:

We always start at 0 when indexing in computer programming! 


Consider the following string:

  destination = 'San Francisco'


'S' is in the 0th index, 'a' is in the 1st index, 'n' is in the 2nd index, and so on, as shown in the following table:



Figure 1.13 – Diagrammatic representation of the character values and the corresponding positive index values


The characters of each index are accessed using bracket notation, as follows:

  destination[0]


The output is as follows:

’S’


To access the data from the first index, enter the following:

  destination[1]


The output is as follows:

’a’


Now, try adding -1 as the index value to access the last character of the string:

destination[-1]


The output is as follows:

’o’


Note

Negative numbers start at the end of the string. (It makes sense to start with -1 since -0 is the same as 0.) 




Slicing


A slice is a subset of a string or other element. A slice could be the whole element or one character, but it’s more commonly a group of adjoining characters.


Let’s say you want to access the fifth through eleventh letters of a string. So, you start at index 4 and end at index 10, as was explained in the Indexing section. When slicing, the colon symbol (:) is inserted between indices, like so: [4:10].


There is one caveat: the lower bound of a slice is always included, but the upper bound is not. So, in the preceding example, if you want to include the 10th index, you must use [4:11].


Now, let’s have a look at the following example for slicing.


Retrieve the fifth through eleventh letters of the destination variable, which you used in the

Indexing section: 

destination[4:11]


The output is as follows:

’Francis’


Retrieve the first three letters of destination: 

destination[0:3]


The output is as follows:

’San’


There is a shortcut for getting the first n letters of a string. If the first numerical character is omitted, Python will start at the 0th index.


Now, to retrieve the first eight letters of destination using the shortcut, use the following code: 

destination[:8]


The output is as follows:

’San Fran’


Finally, to retrieve the last nine letters of destination, use the following code: 

destination[-9:]


The output is as follows:

’Francisco’


The negative sign, -, means that we start at the end. So, the -9 parameter means start at the ninth- to-last letter, and the colon means we end at the last letter. 


To find the reverse of a string, we can have a look at the example below:

place = "San Francisco"

# Using for loop without range
for p in reversed(place):
    print(p,end="")
print()

# Using for loop with range
               # from, till, decrement
for p in range(len(place)-1,-1,-1):
    print(place[p],end="")
print()

#Using join
print("".join(reversed(place)))

# Using slicing
print(place[::-1])

Lists


Python knows a number of compound data types, used to group together other values. The most versatile is the list, which can be written as a list of comma-separated values (items) between square brackets. Lists might contain items of different types, but usually the items all have the same type.


squares = [1, 4, 9, 16, 25]
squares
#[1, 4, 9, 16, 25]


Like strings (and all other built-in sequence types), lists can be indexed and sliced:

squares[0]  # indexing returns the item
# 1
squares[-1]
# 25
squares[-3:]  # slicing returns a new list
# [9, 16, 25]

All slice operations return a new list containing the requested elements. This means that the following slice returns a shallow copy of the list:

squares[:]
# [1, 4, 9, 16, 25]

Lists also support operations like concatenation:

squares + [36, 49, 64, 81, 100]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]


Unlike strings, which are immutable, lists are a mutable type, i.e. it is possible to change their content:

cubes = [1, 8, 27, 65, 125]  # something's wrong here
4 ** 3  # the cube of 4 is 64, not 65!
# 64

cubes[3] = 64  # replace the wrong value
cubes
# [1, 8, 27, 64, 125]


You can also add new items at the end of the list, by using the append() method :

cubes.append(216)  # add the cube of 6
cubes.append(7 ** 3)  # and the cube of 7
cubes
# [1, 8, 27, 64, 125, 216, 343]

Assignment to slices is also possible, and this can even change the size of the list or clear it entirely:

letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
letters
# ['a', 'b', 'c', 'd', 'e', 'f', 'g']

# replace some values
letters[2:5] = ['C', 'D', 'E']
letters
# ['a', 'b', 'C', 'D', 'E', 'f', 'g']

# now remove them
letters[2:5] = []
letters
# ['a', 'b', 'f', 'g']

# clear the list by replacing all the elements with an empty list
letters[:] = []
letters
# []


The built-in function len() also applies to lists:

letters = ['a', 'b', 'c', 'd']
len(letters)
# 4



It is possible to nest lists (create lists containing other lists), for example:

a = ['a', 'b', 'c']
n = [1, 2, 3]
x = [a, n]
x
# [['a', 'b', 'c'], [1, 2, 3]]

x[0]
# ['a', 'b', 'c']

x[0][1]
# 'b'


List Comprehension


List comprehension offers a shorter syntax when you want to create a new list based on the values of an existing list.

Without list comprehension you will have to write a for statement with a conditional test inside.


Example:

squ = [1, 8, 27, 65, 125]
squ1 = []

# Using a traditional for loop
for s in squ:
    squ1.append(s**2)

print(squ1)

# Squaring an array of elements using list comprehension
squ2 =[s**2 for s in squ]

print(squ2)

Tuple


  • A tuple is a collection which is ordered and unchangeable. In Python tuples are written with round brackets.
  • You can access tuple items by referring to the index number, inside square brackets.
  • Once a tuple is created, you cannot change its values. Tuples are unchangeable.
  • You can loop through the tuple items by using a for loop.
  • To determine if a specified item is present in a tuple use the in keyword.
  • To determine how many items a tuple has, use the len() method.
  • Tuples are unchangeable, so you cannot remove items from it, but you can delete the tuple completely.
  • It is also possible to use the tuple() constructor to make a tuple


Example:

flowers=('orchids', 'roses', 'lilacs')

print(flowers[0])

print('size of the array is :', len(flowers))

for fl in flowers:
    print(fl)

if 'roses' in flowers:
    print('The flower exists')
else:
    print('The flower doesn\'t exists')

# deletes the array
del flowers


Output:


orchids

size of the array is : 3

orchids

roses

lilacs

The flower exists




Sets


Set in Python is a data structure equivalent to sets in mathematics. It may consist of various elements; the order of elements in a set is undefined. 


You can add and delete elements of a set, you can iterate the elements of the set, you can perform standard operations on sets (union, intersection, difference). Besides that, you can check if an element belongs to a set.


Unlike arrays, where the elements are stored as ordered list, the order of elements in a set is undefined (moreover, the set elements are usually not stored in order of appearance in the set; this allows checking if an element belongs to a set faster than just going through all the elements of the set).


Any immutable data type can be an element of a set: a number, a string, a tuple. 


Mutable (changeable) data types cannot be elements of the set. In particular, list cannot be an element of a set (but tuple can), and another set cannot be an element of a set. 


The requirement of immutability follows from the way how do computers represent sets in memory.



Example

a = {'red', 'yellow', 'blue'}
b = {'red', 'orange', 'green'}

# Add an item to a set, using the add() method:
b.add('pink')

# Add multiple items to a set, using the update() 
# method
a.update({'white', 'pink'})

# Sets are unordered. The items have no index.
for colour in a:
    print(colour)

# A random element is removed from set A
a.pop()



# A specific element is removed from set B
b.remove('orange')


# In order to make a subset, we perform an 
# intersection update
a.intersection_update(b)
print(a)
print(a.issubset(b))

Output:


yellow

red

pink

white

blue

{'pink', 'red'}

True




Dictionary


A dictionary is a data type similar to arrays, but works with keys and values instead of indexes. 


Each value stored in a dictionary can be accessed using a key, which is any type of object (a string, a number, a list, etc.) instead of using its index to address it.


Example:

bike = {'brand': 'norton',
             'model': 'Dominator',
             'year': 1961
            }

#This loop prints the key and value
for b in bike:
    print(b, " ", bike[b])

#We use a key to access the model name
print(bike['model'])

#removes the key and value from the dictionary
bike.pop('year')

print(bike)

Output:


brand   norton

model   Dominator

year   1961

Dominator

{'brand': 'norton', 'model': 'Dominator'}


Example 2:

computer = {
    "models": {
        "cpu1": {
            "processor": "Core i7 12th Gen",
            "Memory": ["16GB", "32GB"],
            "Storage": {"500GB", "1TB"}
        },
        "cpu2": {
            "processor": "Core i5 12th Gen",
            "Memory": ["8GB", "16GB"],
            "Storage": {"256GB", "512GB"}
        }

    }
}

# Print all the elements in an array
for c in computer:
    print(c, computer[c])

print()
# print both models
for c in computer["models"]:
    print(c, computer["models"][c])

print()
# print elements for a particular model
for c in computer["models"]["cpu2"]:
    print(c, ":", computer["models"]["cpu2"][c])

Functions


A function is a block of code that takes in some data and, either performs some kind of transformation and returns the transformed data, or performs some task on the data, or both.


Functions are useful because they provide a high degree of modularity. Similar code can be easily grouped into functions and you can provide a name to the function that describes what the function is for. 


Functions are the simplest, and, sometimes the most useful, tool for writing modular code.


Syntax:

def name_of_the_function(<arguments>):
    body of the function
    return <value>


Example:

def add(a, b):
    return a + b


def factorial(a):
    if a == 1:
        return 1
    else:
        return a * factorial(a - 1)


addition = add(2, 5)
print(addition)
fact = factorial(7)
print(fact)


Example 2:

# You can define default argument values
def food(order="Cheese burger"):
    print("You ordered a ",order)

# this function takes in a tuple of arguments 
def items(*items):
    for i in items:
        print(i)

# this function takes in a dictionary of arguments
def options(**op):
    for o in op:
        print(o," : ",op[o])


food()

food("Hamburger")

items("bread","milk","eggs")

options(variant="deluxe",color="blue")