from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
import pandas as pd
import numpy as np
# IPython configuration for enhanced interactivity
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
# Set a seed for reproducibility
np.random.seed(42)
# Create a DataFrame with 5 rows and 5 columns of random integers from 1 to 20
df = pd.DataFrame(np.random.randint(1, 21, size=(5, 5)),
columns=['A', 'B', 'C', 'D', 'E'])
df
A | B | C | D | E | |
---|---|---|---|---|---|
0 | 7 | 20 | 15 | 11 | 8 |
1 | 7 | 19 | 11 | 11 | 4 |
2 | 8 | 3 | 2 | 12 | 6 |
3 | 2 | 1 | 12 | 12 | 17 |
4 | 10 | 16 | 15 | 15 | 19 |
# returns None when no value is specified
def my_fun(a,b):
print(a)
print(b)
aa = my_fun(10, 20)
print(aa) # returns None
10 20 None
def my_fun(a,b):
print(a)
print(b)
return
my_fun(10, 20)
aa = my_fun(10, 20)
print(aa) # returns None
10 20 10 20 None
# function ends when return is encountered
def my_fun(a,b):
print(a)
return 10000
print(b)
my_fun(10, 20)
10
10000
# return multiple values
def my_fun(a,b):
print(a)
print(b)
return 10000, 20000, 30000 # returns a tuple
my_fun(10, 20)
10 20
(10000, 20000, 30000)
def my_fun(a,b):
print(a)
print(b)
return [10000, 20000, 30000]
my_fun(10, 20)
10 20
[10000, 20000, 30000]
complex(3,5)
complex(real=3, imag=5)
complex(imag=3, real=5)
# complex(real = 3, 5) # error: positional argument follows keyword argument
complex(3, imag=5) # allowed
# complex(3, real=5) # error: 2 arguements passed for real parameter
# complex(imag = 3, 5) #error: positional argument follows keyword argument
# Rule: positional first, keyword next
# complex(real= 3, real= 5) # error, obviously
(3+5j)
(3+5j)
(5+3j)
(3+5j)
def fn_mumbai():
print("Im in Mumbai")
fn_bangalore()
def fn_bangalore():
print("Im in Bangalore")
fn_delhi()
def fn_delhi():
print("Im in Delhi")
fn_mumbai()
del fn_mumbai, fn_bangalore, fn_delhi
Im in Mumbai Im in Bangalore Im in Delhi
def factorial(n):
if n==1 or n==0:
return 1
else:
return n*factorial(n-1)
for i in range(5):
print(i, factorial(i))
0 1 1 1 2 2 3 6 4 24
def fibonacci(n):
assert isinstance(n, int)
assert n>=0
if n==0 or n==1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
for i in range(5):
print(i, fibonacci(i))
0 1 1 1 2 2 3 3 4 5
if False:
def fn_mumbai():
def fn_bangalore():
print("Im in Bangalore")
print("Im in Mumbai")
fn_bangalore()
fn_mumbai()
fn_bangalore() # not available outside fn_mumbai()
# function can return another function
def multiplier(n):
def temp(x):
return x*n
return temp
multiplier_2 = multiplier(2)
multiplier_2(10)
multiplier_3 = multiplier(3)
multiplier_3(10)
20
30
def my_fun(x, y):
print(x)
my_fun(10, 20) # works
if False:
my_fun(10) # fails
10
def my_fun(x, y= 1000):
print(x)
print(y)
my_fun(10, 20) # works
my_fun(10) # works too, uses default
10 20 10 1000
# block 1
def f1(a,b):
print(dir())
print(a)
print(b)
a = 10
b = 20
[x for x in dir() if not x.startswith("_")]
print(a)
print(b)
f1(a=100, b=200)
print(a)
print(b)
['In', 'InteractiveShell', 'Out', 'a', 'aa', 'b', 'df', 'e1', 'e2', 'emp_1', 'emp_2', 'employee', 'exit', 'f1', 'factorial', 'fibonacci', 'get_ipython', 'i', 'math', 'multiplier', 'multiplier_2', 'multiplier_3', 'my_fun', 'np', 'open', 'pd', 'quit', 'x']
10 20 ['a', 'b'] 100 200 10 20
# block 2 - local variable, local values
def f1(a,b):
print(dir())
print(a)
print(b)
x = 999
print(x)
x = 100
f1(a = 10, b=20)
print(x)
['a', 'b'] 10 20 999 100
# block 3 - if a variable is absent in function, look one level above
def f1(a,b):
print(dir())
print(a)
print(b)
print(x)
x = 100
f1(a = 10, b=20)
print(x)
['a', 'b'] 10 20 100 100
apply()
¶# function by column
df.apply(np.sum, axis=0) # axis = 0 is the default
# function by row
df.apply(np.sum, axis=1) # axis = 0 is the default
A 34 B 59 C 55 D 61 E 54 dtype: int64
0 61 1 52 2 31 3 44 4 75 dtype: int64
map()
¶df
A | B | C | D | E | |
---|---|---|---|---|---|
0 | 7 | 20 | 15 | 11 | 8 |
1 | 7 | 19 | 11 | 11 | 4 |
2 | 8 | 3 | 2 | 12 | 6 |
3 | 2 | 1 | 12 | 12 | 17 |
4 | 10 | 16 | 15 | 15 | 19 |
# error, works only on series
# df.map(lambda x: x + 1000)
df['A'].map(lambda x: x + 1000)
# df[0].map(lambda x: x + 1000) # error
0 1007 1 1007 2 1008 3 1002 4 1010 Name: A, dtype: int64
df.applymap(lambda x: x + 1000)
A | B | C | D | E | |
---|---|---|---|---|---|
0 | 1007 | 1020 | 1015 | 1011 | 1008 |
1 | 1007 | 1019 | 1011 | 1011 | 1004 |
2 | 1008 | 1003 | 1002 | 1012 | 1006 |
3 | 1002 | 1001 | 1012 | 1012 | 1017 |
4 | 1010 | 1016 | 1015 | 1015 | 1019 |
# df.apply(lambda row: row, axis = 0)
# df.apply(lambda row: row, axis = 1)
df.apply(lambda row: row['A'] + row['B'], axis = 1)
0 27 1 26 2 11 3 3 4 26 dtype: int64
Lambda
function¶my_fun = lambda a : a + 10
my_fun(5)
15
Map
¶list(map(lambda a : a + 10, [1,2,3,4,5]))
my_fun = lambda a : a + 10
list(map(my_fun , [1,2,3,4,5]))
[11, 12, 13, 14, 15]
[11, 12, 13, 14, 15]
class employee:
pass
emp_1 = employee()
emp_2 = employee()
print(emp_1)
emp_1.name = "ash red"
emp_1.email= "ashred@gmail.com"
print(emp_1)
print(emp_1.name)
print(emp_1.email)
<__main__.employee object at 0x14d650c90> <__main__.employee object at 0x14d650c90> ash red ashred@gmail.com
class employee:
def __init__(self, name, pay):
self.name = name
self.pay = pay
self.email = name + "@gmail.com"
def print_name(self): # this is a method
print(self.name)
def apply_new_year_bonus(self, bonus = 10):
self.pay = self.pay + bonus
e1 = employee("abc def", 100) # e1 will be passed as self
e1
e1.name
e1.email # not brackets as email is an attribute of the class
e1.print_name() # need brackets since, print_name is a method
employee.print_name(e1) # works too. class_name.method_name(object_instance)
# e1.print_name_junk() # error since self if ommitted
<__main__.employee at 0x14e2b81d0>
'abc def'
'abc def@gmail.com'
abc def abc def
e1.pay
e1.apply_new_year_bonus(bonus = 2)
e1.pay
e1.pay
employee.apply_new_year_bonus(e1, bonus = 2)
e1.pay
100
102
102
104
class employee:
new_year_bonus = 10
def __init__(self, name, pay):
self.name = name
self.pay = pay
self.email = name + "@gmail.com"
def print_name(self): # this is a method
print(self.name)
def apply_new_year_bonus(self):
# self.pay = self.pay + new_year_bonus # error
# self.pay = self.pay + employee.new_year_bonus # works
self.pay = self.pay + self.new_year_bonus # works
e1 = employee("abd def", 100) # e1 will be passed as self
# getattr(e1) # fails
e1.__dict__
employee.__dict__
employee.new_year_bonus
e1.new_year_bonus
e1.pay
e1.apply_new_year_bonus() # bonus = 2
e1.pay
e1.whatever_attr = 999
e1.whatever_attr
e1.__dict__
e1.new_year_bonus = 999
e1.__dict__
e2 = employee("ash red", 766)
e2.whatever_attr
e2.__dict__
e2.new_year_bonus = 999
e1.__dict__
class employee:
employee_count = 0
new_year_bonus = 10
def __init__(self, name, pay):
self.name = name
self.pay = pay
self.email = name + "@gmail.com"
employee.employee_count = employee.employee_count + 1
@classmethod
def from_string(cls, data_string):
name, pay = data_string.split("-")
return cls(name, int(pay))
def print_name(self): # this is a method
print(self.name)
def apply_new_year_bonus(self):
# self.pay = self.pay + new_year_bonus # error
# self.pay = self.pay + employee.new_year_bonus # works
self.pay = self.pay + self.new_year_bonus # works
@classmethod
def set_new_year_bonus(cls, amt):
cls.new_year_bonus = amt
# cls.new_year_bonus = amt + cls.new_year_bonus # works too
employee.employee_count # 0
e1 = employee("ash red", 100)
employee.employee_count # 1
e1.employee_count
e2 = employee("what ever", 200)
employee.employee_count # 2
e2.employee_count # e1 and e2 employee count updates to 2
# classmethod - update new_year_bonus for class and all instances
e1 = employee("ash red", 100)
e1.new_year_bonus
e2 = employee("what ever", 200)
e2.new_year_bonus
employee.set_new_year_bonus(44)
employee.new_year_bonus
e1.new_year_bonus
e2.new_year_bonus
# classmethod - generate instances dynamically
e3 = employee.from_string("ashrith reddy-100")
e3.name
e3.pay
e3.__dict__
e3.new_year_bonus
e3.apply_new_year_bonus(); e3.pay
class developer(employee): # Developer inherits from employee
new_year_bonus = 200
pass
print(help(developer))
dev_1 = developer("apple", 400)
dev_1.email
dev_1.pay
dev_1.apply_new_year_bonus()
dev_1.pay