<jupyter_start><jupyter_text>CLOSURES:**DEF ->** Closure is a function which rememebers the values in enclosing funtion even if they are not present in memory.~~~~def outerFunction(text):     text = text       def innerFunction():         print(text)       innerFunction()   if __name__ == '__main__':     outerFunction('Hey!') ~~~~<jupyter_code>def outerFunction(text): 
    text = text 
  
    def innerFunction(): 
        print(text) 
  
    innerFunction() 
  
if __name__ == '__main__': 
    outerFunction('Hey!')<jupyter_output>Hey!<jupyter_text>func() : is a function call x=fun : is calling function object<jupyter_code>def outer():
    x=10
    a=8
    b=0
    print(hex(id(x)),hex(id(a)))
    def inner(y):
        return x+y+a
    print(inner(50))
    return inner 
local_fun=outer()
print(local_fun(1))
print(local_fun.__closure__)

def raise_to(exp):
    def raise_to_exp(x):
        return pow(x,exp)
    return raise_to_exp

square=raise_to(2)
cube=raise_to(3)
print(square(5),cube(5))<jupyter_output>0x561ddbb71b40 0x561ddbb71b00
68
19
(<cell at 0x7f553c312dc8: int object at 0x561ddbb71b00>, <cell at 0x7f553c312e58: int object at 0x561ddbb71b40>)
25 125<jupyter_text>How to create a closure function ?**1. We must have a nested function****2. The nested function must refer to value defined in the enclosing function****3. Enclosing function must return the nested function.**  OOPS<jupyter_code>from math import pi

def calc_area(radius):
    return pi*radius**2
def calc_circumference(radius):
    return 2*pi*radius

circle1_name='c1'
circle1_radius=4.2

circle1_circumference = calc_circumference(circle1_radius)
print(circle1_circumference)
class Circle:
    pass

circle1=Circle()
circle2=Circle()
circle1.radius=4.2
circle1.name='C1'

print(calc_circumference(circle1.radius))
import random
class Circle:
    radius=0

circle1=Circle()
circle2=Circle()
circle1.name='C1'
circle2.name='C2'
circle1.color="Blue"
print(circle1.name,circle1.radius,circle2.name,circle2.radius)

circumference=[]
for i in range(10):
    circle=Circle()
    circle.radius=random.uniform(1.1,5.1)
    circumference.append(calc_circumference(circle2.radius))
print(circumference)
%%time
import random
from math import pi
class Circle:
    radius=0
    def calc_circumference(self):
        return 2*pi*self.radius
    def calc_area(self):
        return pi*self.radius**2
circle1=Circle()
circle2=Circle()
circle1.name='C1'
circle2.name='C2'
circle1.color="Blue"
print(circle1.name,circle1.radius,circle2.name,circle2.radius)

circle=Circle()    
circumference=[]
for i in range(10):
    circle.radius=random.uniform(1.1,5.1)
    circumference.append(circle.calc_circumference())
print(circumference)<jupyter_output>C1 0 C2 0
[30.707532418965528, 11.717835100318895, 27.711278416716205, 7.039203210847858, 14.210650039731977, 12.03444804568751, 28.81530907460553, 24.40198773773594, 14.605953625256523, 16.64478003760946]
CPU times: user 242 µs, sys: 39 µs, total: 281 µs
Wall time: 319 µs<jupyter_text>self1. self is a reference to calling object 2. self is  always a first arguement of clas methods<jupyter_code>class Car:
    wheels=4
    steering_type='Manual'
audi=Car()
merc=Car()

print(audi.wheels)

print(merc.wheels)
merc.wheels=5
print(merc.wheels)
class Car:
    wheels=4
    steering_type='Manual'
    def move_steering(self,direction):
        self.direction=direction
        print('Car is moving in {} direction'.format(direction))
        
audi=Car()
merc=Car()

print(audi.wheels)

print(merc.wheels)
merc.wheels=5
print(merc.wheels)
nano=Car()
print(nano.wheels)
nano.move_steering('left')
print(nano.direction)
class Employee:
    emp_id=0
    designation='IT'
    def set_designation(self,designation):
        #designation='Test'
        self.designation=designation
        

if __name__=='__main__':
    emp1=Employee()
    print(emp1.emp_id)
    print(emp1.designation)
    emp1.set_designation('Manager')
    print(emp1.emp_id)
    print(emp1.designation)
class Employee:
    emp_id=0
    #designation='IT'
    def __init__(self,name):
        self.emp_id=random.randint(100,1000)
        self.name=name
    def set_designation(self,designation):
        #designation='Test'
        self.designation=designation
        

if __name__=='__main__':
    emp1=Employee('Aakash')
    #print(emp1.emp_id)
    #print(emp1.designation)
    emp1.set_designation('Manager')
    print(emp1.emp_id)
    print(emp1.designation)
    print(emp1.name)
import random
from math import pi
class Circle:
    def __init__(self):
        self.radius=random.uniform(1.1,5.1)
    def calc_circumference(self):
        return 2*pi*self.radius
    def calc_area(self):
        return pi*self.radius**2
circle1=Circle()
circle2=Circle()
circle1.name='C1'
circle2.name='C2'
circle1.color="Blue"
print(circle1.name,circle1.radius,circle2.name,circle2.radius)

circle=Circle()    
circumference=[]
for i in range(10):
    circumference.append(circle.calc_circumference())
print(circumference)
#Q create 5 employees & initialise their name
#Write below functions
#1. Get emp_id,salary for user
#2 Apply salary hike to only first 2 employees
        #sal_hike=0.8
class Employee:
    def __init__(self,name):
        self.name=name
        emp_id=int(input("Enter EMP ID"))
    def sal_hike(self,sal):
        self.sal=sal+sal*(0.8)
if __name__=='__main__':
    emp1=Employee('Aakash')
    emp1.sal_hike(int(input("Enter salary")))
    print(emp1.sal)
    print(emp1.name)
    emp2=Employee('B')
    emp2.sal_hike(int(input("Enter salary")))
    print(emp2.name)
    print(emp2.sal)
    #emp3=Employee('C')
    #emp4=Employee('D')
    #emp5=Employee('E')
    
    
class Emp:
    salary_hike=1.08
    def __init__(self,n):
        self.name=n
        self.emp_id=int(input("Enter emp id"))
        self.salary=int(input("Enter salary"))
    def apply_hike(self):
        self.salary=self.salary * Emp.salary_hike

emp1=Emp("Aakash")
emp2=Emp("Bakash")
emp3=Emp("Cakash")
emp4=Emp("Dakash")
emp5=Emp("Eakash")
emp1.apply_hike()
print(emp1.name)
print(emp1.salary)
emp2.apply_hike()
print(emp2.name)
print(emp2.salary)
import random
name=['A','B','C','D','E','F']
employees=[]
for i in range(2):
    name=random.choice(name)
    emp=Emp(name)
    employees.append(emp)
print(employees[0].salary)
employees[0].apply_hike()
print(employees[0].salary)
try:
    with open('/home/student/NSE-INFY.csv','r') as infy:
        close=[]      
        d={}
        for line in infy:
            closing_price = line.split(',')[5]
            if closing_price == 'Close':
                continue
            close.append(float(closing_price))
            date = line.split(',')[0]
            year=date.split('-')[0]
            if year in d:
                d[year].append(float(closing_price))
            else:
                d[year]=[float(closing_price)]
        for key in d.keys():
            print('Close price for',key,'is --> {}'.\
                  format(sum(d[key])/len(d[key])))
            
        #print(sum(close)/len(close))
except IOError as err:
    print('File not found -->',err)
        
#Q Print details of tata
list({'k1':'v1','k2':'v2'})
d={'k1':'v1','k2':'v2'}
d.values()
list(d.values())
list(d)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13758806464981352, 'fraction_numerical': 0.0560850946263296, 'mean_word_length': 3.8460508701472556, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '445154', 'license': 'MIT', 'n_tokens_mistral': 2867, 'n_tokens_neox': 2634, 'n_words': 498, 'path': 'Mod04-Python/ClassNotes/Day6.ipynb', 'repo_name': 'kambleaa007/PG-DBDA', 'size': '7239'}