Python is an interpreted, high-level, general-purpose programming language. Created by Guido van Rossum and first released in 1991, Python's design philosophy emphasizes code readability with its notable use of significant whitespace
Whitespace is significant in Python. Where other languages may use {} or (), Python uses indentation to denote code blocks.
There are three options available to install python on your machine
import this
In general, it is a good idea to write comments while you are writing or updating a program as it is easy to forget your thought process later on, and comments written later may be less useful in the long term.
#
is used for single line comments
""" """
or ''' '''
is used for multi line comments# It is a single line comment
"""
It
is
multi-line
comment
"""
a = 20
#Get all keywords in python
import keyword
print(f"Total Number of keywords in Python: {len(keyword.kwlist)}\n\n")
print(keyword.kwlist)
Identifier is the name given to entities like class
, functions
, variables
etc. in Python. It helps differentiating one entity from another.
# Instructions that a Python interpreter can execute are called **statements**.
total = 2 # single line statement
new_total = 1 + 2 + 3 + \
4 + 5 + 6 + \
7 + 8 + 9 # Multiline statement
extra = (1 + 2 + 3 +
4 + 5 + 6 +
7 + 8 + 9) # Other way of multiline statement
# Multiple statements in single line
a = 20; b = 30; c = 30
l
(lowercase letter el), O
(uppercase letter oh) and I
(uppercase letter eye) as they can be confused with 1 and 0name = "Pyton"
ver = 3.6
name2 = "Python 3"
legacy_ver = 2.7
is_legacy_supported = False
cmp_num = 2+3j
name, ver, is_legacy_supported = "Python", 2.7, False
Python uses memory more efficiently.
If two variables have same value then they both point to the same memory location.
Use id()
to get the memory location of the identifier
a = 100
b = 100
print(f"Location of a in memory: {id(a)}")
print(f"Location of b in memory: {id(b)}")
type()
¶type(name)
type(ver)
type(cmp_num)
type(is_legacy_supported)
int
], Floating point numbers [float
], Complex numbers [complex
])bool
] - Either False
or True
str
]a = 10
b = 5.99
c = 7+6j
print(f"{a} is of type {type(a)}")
print(f"{b} is of type {type(b)}")
print(f"{c} is of type {type(c)}")
a = True
b = False
print(f"{a} is of type {type(a)}")
print(f"{b} is of type {type(b)}")
Strings are immutable i.e we cannot do
S[4] = 't'
s = "This is a string"
print(s)
print(f"variable s is a type of {type(s)}")
# Multiline string
s = """This is
multiline string
in Python
"""
print(s)
new_str = "This is python string"
# accessing first character in string using index
new_str[0]
# accessing last character in string using index
new_str[-1]
# slicing [Start:stop: step]
new_str[5:]
new_str[8:-3]
commas
are enclosed within brackets [ ]
.a = [10, 20.5, 1+2j, "Hello", True]
print(a[1]) #print 1st index element
# List is mutable
a[1] = 19.99
a
a = (10, 20.5, 1+2j, "Hello", True)
print(a[1]) #print 1st index element
{ }
.Since set is unordered we cannot access elements using indices like list/tuple/string
a = {10, 30, 20, 40, 8}
print(a)
{}
with each item being a pair in the form key:value
.d = {'a': "apple", 'b': "bat", 'c': 'cat'}
print(d['a'])
int(99.99)
float(25)
str(20)
a = [1, 2, 3, 2]
print(type(a)) #type of a is list
s = set(a) #convert list to set using set() method
print(type(s))
list("Python")
Operators are special symbols in Python that carry out arithmetic or logical computation. The value that the operator operates on is called the operand.
+
, -
, *
, /
, %
, //
, **
are arithmetic operators
x, y = 25, 7
#addition
print(f"Addition of {x} and {y}: {x + y}")
#subtraction(-)
print(f"Subtraction of {x} and {y}: {x - y}")
#multiplication(*)
print(f"Multiplication of {x} and {y}: {x * y}")
#division(/)
print(f"Division of {x} and {y}: {x / y}")
#modulo division (%)
print(f"Modulo division (remainder) of {x} and {y}: {x % y}")
#Floor Division (//)
print(f"Floor division (nearest lower integer) of {x} and {y}: {x // y}")
#Exponent (**)
print(f"Exponenet of {x} and {y}: {x ** y}")
5//2
>
, <
, ==
, !=
, >=
, <=
are comparision operators
a, b = 25, 7
#check a is less than b
print(f"{a} less than {b} : {a < b}")
#check a is greater than b
print(f"Is {a} greater than {b} : {a > b}")
#check a is equal to b
print(f"Is {a} equal to {b} : {a == b}")
#check a is not equal to b (!=)
print(f"Is {a} not equal to {b} : {a != b}")
#check a greater than or equal to b
print(f"Is {a} greater than or equal to {b} : {a >= b}")
#check a less than or equal to b
print(f"Is {a} less than or equal to {b} : {a <= b}")
and
, or
, not
operators.a, b = True, False
#print a and b
print(f"{a} and {b} is {a and b}")
#print a or b
print(f"{a} or {b} is {a and b}")
#print not b
print(f"not {b} is {not b}")
print(f"not {a} is {not a}")
a, b = 10, 4
#Bitwise AND
print(f"{a} & (bitwise AND) {b} is {a & b}")
#Bitwise OR
print(f"{a} | (bitwise OR) {b} is {a | b}")
#Bitwise NOT
print(f"~ (bitwise NOT) {a} is {~ a}")
print(f"~ (bitwise NOT) {b} is {~ b}")
#Bitwise XOR
print(f"{a} ^ (bitwise XOR) {b} is {a ^ b}")
#Bitwise rightshift
print(f"{a} >> (bitwise RIGHTSHIFT) {b} is {a >> b}")
#Bitwise Leftshift
print(f"{a} << (bitwise LEFTSHIFT) {b} is {a << b}")
a = 5
is a simple assignment operator that assigns the value 5 on the right to the variable a on the left.=
, +=
, -=
, *=
, /=
, %=
, //=
, **=
, &=
, |=
, ^=
, >>=
, <<=
are Assignment operators
a = 64
print(f"a is {a}")
# add AND (a += 10 is equivalent to a = a + 10)
a += 10
print(f"After Add and Assign 10 to a: {a}")
#subtract AND (-=)
a -= 10
print(f"After Subtract and Assign 10 to a: {a}")
#Multiply AND (*=)
a *= 10
print(f"After Multiply and Assign 10 to a: {a}")
#Divide AND (/=)
a /= 10
print(f"After Divide and Assign 10 to a: {a}")
#Modulus AND (%=)
a %= 10
print(f"After Modulus and Assign 10 to a: {a}")
#Exponent AND (**=)
a **= 10
print(f"After Exponent and Assign 10 to a: {a}")
#Floor Division (//=)
a //= 10
print(f"After Floor Divsion and Assign 10 to a: {a}")
is
and is not
are the identity operators in Python.
They are used to check if two values (or variables) are located on the same part of the memory.
a = 5
b = 5
#5 is object created once both a and b points to same object
print(f"A is B: {a is b}")
print(f"A is not B: {a is not b}")
s1 = "Python"
s2 = "Python"
print(f"S1 is S2: {s1 is s2}")
print(f"S1 is not S2: {s1 is not s2}")
s1 = "Python"
s2 = "Java"
print(f"S1 is S2: {s1 is s2}")
print(f"S1 is not S2: {s1 is not s2}")
in
and not in
are the membership operators in Python.
They are used to test whether a value or variable is found in a sequence (string, list, tuple, set and dictionary).
lst = [1, 2, 3, 4]
print(f"List is {lst}")
#check 1 is present in a given list or not
print(f"check 1 is present in a given list or not {1 in lst}")
#check 5 is present in a given list
print(f"check 5 is present in a given list or not {5 in lst}")
d = {1: "a", 2: "b"}
print(1 in d)
# syntax
if test_expression:
code
Python interprets non-zero values as
True
. None and 0 are interpreted asFalse
.
num = 10
# try 0, -1 and None
if num:
print("Number is positive")
print("This will print always") #This print statement always print
#NOTE::: Experiment by changing number
# syntax
if test_expression:
code of if
else:
code of else
num = 10
# try 0, -1 and None
if num:
print("Number is positive")
else:
print("Number is negative")
print("This will print always") #This print statement always print
#NOTE::: Experiment by changing number
# syntax
if test_expression:
code
elif test_expression2:
code
else:
code
num = 0
# try 0, -1 and None
if num > 0:
print("Number is positive")
elif num == 0:
print("Number is Zero")
else:
print("Number is negative")
print("This will print always") #This print statement always print
#NOTE::: Experiment by changing number
num = 10.5
if num >= 0:
if num == 0:
print("Zero")
else:
print("Positive number")
else:
print("Negative Number")
# FIND THE LARGEST AMONG THREE NUMBERS
num1 = 10
num2 = 50
num3 = 15
if (num1 >= num2) and (num1 >= num3): #logical operator and
largest = num1
elif (num2 >= num1) and (num2 >= num3):
largest = num2
else:
largest = num3
print(f"Largest element among three numbers is: {largest}")
# Syntax
while test_expression:
code
#Find product of all numbers present in a list
lst = [10, 20, 30, 40, 60] # 10*20*30*40*60 = 14400000
product = 1
index = 0
while index < len(lst):
product *= lst[index]
index += 1
print(f"Product is: {product}")
numbers = [1, 2, 3,4,5]
#iterating over the list
index = 0
while index < len(numbers):
print(numbers[index])
index += 1
else:
print("no item left in the list")
# To check whether given number is prime or not
num = int(input("Enter a number: ")) #convert string to int
isDivisible = False;
i=2;
while i < num:
if num % i == 0:
isDivisible = True;
print (f"{num} is divisible by {i}")
i += 1;
if isDivisible:
print(f"{num} is NOT a Prime number")
else:
print(f"{num} is a Prime number")
# syntax
for element in sequence :
code
#Find product of all numbers present in a list
lst = [10, 20, 30, 40, 60]
product = 1
#iterating over the list
for el in lst:
product *= el
print(f"Product is: {product}")
range()
¶range()
function.range(10)
will generate numbers from 0 to 9 (10 numbers).start
, stop
, step size
and generates the next number on the go.#print range of 10
for i in range(10):
print(i, end="\t")
for i in range(0, 20, 2):
print(i)
lst = ["python", "java", "go", "rust", "typescript", "c++"]
#iterate over the list using index
#for index in range(len(lst)):
# print(lst[index])
for el in lst:
print(el)
numbers = [1, 2, 3]
#iterating over the list
for item in numbers:
print(item)
else:
print("no item left in the list")
# Display all the prime numbers in a range
index1 = 20
index2 = 50
print(f"Prime numbers between {index1} and {index2} are :", end=" ")
for num in range(index1, index2+1): #default step size is 1
if num > 1:
isDivisible = False
for index in range(2, num):
if num % index == 0:
isDivisible = True
if not isDivisible:
print(num, end="\t")
numbers = [1, 2, 3, 4, 5, 6]
for num in numbers: #iterating over list
if num == 4:
break
print(num)
else:
print("in the else-block")
print("Outside of for loop")
# check given number is Prime number or not (using break)
num = int(input("Enter a number: ")) #convert string to int
isDivisible = False;
i=2;
while i < num:
if num % i == 0:
isDivisible = True;
print (f"{num} is divisible by {i}")
break; # this line is the only addition.
i += 1;
if isDivisible:
print(f"{num} is NOT a Prime number")
else:
print(f"{num} is a Prime number")
#print odd numbers present in a list
numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
continue
print(num)
else:
print("else-block")
A data structure is a collection of data elements (such as numbers or characters—or even other data structures) that is structured in some way, for example, by numbering the elements. The most basic data structure in Python is the "sequence".
[ ]
empty_list = list()
empty_list_2 = []
lst = ['one', 'two', 'three', 'four'] # list of strings
lst2 = [1, 2, 3, 4] #list of integers
lst3 = [[1, 2], [3, 4]] # list of lists
lst4 = [1, 'python', 24, 1.24] # list of different datatypes
print(lst4)
len()
function returns the length of the listlst = ['one', 'two', 'three', 'four']
print(len(lst))
append()
is used to add elements at the end of the listextend()
is used to join two lists+
to extend the listlst.append('five')
print(lst)
l1 = ["one", "two", "three"]
l2 = ["four", "five", "six"]
l1.append(l2)
print(l1)
l1 = ["one", "two", "three"]
l2 = ["four", "five", "six"]
l1.extend(l2)
print(l1)
l1 = ["one", "two", "three"]
l2 = ["four", "five", "six"]
l3 = l1 + l2
print(l3)
insert()
method is used to insert element at specified locationlst.insert(0, "Zero")
lst.insert(3, 4)
print(lst)
remove()
method removes the first occurence of the given element from the listdel
delete the element at specified index. If didn't specify any index it deletes the whole list from memory then you're not able to access it.pop()
Pop removes and returns the element at specified location in a listlst1 = [1,2,3,4,3,3]
lst1.remove(3)
print(lst1)
lst1.pop(4)
print(lst1)
del lst1[1]
print(lst1)
del lst1
reverse()
method reverses the list itemslst = ['one', 'two', 'three', 'four', 'five']
lst.reverse()
print(lst)
sorted()
function returns the sorted list.sort()
method sorts the list inplace.nums = [8, 9, 5, 4 ,7, 2, 6, 3, 1]
sorted_lst = sorted(nums)
print(f"Original list\t {nums}")
print(f"Sorted list\t {nums}")
print(f"Reverse Sorted list\t {sorted(nums, reverse=True)}")
nums.sort()
print(f"Sorted list\t {nums}")
lst = [1, 2, 3, 4, 5]
abc = lst
abc.append(6)
# original list also got appended 6
print("Original list: ", lst)
s = "This is python notes"
s_lst = s.split()
print(s_lst)
lst = [1, 2, 3, 4]
print(lst[1]) #print second element
# -ve indexing starts from end
print(lst[-2])
[start: end: step]
start
is inclusiveend
is exclusivestep
default to 1numbers = [10, 20, 30, 40, 50,60,70,80]
#print all numbers
print(numbers[:])
#print from index 0 to index 3
print(numbers[0:4])
#print alternate elements in a list
print(numbers[::2])
#print elemnts start from 0 through rest of the list
print(numbers[2::2])
numbers = [1, 2, 3, 1, 3, 4, 1, 2, 1, 5]
#frequency of 1 in a list
print(f"Frequency of 1: {numbers.count(1)}")
#frequency of 3 in a list
print(f"Frequency of 3: {numbers.count(3)}")
lst = ['one', 'two', 'three', 'four', 'five']
for ele in lst:
print(ele)
List comprehensions provide a concise way to create lists.
Common applications are to make new lists where each element is the result of some operations applied to each member of another sequence or iterable, or to create a subsequence of those elements that satisfy a certain condition.
# without list comprehension
squares = []
for i in range(10):
squares.append(i**2) #list append
print(squares)
#using list comprehension
squares = [i**2 for i in range(10)]
print(squares)
lst = [-10, -20, 10, 20, 50]
#create a new list with values doubled
new_lst = [i*2 for i in lst]
print(new_lst)
#filter the list to exclude negative numbers
new_lst = [i for i in lst if i >= 0]
print(new_lst)
#create a list of tuples like (number, square_of_number)
new_lst = [(i, i**2) for i in range(10)]
print(new_lst)
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
]
#transpose of a matrix without list comprehension
transposed = []
for i in range(4):
lst = []
for row in matrix:
lst.append(row[i])
transposed.append(lst)
print(transposed)
#with list comprehension
transposed = [[row[i] for row in matrix] for i in range(4)]
print(transposed)
#empty tuple
t = ()
t = tuple()
#tuple having integers
t = (1, 2, 3)
print(t)
#tuple with mixed datatypes
t = (1, 'delta', 28, 'omega')
print(t)
#nested tuple
t = (1, (2, 3, 4), [1, 'alpha', 28, 'omega'])
print(t)
#only parenthesis is not enough
t = ('python')
type(t)
#need a comma at the end
t = ('python',)
type(t)
#parenthesis is optional only if it has one element
t = "python",
print(type(t))
print(t)
t = ("Python", "Java", "C++", "Go", "TypeScript")
print(t[0])
print(t[-1])
print(t[2])
t = (1, 2, 3, 4, 5, 6)
print(t[1:4])
#print elements from starting to 2nd last elements
print(t[:-2])
#print elements from starting to end
print(t[:])
t = (1, 2, 3, 4, [5, 6, 7])
t[4][1] = 'Python'
print(t)
t = (1, 2, 3) + (4, 5, 6)
print(t)
t = (('Python', ) * 4)
print(t)
del
is used to delete the tuple#delete entire tuple using del keyword
t = (1, 2, 3, 4, 5, 6)
del t
count()
method returns the frequency of the given element numbers = (1, 2, 3, 1, 3, 4, 1, 2, 1, 5)
#frequency of 1 in a tuple
print(f"Frequency of 1: {numbers.count(1)}")
#frequency of 3 in a tuple
print(f"Frequency of 3: {numbers.count(3)}")
index()
method returns the index of first elements that is equal to the specified valuet = (1, 2, 3, 1, 3, 3, 4, 1)
print(t.index(3))
t = (1,2,3,4,5,6,7,8,9)
print(1 in t)
print(0 in t)
len()
function returns the length of tuplet = (1,2,3,4,5,6,7,8)
print(len(t))
sorted()
function is returns the sorted listt = (2,1,3,5,8,6,7,4)
sorted_t = sorted(t)
print(f"Original tuple:\t {t}")
print(f"Sported list:\t {sorted_t}")
{}
empty curly bases represnt the dictionary not set.s = set()
s = {1,2,3}
s = set([1,2,3,2,1,2,2,3,4,5])
print(s)
add()
method to add the single element to setupdate()
method to add multiple elements to sets = {1,3,4}
s.add(2)
print(s)
s.update([5,6,7,2,3])
print(s)
s.update([8,9], {0,1,2})
print(s)
discard()
method removes the specified itemremove()
method removes the specified item. It throws error if the specified item is not present in setpop()
method removes random element from setclear()
method removes all the items in a sets = {1,2,3,4,5,6}
print(s)
s.discard(5)
print(s)
s.remove(2)
print(s)
s.pop()
print(s)
s = {1, 2, 3, 4, 5}
s.clear()
print(s)
|
or union()
methodset1 = {1, 2, 3, 4, 5}
set2 = {3, 4, 5, 6, 7}
print(set1 | set2)
print(set1.union(set2))
&
or intersection()
methodprint(set1 & set2)
print(set1.intersection(set2))
-
or difference()
methodprint(set1 - set2)
print(set1.difference(set2))
^
or symmetric_difference()
methodprint(set1 ^ set2)
print(set1.symmetric_difference(set2))
issubset()
method#find issubset()
x = {"a","b","c","d","e"}
y = {"c","d"}
#check x is subset of y
print(f"set 'x' is subset of 'y' ? {x.issubset(y)}")
#check y is subset of x
print(f"set 'y' is subset of 'x' ? { y.issubset(x)}")
Frozen sets has the characteristics of sets, but we can't be changed once it's assigned. While tuple are immutable lists, frozen sets are immutable sets
Frozensets can be created using the function frozenset()
Sets being mutable are unhashable, so they can't be used as dictionary keys. On the other hand, frozensets are hashable and can be used as keys to a dictionary.
This datatype supports methods like copy()
, difference()
, intersection()
, isdisjoint()
, issubset()
, issuperset()
, symmetric_difference()
and union()
. Being immutable it does not have method that add or remove elements.
set1 = frozenset([1, 2, 3, 4])
set2 = frozenset([3, 4, 5, 6])
print(f"Union: {set1 | set2}")
print(f"Intersection: {set1 & set2}")
print(f"Symmetric difference: {set1 ^ set2}")
Python dictionary is an unordered collection of items. While other compound data types have only value as an element, a dictionary has a key: value
pair.
#empty dictionary
my_dict = {}
my_dict = dict()
#dictionary with integer keys
my_dict = {1: 'abc', 2: 'xyz'}
print(my_dict)
#dictionary with mixed keys
my_dict = {'name': 'satish', 1: ['abc', 'xyz']}
print(my_dict)
#create empty dictionary using dict()
my_dict = dict()
my_dict = dict([(1, 'abc'), (2, 'xyz')]) #create a dict with list of tuples
print(my_dict)
my_dict = {'name': 'Python', 'version': 3.8, 'address': 'python.org'}
#get name
print(my_dict['name'])
print(my_dict.get('address'))
print(my_dict['version'])
my_dict = {'name': 'Python', 'age': 29, 'address': 'python.org'}
print(my_dict)
my_dict['name'] = 'Python 3'
my_dict['Version'] = 3.8
print(my_dict)
pop()
method removes the specified item popitem()
method removes the random itemclear()
removes all the itemsdel
removes the specified item. if not specified it removes the variable from memorymy_dict = {'name': 'Python', 'version': 3.8, 'address': 'python.org'}
my_dict.pop('version')
print(my_dict)
my_dict = {'name': 'Python', 'version': 3.8, 'address': 'python.org'}
my_dict.popitem()
print(my_dict)
squares = {2: 4, 3: 9, 4: 16, 5: 25}
#delete particular key
del squares[2]
print(squares)
#remove all items
squares.clear()
print(squares)
squares = {2: 4, 3: 9, 4: 16, 5: 25}
#delete dictionary itself
del squares
# print(squares) #NameError because dict is deleted
squares = {2: 4, 3: 9, 4: 16, 5: 25}
my_dict = squares.copy()
print(my_dict)
fromkeys[seq[, v]]
Return a new dictionary with keys from seq and value equal to v (defaults to None).subjects = {}.fromkeys(['Math', 'Science', 'Social'], 0)
print(subjects)
keys()
method returns all the keys in a dictvalues()
method returns all the values in a dictitems()
method returns all the key value pairs in a dictsquares = {2:4, 3:9, 4:16, 5:25}
print(squares.items())
squares = {2:4, 3:9, 4:16, 5:25}
print(squares.keys())
squares = {2:4, 3:9, 4:16, 5:25}
print(squares.values())
d = {'a': 1, 'b': 2, 'c': 3}
for pair in d.items():
print(pair)
#Creating a new dictionary with only pairs where the value is larger than 2
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
new_dict = {k:v for k, v in d.items() if v > 2}
print(new_dict)
d = {'a':1,'b':2,'c':3,'d':4,'e':5}
d = {k + 'c':v * 2 for k, v in d.items() if v > 2}
print(d)
my_string = 'Hello'
print(my_string)
my_string = "Hello"
print(my_string)
my_string = '''Hello'''
print(my_string)
Index starts from 0.
my_string = "Hello"
#print first Character
print(my_string[0])
#print last character using negative indexing
print(my_string[-1])
#slicing 2nd to 5th character
print(my_string[2:5])
del
deletes the complete string
my_string = "Hello"
del my_string
+
operator does this in Python. Simply writing two string literals together also concatenates them.*
operator can be used to repeat the string for a given number of times.s1 = "Hello "
s2 = "Oliver"
#concatenation of 2 strings
print(s1 + s2)
#repeat string n times
print(s1 * 3)
count = 0
for l in "Hello World":
if l == 'o':
count += 1
print(count, ' letters found')
in
operator to test membershipprint('l' in 'Hello World')
lower()
, upper()
, join()
, split()
, find()
, replace()
etc"Hello".lower()
"Hello".upper()
"hello".capitalize()
x = "This will split all words in a list".split()
print(x)
' '.join(x)
"Good Morning".find("Mo")
s1 = "Bad morning"
s2 = s1.replace("Bad", "Good")
print(s1)
print(s2)
### Palindrome program
myStr = "Madam"
#convert entire string to either lower or upper
myStr = myStr.lower()
#reverse string
revStr = reversed(myStr)
#check if the string is equal to its reverse
if list(myStr) == list(revStr):
print("Given String is palindrome")
else:
print("Given String is not palindrome")
### Sort words in Alphabetic order
myStr = "python Program to Sort words in Alphabetic Order"
#breakdown the string into list of words
words = myStr.split()
#sort the list
words.sort()
#print Sorted words are
for word in words:
print(word)
Function is a group of related statements that perform a specific task.
Functions help break our program into smaller and modular chunks. As our program grows larger and larger, functions make it more organized and manageable.
It avoids repetition and makes code reusable.
def function_name(parameters):
"""
Doc String
"""
Statement(s)
keyword def
marks the start of function header
Parameters (arguments) through which we pass values to a function. These are optional
A colon(:) to mark the end of funciton header
Doc string describe what the function does. This is optional
return
statement to return a value from the function. This is optional
# Function definition
def print_name(name):
"""
This function prints the name
"""
print("Hello " + str(name))
# function call
print_name("Python")
print(print_name.__doc__) # print doc string of the function
# Function defintion
def get_sum(lst):
"""
This function returns the sum of all the elements in a list
"""
#initialize sum
_sum = 0
#iterating over the list
for num in lst:
_sum += num
return _sum
# function call
s = get_sum([1,2,3,4,5,6,7])
print(f"Sum of given list is{s}")
print(get_sum.__doc__)
def compute_HCF(a, b):
"""
Computing HCF of two numbers
"""
smaller = b if a > b else a #consice way of writing if else statement
hcf = 1
for i in range(1, smaller+1):
if (a % i == 0) and (b % i == 0):
hcf = i
return hcf
num1 = 6
num2 = 36
print(f"H.C.F of {num1} and {num2} is: {compute_HCF(num1, num2)}")
print()
, abs()
, filter()
, divmod()
, type()
, dir()
etc.# one more example
def product_numbers(a, b):
"""
this function returns the product of two numbers
"""
product = a * b
return product
num1 = 10
num2 = 20
print (f"product of {num1} and {num2} is {product_numbers(num1, num2)}")
Arguments should be in the above defined order while defining a function
# positional argument example
def greet(name, msg):
"""
This function greets to person with the provided message
"""
print("Hello {0} , {1}".format(name, msg))
greet("Dave", "Good Morning")
# Default argument example
def greet(name, msg="Good Morning"):
"""
This function greets to person with the provided message
"""
print("Hello {0} , {1}".format(name, msg))
greet("Dave")
greet("Dave", "How are you?")
def greet(*names):
"""
This function greets all persons in the names tuple
"""
# print(names)
for name in names:
print(f"Hello, {name}.")
greet("Adya", "Aditi", "Ananya", "Ankit", "Sonal")
# print factorial of a number using recurion
def factorial(num):
"""
This is a recursive function to find the factorial of a given number
"""
return 1 if num == 1 else (num * factorial(num-1))
num = 5
print(f"Factorial of {num} is {factorial(num)}")
def fibonacci(num):
"""
Recursive function to print fibonacci sequence
"""
return num if num <= 1 else fibonacci(num-1) + fibonacci(num-2)
nterms = 10
print("Fibonacci sequence")
for num in range(nterms):
print(fibonacci(num), end="\t")
# def double(x):
# return x*2
# The above commented function rewrite as a lambda functoin
double = lambda x: x *2
print(double(6))
lst = [1, 2, 3, 4, 5]
even_lst = list(filter(lambda x: (x%2 == 0), lst))
print(even_lst)
from functools import reduce
lst = [1, 2, 3, 4, 5]
product_lst = reduce(lambda x, y: x*y, lst)
print(product_lst)
import
keyword.
operation.import math
print(f"The value of PI: {math.pi:.3f}")
print(f"The value of e: {math.e:.3f}")
import datetime as dt
dt.datetime.now()
# we can import specific names without importing everything
from math import pi, e
print(f"The value of PI: {pi:.3f}")
print(f"The value of e: {e:.3f}")
dir()
function¶We can use the dir()
function to find out names that are defined inside a module.
# functions in datetime module
dir(dt)
# from the above package structure
import Game.Level.start
Python has a built-in function open()
to open a file. This function returns a file object, also called a handle, as it is used to read or modify the file accordingly.
We can specify the mode while opening a file. In mode, we specify whether we want to read 'r', write 'w' or append 'a' to the file. We also specify if we want to open the file in text mode or binary mode.
Mode | Mode Description |
---|---|
'r' |
Open a file for reading. (default) |
'w' |
Open a file for writing. Creates a new file if it does not exist or truncates the file if it exists. |
'x' |
Open a file for exclusive creation. If the file already exists, the operation fails. |
'a' |
Open for appending at the end of the file without truncating it. Creates a new file if it does not exist. |
't' |
Open in text mode. (default) |
'b' |
Open in binary mode. |
'+' |
Open a file for updating (reading and writing) |
close()
method.But more often everyone we forget to close the file. So, the community recommends to use
with
# writing to a file
with open("test.txt",'w', encoding='utf-8') as f:
f.write("We are writing this file from Python\n")
f.write("Open the file using with statement\n")
f.write("The good thing about with is it automatically closes when the block inside with is exited.\n")
# reading from a file
with open('test.txt', 'r', encoding='utf-8') as f:
# Read the whole file from the cursor position
s = f.read()
# moving cursor to the initial position
f.seek(0)
# reading line by line
print(f.readline())
print(s)
When writing a program, we, more often than not, will encounter errors. Error caused by not following the proper structure (syntax) of the language is called syntax error or parsing error.
Errors can also occur at runtime and these are called exceptions.
They occur, for example, when a file we try to open does not exist (FileNotFoundError), dividing a number by zero (ZeroDivisionError), module we try to import is not found (ImportError) etc.
Whenever these type of runtime error occur, Python creates an exception object. If not handled properly, it prints a traceback to that error along with some details about why that error occurred and terminates program.
Python has many built-in exceptions which forces your program to output an error when something in it goes wrong.
When these exceptions occur, it causes the current process to stop and passes it to the calling process until it is handled. If not handled, our program will crash.
For example, if function A calls function B which in turn calls function C and an exception occurs in function C. If it is not handled in C, the exception passes to B and then to A. If never handled, an error message is spit out and our program come to a sudden unexpected halt.
raise
allows you to throw an exception at any time.assert
enables you to verify if a certain condition is met and throw an exception if it isn’t.try
clause, all statements are executed until an exception is encountered.except
is used to catch and handle the exception(s) that are encountered in the try clause.else
lets you code sections that should run only when no exceptions are encountered in the try clause.finally
enables you to execute sections of code that should always run, with or without any previously encountered exceptions.import sys
lst = ['b', 0, 2]
for entry in lst:
try:
print("The entry is", entry)
r = 1 / int(entry)
except:
print("Oops!", sys.exc_info()[0],"occured.")
print("Next entry.")
print("***************************")
print(f"The reciprocal of {entry} is {r}")
# catching specific exception
lst = ['b', 0, 2]
for entry in lst:
try:
print("****************************")
print("The entry is", entry)
r = 1 / int(entry)
except(ValueError):
print("This is a ValueError.")
except(ZeroDivisionError):
print("This is a ZeroError.")
except:
print("Some other error")
print("The reciprocal of", entry, "is", r)
# Raise exception
try:
num = int(input("Enter a positive integer:"))
if num <= 0:
raise ValueError("Error:Entered negative number")
except ValueError as e:
print(e)
try:
f = open('test.txt')
finally:
f.close()
Everything in Python is an Object
x = 1
help(x)
dir(x)
Object : It is an instance of class. Objects combine functions with data ex: List
Class is the blue print of an object. Which contains attributes and methods
User defined objects are created using the class
keyword. The class is a blueprint that defines the nature of a future object. From classes we can construct instances. An instance is a specific object created from a particular class. For example, above we created the object x
which was an instance of a int
object.
class Patient:
"""Medical centre patient"""
pass
x = Patient()
Methods are functions defined inside the body of a class. They are used to perform operations with the attributes of our objects. Methods are a key concept of the OOP paradigm. They are essential to dividing responsibilities in programming, especially in large applications.
__init__()
¶self
. Here self
refers to the object
itself.The variable created by the instructor are unique to each instance.
Class wide variables/attributes are same for any instance. In our example status
is class wide attribute
class Patient:
"""
Attribuets
----------
name: Patient Name
age: Patient age
conditions: Existing Medical conditions
"""
status = "patient"
def __init__(self, name, age):
self.name = name
self.age = age
self.conditions = []
def get_details(self):
print(f"Patient record: {self.name}, {self.age} years, Current.Info: {self.conditions if self.conditions else 'nil'}.")
def add_info(self, information):
self.conditions.append(information)
john = Patient("John", 29)
dave = Patient("Dave", 34)
finn = Patient("Finn", 40)
# print(f"{john.name:8} {john.age:3} {john.status}")
# print(f"{dave.name:8} {dave.age:3} {dave.status}")
john.add_info("Treated for Fever - Paracetamol prescribed")
finn.add_info("Symptoms: Fever, Cough, Headache")
finn.add_info("Suggested: 2 days observation")
john.get_details()
finn.get_details()
dave.get_details()
john.status
Inheritance is a way to form new classes using classes that have already been defined. The newly formed classes are called derived classes, the classes that we derive from are called base classes. Important benefits of inheritance are code reuse and reduction of complexity of a program. The derived classes (descendants) override or extend the functionality of base classes (ancestors).
Sometimes it makes sense for a derived class to inherit qualities from two or more base classes. Python allows for this with multiple inheritance.
Things get complicated when you have several base classes and levels of inheritance. This is resolved using Method Resolution Order - a formal plan that Python follows when running object methods.
super()
it refers to the parent class.class Infant(Patient):
"""Patient under 2 years
Attribuets
----------
name: Patient Name
age: Patient age
vaccinations: Vaccinations given
"""
def __init__(self, name, age):
self.vaccinations = []
super().__init__(name, age)
def add_vac(self, vaccine):
self.vaccinations.append(vaccine)
def get_details(self):
s = f"""****************************************************
Patient record: {self.name}, {self.age} years
Patient has had {self.vaccinations if self.vaccinations else None} vaccines
{self.name} IS AN INFANT, HAS HE HAD ALL HIS CHECKS?\n\n"""
print(s)
ted = Infant("Ted", 1)
ted.add_vac("MMR")
ted.get_details()
__repr__
: The “official” string representation of an object. This is how you would make an object of the class. The goal of repr is to be unambiguous.__str__
: The “informal” or nicely printable string representation of an object. This is for the enduser.
etc.class BankAccount:
"""
BANK ACCOUNT
Attributes
----------
balance: Amount left in the account
"""
def __init__(self, balance=0.0):
self.balance = balance
def display_balance(self):
print(f"Your balance is {self.balance}")
def make_deposit(self):
amount = float(input("How much would you like to deposit? $"))
self.balance += amount
print(f"DEPOSIT SUCCESSFUL: Now your balance is: {self.balance}")
def make_withdrawl(self):
amount = float(input("How much would you like to withdraw? $"))
if amount >= self.balance:
print(f"You dont have sufficient funds, Your balance is {self.balance}")
else:
self.balance -= amount
print(f"WITHDRAWL SUCCESSFUL: Now your balance is: {self.balance}")
def __str__(self):
return f"Your balance is {self.balance}"
my_bank = BankAccount(500)
print(my_bank)
my_bank.make_withdrawl()
my_bank.make_deposit()
def new_decorator(func):
def wrap_func():
print("Code would be here, before executing the func")
func()
print("Code here will execute after the func()")
return wrap_func
@new_decorator
def func_needs_decorator():
print("This function is in need of a Decorator")
func_needs_decorator()
def smart_divide(func):
def inner(a,b):
print("I am going to divide",a,"and",b)
if b == 0:
print("Whoops! cannot divide")
return
return func(a,b)
return inner
@smart_divide
def divide(a,b):
return a/b
print(divide(2, 5))
print(divide(2, 0))
def star(func):
def inner(*args, **kwargs):
print("*" * 30)
func(*args, **kwargs)
print("*" * 30)
return inner
def percent(func):
def inner(*args, **kwargs):
print("%" * 30)
func(*args, **kwargs)
print("%" * 30)
return inner
@star
@percent
def printer(msg):
print(msg)
printer("Hello")
@percent
@star
def printer(msg):
print(msg)
printer("Hello")
range()
Each time the yield
statement is executed the function generates a new value.
In most aspects, a generator function will appear very similar to a normal function. The main difference is when a generator function is compiled they become an object that supports an iteration protocol.
def gen_cubes(n):
for num in range(n):
yield num ** 3
for x in gen_cubes(10):
print(x, end="\t")
def integers():
"""Infinite sequence of integers."""
i = 1
while True:
yield i
i = i + 1
def squares():
for i in integers():
yield i * i
def take(n, seq):
"""Returns first n values from the given sequence."""
seq = iter(seq)
result = []
try:
for i in range(n):
result.append(next(seq))
except StopIteration:
pass
return result
print(take(10, squares()))
def simple_gen():
for x in range(3):
yield x
g = simple_gen()
print(next(g))
print(next(g))
print(next(g))
print(next(g))
a = (x*x for x in range(11))
sum(a)