Python References
Python References
Python references:
something:10
>>> x
'10'
>>> x = input("something:")
>>> x
"'10'"
a = y*x*x
print(a)
return a
a = area(10)
print("area",a)
Numbers
String
List
Tuple
Dictionary
Python Numbers
var1 = 1
var2 = 10
del var
del var_a, var_b
long (long integers, they can also be represented in octal and hexadecimal)
Python Strings
str ='Hello World!'
Strings can be created by enclosing characters inside a single quote or double quotes. Even
triple quotes can be used in Python but generally used to represent multiline strings and
docstrings.
String Formats:
name='priya'
>>> age=26
Python Lists
list =['abcd',786,2.23,'john',70.2]
tinylist =[123,'john']
list # Prints complete list
Python Tuples
tuple =('abcd',786,2.23,'john',70.2)
tinytuple =(123,'john')
#!/usr/bin/python
tuple =('abcd',786,2.23,'john',70.2)
list =['abcd',786,2.23,'john',70.2]
Python Dictionary
tinydict ={'name':'john','code':6734,'dept':'sales'}
The second case can be expressed with a dictionary as well, as we can see in the following
code:
>>> data = dict(province="Ontario",capital="Toronto")
>>> data
{'province': 'Ontario', 'capital': 'Toronto'}
>>> print("The capital of {province} is {capital}".format(**data))
The capital of Ontario is Toronto
The double "*" in front of data turns data automatically into the form
'province="Ontario",capital="Toronto"'. Let's look at the following Python program:
capital_country = {"United States" : "Washington",
"US" : "Washington",
"Canada" : "Ottawa",
"Germany": "Berlin",
"France" : "Paris",
"England" : "London",
"UK" : "London",
"Switzerland" : "Bern",
"Austria" : "Vienna",
"Netherlands" : "Amsterdam"}
center(...):
Return S centred in a string of length width. Padding is done using the specified fill
character. The default value is a space.
Examples:
>>> s = "Python"
>>> s.center(10)
' Python '
>>> s.center(10,"*")
'**Python**'
ljust(...):
Examples:
>>> s = "Training"
>>> s.ljust(12)
'Training '
>>> s.ljust(12,":")
'Training::::'
>>>
rjust(...):
Examples:
>>> s = "Programming"
>>> s.rjust(15)
' Programming'
>>> s.rjust(15, "~")
'~~~~Programming'
>>>
zfill(...):
Pad a string S with zeros on the left, to fill a field of the specified width. The string S
is never truncated. This method can be easily emulated with rjust.
Examples:
Types of Operator
Python language supports the following types of operators.
Arithmetic Operators
% modulo
** exponent
// floor division
If else loop:
if amount<1000:
discount = amount*0.05
print ("Discount",discount)
else:
discount = amount*0.10
print ("Discount",discount)
Assignment Operators
Logical Operators
marks=67
print('grade a')
else:
print('grade b')
grade b
elif loop:
print('grade a')
elif(marks<60and marks>80):
print('grade b')
print('grade c')
else:
print('fail')
Bitwise Operators
&-And
|-or
^-xor
~ones compliment
<<binary left
>>binary right
Membership Operators
In
Not in
if(a in list):
print("yes")
else:
print("no")
Identity Operators:
Is
Is not
Id(a)
While loop:
count =0
while(count <9):
print("Good bye!")
count =0
count = count +1
else:
range(0,5)
>>> list(range(5))
[0,1,2,3,4]
>>>forvarin list(range(5)):
print(var)
print()
fruits =['banana','apple','mango']
for i in range(1,11):
for j in range(1,11):
k=i*j
print(k,end=' ')
print()
Break statement:
if letter =='h':
break
whilevar>0:
var=var-1
ifvar==5:
break
no=int(input('any number: '))
numbers =[11,33,55,39,55,75,37,21,23,41,13]
if num ==no:
break
else:
Continue statements:
if letter =='h':
continue
whilevar>0:
var=var-1
ifvar==5:
continue
However, nothing happens when pass is executed. It results into no operation (NOP).
pass
Sets
If we want to create a set, we can call the built-in set function with a sequence or another
iterable object:
In the following example, a string is singularized into its characters to build the resulting set
x:
>>> x = set("A Python Tutorial")
>>> x
{'A', ' ', 'i', 'h', 'l', 'o', 'n', 'P', 'r', 'u', 't', 'a', 'y', 'T'}
>>> type(x)
<class 'set'>
>>>
We can pass a list to the built-in set function, as we can see in the following:
Now, we want to show what happens, if we pass a tuple with reappearing elements to the
set function - in our example the city "Paris":
>>> cities = set(("Paris", "Lyon", "London","Berlin","Paris","Birmingham"))
>>> cities
{'Paris', 'Birmingham', 'Lyon', 'London', 'Berlin'}
>>>
Sequences are one of the principal built-in data types besides numerics, mappings, files,
instances and exceptions. Python provides for six sequence (or sequential) data types:
strings
byte sequences
byte arrays
lists
tuples
range objects
countries = ["Germany","Switzerland","Austria","France","Belgium",
"Netherlands", "England"]
>>> len(countries)
7
>>> fib = [1,1,2,3,5,8,13,21,34,55]
>>> len(fib)
10
Sublists
Lists can have sublists as elements. These sublists may contain sublists as well, i.e. lists can
be recursively constructed by sublist structures.
>>> person = [["Marc","Mayer"],["17, Oxford Str", "12345","London"],"07876-
7876"]
>>> name = person[0]
>>> print(name)
['Marc', 'Mayer']
>>> first_name = person[0][0]
>>> print(first_name)
Marc
>>> last_name = person[0][1]
>>> print(last_name)
Mayer
>>> address = person[1]
>>> street = person[1][0]
>>> print(street)
17, Oxford Str
Functions:
def fahrenheit(T_in_celsius):
""" returns the temperature in degrees Fahrenheit """
return (T_in_celsius * 9 / 5) + 32
Optional Parameters
def Hello(name="everybody"):
""" Greets a person """
print("Hello " + name + "!")
Hello("Peter")
Hello()
Using keyword parameters is an alternative way to make function calls. The definition of the
function doesn't change.
An example:
print(sumsub(12,4))
print(sumsub(42,15,d=10))
Keyword parameters can only be those, which are not used as positional arguments. We can
see the benefit in the example. If we hadn't keyword parameters, the second call to function
would have needed all four arguments, even though the c needs just the default value:
print(sumsub(42,15,0,10))
def empty_return(x,y):
c = x + y
return
res = empty_return(4,5)
print(res)
def f():
s = "Perl"
print(s)
s = "Python"
f()
print(s)
def f():
global s
print(s)
s = "dog"
print(s)
s = "cat"
f()
print(s)
print(arithmetic_mean(45,32,89,78))
print(arithmetic_mean(8989.8,78787.78,3453,78778.73))
print(arithmetic_mean(45,32))
print(arithmetic_mean(45))
x = [3, 5, 9]
arithmetic_mean(*x)
A practical example:
We have a list
my_list = [('a', 232),
('b', 343),
('c', 543),
('d', 23)]
This can be done by using the *-operator and the zip function in the following way:
list(zip(*my_list))
We can track how the function works by adding two print() functions to the previous
function definition:
def factorial(n):
print("factorial has been called with n = " + str(n))
if n == 1:
return 1
else:
res = n * factorial(n-1)
print("intermediate result for ", n, " * factorial(" ,n-1, "):
",res)
return res
print(factorial(5))
Function example:
>>> def no_side_effects(cities):
... print(cities)
... cities = cities + ["Birmingham", "Bradford"]
... print(cities)
...
>>> locations = ["London", "Leeds", "Glasgow", "Sheffield"]
>>> no_side_effects(locations)
['London', 'Leeds', 'Glasgow', 'Sheffield']
['London', 'Leeds', 'Glasgow', 'Sheffield', 'Birmingham', 'Bradford']
>>> print(locations)
['London', 'Leeds', 'Glasgow', 'Sheffield']
>>>
This means that we have two names, i.e. "succ" and "successor" for the same function. The
next important fact is that we can delete either "succ" or "successor" without deleting the
function itself.
>>> del succ
>>> successor(10)
11
def g():
print("Hi, it's me 'g'")
print("Thanks for calling me")
f()
print(temperature(20))
The output:
It's 68.0 degrees!
Lambda expressions:
The argument list consists of a comma separated list of arguments and the expression is an
arithmetic expression using these arguments. You can assign the function to a variable to
give it a name.
The following example of a lambda function returns the sum of its two arguments:
>>> sum = lambda x, y : x + y
>>> sum(3,4)
7
r = map(func, seq)
The first argument func is the name of a function and the second a sequence (e.g. a
list) seq. map() applies the function func to all the elements of the sequence seq. Before
Python3, map() used to return a list, where each element of the result list was the result of
the function func applied on the corresponding element of the list or tuple "seq". With
Python 3, map() returns an iterator.
In the example above we haven't used lambda. By using lambda, we wouldn't have had to
define and name the functions fahrenheit() and celsius(). You can see this in the following
interactive session:
>>> C = [39.2, 36.5, 37.3, 38, 37.8]
>>> F = list(map(lambda x: (float(9)/5)*x + 32, C))
>>> print(F)
[102.56, 97.7, 99.14, 100.4, 100.03999999999999]
>>> C = list(map(lambda x: (float(5)/9)*(x-32), F))
>>> print(C)
[39.2, 36.5, 37.300000000000004, 38.00000000000001, 37.8]
>>>
Filtering
The function
filter(function, sequence)
offers an elegant way to filter out all the elements of a sequence "sequence", for which the
function function returns True. i.e. an item will be produced by the iterator result of
filter(function, sequence) if item is included in the sequence "sequence" and if
function(item) returns True.
In other words: The function filter(f,l) needs a function f as its first argument. f has to
return a Boolean value, i.e. either True or False. This function will be applied to every
element of the list l. Only if f returns True will the element be produced by the iterator,
which is the return value of filter(function, sequence).
In the following example, we filter out first the odd and then the even elements of the
sequence of the first 11 Fibonacci numbers:
The function
reduce(func, seq) :
Examples of reduce()
Determining the maximum of a list of numerical values by using reduce:
>>> from functools import reduce
>>> f = lambda a,b: a if (a > b) else b
>>> reduce(f, [47,11,42,102,13])
102
>>>
It's very simple to change the previous example to calculate the product (the factorial) from
1 to a number, but do not choose 100. We just have to turn the "+" operator into "*":
>>> reduce(lambda x, y: x*y, range(1,49))
12413915592536072670862289047373375038521486354677760000000000
If you are into lottery, here are the chances to win a 6 out of 49 drawing:
>>> reduce(lambda x, y: x*y, range(44,50))/reduce(lambda x, y: x*y,
range(1,7))
13983816.0
>>>
The list contains the names of all the modules, variables and functions that
are defined in a module. Following is a simple example −
#!/usr/bin/python3
import math
content = dir(math)
print(content)
Importing Modules
>>> math.pi
3.141592653589793
>>> math.sin(math.pi/2)
1.0
>>> math.cos(math.pi/2)
6.123031769111886e-17
>>> math.cos(math.pi)
-1.0
from math import *
>>> sin(3.01) + tan(cos(2.1)) + e
2.2968833711382604
>>> e
2.718281828459045
>>>
Let's turn our Fibonacci functions into a module. There is hardly anything to be done, we
just save the following code in the file fibonacci.py:
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
def ifib(n):
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a
The newly created module "fibonacci" is ready for use now. We can import this module like
any other module in a program or script. We will demonstrate this in the following
interactive Python shell:
>>> import fibonacci
>>> fibonacci.fib(7)
13
>>> fibonacci.fib(20)
6765
>>> fibonacci.ifib(42)
267914296
>>> fibonacci.ifib(1000)
434665576869374564356885276750406258025646605173717804024817290895365554179
490518904038798400792551692959225930803226347752096896232398733224711616429
96440906533187938298969649928516003704476137795166849228875
>>>
Renaming a Namespace
After this import there exists a namespace mathematics but no namespace math.
It's possible to import just a few methods from a module:
>>> from math import pi,pow as power, sin as sinus
>>> power(2,3)
8.0
>>> sinus(pi)
1.2246467991473532e-16
What is Tick?
Time intervals are floating-point numbers in units of seconds. Particular
instants in time are expressed in seconds since 12:00am, January 1,
1970(epoch).
Example
#!/usr/bin/python3
ticks = time.time()
import time
print(time.localtime());
#!/usr/bin/python3
import time
localtime = time.asctime( time.localtime(time.time()))
#!/usr/bin/python3
import calendar
cal = calendar.month(2016,2)
print(cal)
With the aid of exception handling, we can write robust code for reading an integer from
input:
while True:
try:
n = input("Please enter an integer: ")
n = int(n)
break
except ValueError:
print("No valid integer! Please try again ...")
try:
num1, num2 = eval(input("Enter two numbers, separated by a comma : "))
result = num1 / num2
print("Result is", result)
except ZeroDivisionError:
print("Division by zero is error !!")
except SyntaxError:
print("Comma is missing. Enter numbers separated by comma like this 1, 2")
except:
print("Wrong input")
else:
print("No exceptions")
finally:
print("This will execute no matter what")
FILE Handling in Python
classEmployee:
empCount =0
self.name = name
self.salary = salary
Employee.empCount +=1
def displayCount(self):
def displayEmployee(self):
emp1 =Employee("Zara",2000)
emp2 =Employee("Manni",5000)
emp1.displayEmployee()
emp2.displayEmployee()
You can add, remove, or modify attributes of classes and objects at any
time −
emp1.salary = 7000 # Add an 'salary' attribute.
emp1.name = 'xyz' # Modify 'age' attribute.
del emp1.salary # Delete 'age' attribute.
Instead of using the normal statements to access attributes, you can use
the following functions −
print("Employee.__doc__:",Employee.__doc__)
print("Employee.__name__:",Employee.__name__)
print("Employee.__module__:",Employee.__module__)
print("Employee.__bases__:",Employee.__bases__)
print("Employee.__dict__:",Employee.__dict__ )
parentAttr =100
def __init__(self):
def parentMethod(self):
Parent.parentAttr = attr
def getAttr(self):
def __init__(self):
def childMethod(self):
classPolygon:
def __init__(self, no_of_sides):
self.n = no_of_sides
self.sides =[for i in range(no_of_sides)]
def inputSides(self):
self.sides =[float(input("Enter side "+str(i+1)+" : "))for i in
range(self.n)]
def dispSides(self):
for i in range(self.n):
print("Side",i+1,"is",self.sides[i])
This class has data attributes to store the number of sides, n and magnitude of each
side as a list, sides.
Method inputSides() takes in magnitude of each side and similarly, dispSides() will
display these properly.
A triangle is a polygon with 3 sides. So, we can created a class called Triangle which
inherits from Polygon. This makes all the attributes available in class Polygon readily
available in Triangle. We don't need to define them again (code re-
usability). Triangle is defined as follows.
classTriangle(Polygon):
def __init__(self):
Polygon.__init__(self,3)
def findArea(self):
a, b, c =self.sides
# calculate the semi-perimeter
s =(a + b + c)/2
area =(s*(s-a)*(s-b)*(s-c))**0.5
print('The area of the triangle is %0.2f'%area)
However, class Triangle has a new method findArea() to find and print the area of the
triangle. Here is a sample run.
>>> t =Triangle()
>>> t.inputSides()
Enter side 1:3
Enter side 2:5
Enter side 3:4
>>> t.dispSides()
Side1is3.0
Side2is5.0
Side3is4.0
>>> t.findArea()
The area of the triangle is6.00
Generally when overriding a base method, we tend to extend the definition rather than
simply replace it. The same is being done by calling the method in base class from the
one in derived class (calling Polygon.__init__() from __init__() in Triangle).
A better option would be to use the built-in function super(). So, super().__init__(3) is
equivalent to Polygon.__init__(self,3) and is preferred. You can learn more about
the super() function in Python.
Two built-in functions isinstance() and issubclass() are used to check inheritances.
Function isinstance() returns True if the object is an instance of the class or other
classes derived from it. Each and every class in Python inherits from the base
class object.
>>> isinstance(t,Triangle)
True
>>> isinstance(t,Polygon)
True
>>> isinstance(t,int)
False
>>> isinstance(t,object)
True
>>> issubclass(Polygon,Triangle)
False
>>> issubclass(Triangle,Polygon)
True
>>> issubclass(bool,int)
True
Encapsulation is often accomplished by providing two kinds of methods for attributes: The
methods for retrieving or accessing the values of attributes are called getter methods.
Getter methods do not change the values of attributes, they just return the values. The
methods used for changing the values of attributes are called setter methods.
We will define now a Robot class with a Getter and a Setter for the name attribute. We will
call them get_name and set_name accordingly.
class Robot:
def say_hi(self):
if self.name:
print("Hi, I am " + self.name)
else:
print("Hi, I am a robot without a name")
def get_name(self):
return self.name
x = Robot()
x.set_name("Henry")
x.say_hi()
y = Robot()
y.set_name(x.get_name())
print(y.get_name())
Hopefully, it will be easy for you to see, that this program prints the following:
Hi, I am Henry
Henry
Before you go on, you can do a little exercise. You can add an additional attribute
"build_year" with Getters and Setters to the Robot class.
class Robot:
def __init__(self,
name=None,
build_year=None):
self.name = name
self.build_year = build_year
def say_hi(self):
if self.name:
print("Hi, I am " + self.name)
else:
print("Hi, I am a robot without a name")
if self.build_year:
print("I was built in " + str(self.build_year))
else:
print("It's not known, when I was created!")
def get_name(self):
return self.name
def get_build_year(self):
return self.build_year
x = Robot("Henry", 2008)
y = Robot()
y.set_name("Marvin")
x.say_hi()
y.say_hi()
def __str__(self):
return "Name: " + self.name + ", Build Year: " +
str(self.build_year)
if __name__ == "__main__":
x = Robot("Marvin", 1979)
x_repr = repr(x)
print(x_repr, type(x_repr))
new = eval(x_repr)
print(new)
print("Type of new:", type(new))
$ python3 robot_class6b.py
Robot("Marvin",1979) <class 'str'>
Name: Marvin, Build Year: 1979
Type of new: <class '__main__.Robot'>
class Robot:
def say_hi(self):
if self.__name:
print("Hi, I am " + self.__name)
else:
print("Hi, I am a robot without a name")
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def get_build_year(self):
return self.__build_year
def __repr__(self):
return "Robot('" + self.__name + "', " + str(self.__build_year) +
")"
def __str__(self):
return "Name: " + self.__name + ", Build Year: " +
str(self.__build_year)
if __name__ == "__main__":
x = Robot("Marvin", 1979)
y = Robot("Caliban", 1943)
for rob in [x, y]:
rob.say_hi()
if rob.get_name() == "Caliban":
rob.set_build_year(1993)
print("I was built in the year " + str(rob.get_build_year()) + "!")
Hi, I am Marvin
I was built in the year 1979!
Hi, I am Caliban
I was built in the year 1993!
class ComplexNumber:
def __init__(self,r = 0,i = 0):
self.real = r
self.imag = i
def getData(self):
print("{0}+{1}j".format(self.real,self.imag))
Destructor
What we said about constructors holds true for destructors as well. There is no "real"
destructor, but something similar, i.e. the method __del__. It is called when the instance is
about to be destroyed and if there is no other reference to this instance. If a base class has
a __del__() method, the derived class's __del__() method, if any, must explicitly call it to
ensure proper deletion of the base class part of the instance.
class Robot():
def __init__(self, name):
print(name + " has been created!")
def __del__(self):
print ("Robot has been destroyed")
if __name__ == "__main__":
x = Robot("Tik-Tok")
y = Robot("Jenkins")
z = x
print("Deleting x")
del x
print("Deleting z")
del z
del y
$ python3 del_example.py
Tik-Tok has been created!
Jenkins has been created!
Deleting x
Deleting z
Robot has been destroyed
Robot has been destroyed
The new method creates and returns the new class object, and after this the init method
initializes the newly created object.
class Robot:
counter = 0
def __init__(self, name):
self.name = name
def sayHello(self):
return "Hi, I am " + self.name
def Rob_init(self, name):
self.name = name
Robot2 = type("Robot2",
(),
{"counter":0,
"__init__": Rob_init,
"sayHello": lambda self: "Hi, I am " + self.name})
x = Robot2("Marvin")
print(x.name)
print(x.sayHello())
y = Robot("Marvin")
print(y.name)
print(y.sayHello())
print(x.__dict__)
print(y.__dict__)
Marvin
Hi, I am Marvin
Marvin
Hi, I am Marvin
{'name': 'Marvin'}
{'name': 'Marvin'}
''' Program make a simple calculator that can add, subtract, multiply and
divide using functions '''
print("Select operation.")
print("1.Add")
print("2.Subtract")
print("3.Multiply")
print("4.Divide")
if choice == '1':
print(num1,"+",num2,"=", add(num1,num2))
# Python program to find the largest number among the three input numbers
# Program to sort alphabetically the words form a string provided by the user
words = my_str.split()
words.sort()
print(word)
Regular expressions:
Regular expressions (called REs, or regexes, or regex patterns) are essentially a tiny,
highly specialized programming language embedded inside Python and made available
through the re module
pattern = "Cookie"
sequence = "Cookie"
if re.match(pattern, sequence):
print("Match!")
Example
import re
# Lets use a regular expression to match a date string. Ignore
# the output since we are just testing if the regex matches.
regex = r"([a-zA-Z]+) (\d+)"
if re.search(regex, "June 24"):
# Indeed, the expression "([a-zA-Z]+) (\d+)" matches the date string
# This will print [0, 7), since it matches at the beginning and end of the
# string
print("Match at index %s, %s" % (match.start(), match.end()))
Example
#!/usr/bin/python
import re
else:
print"Nothing found!!"
import re
xx="happy100 is fine"
>>> rl=re.findall(r"^\w+",xx)
>>> print(rl)
['happy100']
text=”software testing is easy to learn”
patterns = ['software testing', 'abcd']
if re.search(pattern, text):
print('found a match!')
else:
print('no match')
print(email)
guru99@google.com
careerguru99@hotmail.com
users@yahoomail.com
import threading
def f():
return
if __name__ == '__main__':
for i in range(3):
t = threading.Thread(target=f)
t.start()
Passing parameters
To make a thread more useful, we want to pass args to give more information
about the work. The code below passes an integer for thread id, and then the
thread prints it. The args is the argument tuple for the target invocation.
Defaults to ().
import threading
def f(id):
return
if __name__ == '__main__':
for i in range(3):
t = threading.Thread(target=f, args=(i,))
t.start()
import threading
import datetime
threading.Thread.__init__(self)
self.threadID = counter
self.name = name
self.counter = counter
def run(self):
print_date(self.name, self.counter)
datefields = []
today = datetime.date.today()
datefields.append(today)
thread1 = myThread("Thread", 1)
thread2 = myThread("Thread", 2)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
import datetime
exitFlag = 0
threading.Thread.__init__(self)
self.threadID = counter
self.name = name
self.counter = counter
def run(self):
threadLock.acquire()
print_date(self.name, self.counter)
threadLock.release()
datefields = []
today = datetime.date.today()
datefields.append(today)
threadLock = threading.Lock()
threads = []
thread1 = myThread("Thread", 1)
thread2 = myThread("Thread", 2)
thread1.start()
thread2.start()
threads.append(thread1)
threads.append(thread2)
for t in threads:
t.join()
Generator Functions:
Let's look at the interactive example below:
>>> c = create_counter(2)
>>> c
<generator object create_counter at 0x03004B48>
>>> next(c)
create_counter()
2
>>> next(c)
increment n
3
>>> next(c)
increment n
4
>>>
1. The presence of the yield keyword in create_counter() means that this is not
a normal function. It is a special kind of function which generates values one
at a time. We can think of it as a resumable function. Calling it will return
a generator that can be used to generate successive values of n.
2. To create an instance of the create_counter() generator, just call it like any
other function. Note that this does not actually execute the function code. We
can tell this because the first line of the create_counter() function
calls print(), but nothing was printed from the line:
3. >>> c = create_counter(2)
Iterators
In computer science, an iterator is an object that allows a programmer to
traverse through all the elements of a collection regardless of its specific
implementation.
iterator = iterable.__iter__()
value = iterator.next()
value = iterator.next()
...
To be more specific, we can start from an iterable, and we know a list (e.g,
[1,2,3]) is iterable. iter(iterable) produces an iterater, and from this we can
get stream of values.
>>> # Python 3
>>> iterable = [1,2,3]
>>> iterator = iterable.__iter__() # or iterator =
iter(iterable)
>>> type(iterator)
<type 'listiterator'>
>>> value = iterator.__next__() # or value = next(iterator)
>>> print(value)
1
>>> value = next(iterator)
>>> print(value)
2
Python Closures
3
Before seeing what a closure is, we have to first understand what are nested functions and non-local
variables.
# nested functions
defouterFunction(text):
text =text
definnerFunction():
print(text)
innerFunction()
if__name__ =='__main__':
outerFunction('Hey!')
Run on IDE
As we can see innerFunction() can easily be accessed inside the outerFunction body but not outside of
it’s body. Hence, here, innerFunction() is treated as nested Function which uses textas non-local
variable.
Python Closures
A Closure is a function object that remembers values in enclosing scopes even if they are not present in
memory.
It is a record that stores a function together with an environment: a mapping associating each free
variable of the function (variables that are used locally, but defined in an enclosing scope) with the
value or reference to which the name was bound when the closure was created.
A closure—unlike a plain function—allows the function to access those captured variables through
the closure’s copies of their values or references, even when the function is invoked outside their
scope.
# Python program to illustrate
# closures
defouterFunction(text):
text =text
definnerFunction():
print(text)
myFunction =outerFunction('Hey!')
myFunction()
Run on IDE
Output:
omkarpathak@omkarpathak-Inspiron-3542:
Hey!
1. As observed from above code, closures help to invoke function outside their scope.
2. The function innerFunction has its scope only inside the outerFunction. But with the use of
closures we can easily extend its scope to invoke a function outside its scope.
When and why to use Closures:
1. As closures are used as callback functions, they provide some sort of data hiding. This helps us to
reduce the use of global variables.
2. When we have few functions in our code, closures prove to be efficient way. But if we need to have
many functions, then go for class (OOP).
import mysql.connector
def connect():
try:
conn = mysql.connector.connect(host='localhost',
database='python',
user='root',
password='abc')
if conn.is_connected():
cursor = conn.cursor()
row = cursor.fetchone()
print(row)
row = cursor.fetchone()
except Error as e:
print(e)
finally:
cursor.close()
conn.close()
if __name__ == '__main__':
connect()
import mysql.connector
def connect():
try:
conn = mysql.connector.connect(host='localhost',
database='python',
user='root',
password='abc')
if conn.is_connected():
cursor = conn.cursor()
rows = cursor.fetchall()
print(row)
except Error as e:
print(e)
finally:
cursor.close()
conn.close()
if __name__ == '__main__':
connect()
while True:
rows = cursor.fetchmany(size)
if not rows:
break
yield row
def connect():
try:
conn = mysql.connector.connect(host='localhost',
database='python',
user='root',
password='abc')
if conn.is_connected():
cursor = conn.cursor()
print(row)
except Error as e:
print(e)
finally:
cursor.close()
conn.close()
if __name__ == '__main__':
connect()
def insert_book(book_id,book_name,book_price):
"VALUES(%s,%s,%s);"
args = (book_id,book_name,book_price)
try:
conn = mysql.connector.connect(host='localhost',
database='python',
user='root',
password='abc')
if conn.is_connected():
cursor = conn.cursor()
cursor.execute(query, args)
conn.commit()
except Error as e:
print(e)
finally:
cursor.close()
conn.close()
def main():
insert_book('15','geography','7600')
insert_book('16','geoscience','9600')
print('inserted successfully')
if __name__ == '__main__':
main()