BPP Unit 2
BPP Unit 2
A program’s control flow is the order in which the program’s code executes.
The control flow of a Python program is regulated by conditional statements, loops, and
function calls.
Repetition - used for looping, i.e., repeating a piece of code multiple times.
Sequential
a=20
b=10
c=a-b
print ("Subtraction is : “, c)
Output
1.02s
Subtraction is : 10
Selection/Decision control statements
Simple if
if-else
nested if
if-elif-else
Simple if:
If statements are control flow statements that help us to run a particular code, but
only when a certain condition is met or satisfied. A simple if only has one condition to check.
If else in Python
If statement in Python tells the program what to do if the condition is true. In case the
condition is false, the program just goes on to execute what comes after if statements. In
situations where we want the program to execute some statement if the condition is true and
some other statement only if the condition is false, then we use if else in Python.
if condition:
if-statement block
else:
else-statement block
Nested if-else statements
Nested if Syntax:
if(condition):
if(condition):
#end of nested if
#end of if
The above syntax clearly says that the if block will contain another if block in it and so on. If
block can contain ‘n’ number of if block inside it.
if(condition):
if(condition):
else:
else:
Here we have included the “if-else” block inside an if block, you can also include an “if-else”
block inside “else” block.
if num1>num2:
if num1>num3:
greater=num1
else:
greater=num3
else:
if num2>num3:
greater=num2
else:
greater=num3
print("Greater = ",greater)
Output
Enter num1: 10
Enter num2: 20
Enter num3: 5
Greater = 20
if..elif..else statements
The elif is short for else if and is useful to avoid excessive indentation. If you have
multiple conditions to check and for each condition different code is required to execute, you
may use the elif statement of Python. The elif statement also takes an expression which is
checked after the first if statement. You may use multiple elif statements.
if expression:
statements
elif expression:
statements
else:
statements
Basic loop structures in python
In Python, loops can be used to solve awesome and complex problems. Loops are
used to Execute a block of statements repeatedly as long as the condition is TRUE. Or it Is an
iterator based loop, which steps through the items of iterable objects like lists, tuples, string
and executes a piece of code repeatedly for a number of times, based on the number of items
in that iterable object. There are two types of loops
1) while loop
2) for loop
While loop:
A while loop clause repetitively executes a set of statements until the given condition
turns out to be false. The general syntax for a Python while loop statement is:
variable
while (test_expression/condition) :
statement
increment/ decrement
The statement body can either be a single statement or a set or block of statements,
while the condition may or may not be an expression. In the Python while loop, the test
expression is evaluated at the start. The program execution enters the body of the while loop
if and only if the test_expression or condition evaluates to be true. The body of the while loop
is evaluated at every iteration. Evaluating the body of the while loop is continued until the
test_expression/condition evaluates to false. Now, the program control is passed to the line
immediately succeeding the while loop. In Python, indentation is used for determining the
body of the while loop.
for Loop
A for loop can iterate over every item in a list or go through every single character in
a string and won't stop until it has gone through every character. Writing for loops helps
reduce repetitiveness in your code, following the DRY (Don't Repeat Yourself) principle.
You don't write the same block of code more than once.
Syntax
statements(s)
range() function
Python range() function generates the immutable sequence of numbers starting from
the given start integer to the stop integer. It is a built-in function that returns a range object
consists of a series of integer numbers, which we can iterate using a for loop.
Syntax:
start: (Lower limit) It is the starting position of the sequence. The default value is 0 if not
specified.
stop: (Upper limit) generate numbers up to this number, i.e., An integer number specifying at
which position to stop (upper limit). The range() never includes the stop number in its result
step: Specify the increment value. Each next number in the sequence is generated by adding
the step value to a preceding number. The default value is 1 if not specified. It is nothing but
a difference between each number in the result.
Selecting appropriate loops in python
A counter controlled loop is also known as definite repetition loop, since the
number of iterations is known before the loop begins to execute. The counter-controlled loop
has the following components:
a control variable.
the increment (or decrement) value by which the control variable is modified at each
iteration of the loop.
the loop terminating condition that checks if looping should continue.
Difference between Sentinel and Counter Controlled Loop in C is given
below:
SENTINEL COUNTER
BASIS OF CONTROLLED CONTROLLED
S.NO. COMPARISON LOOP LOOP
Controlled variable
Controlling variable used is know as Controlled variable used
2. variable sentinel variable. is know as counter.
A nested loop is a loop inside the body of the outer loop. The inner or outer
loop can be any type, such as a while loop or for loop. For example, the outer for loop can
contain a while loop and vice versa. The outer loop can contain more than one inner loop.
There is no limitation on the chaining of loops. In the nested loop, the number of iterations
will be equal to the number of iterations in the outer loop multiplied by the iterations in the
inner loop. In each iteration of the outer loop inner loop execute all its iteration. For each
iteration of an outer loop the inner loop re-start and completes its execution before the outer
loop can continue to its next iteration. Nested loops are typically used for working with
multidimensional data structures, such as printing two-dimensional arrays, iterating a list that
contains a nested list.
Loop Control Statements
Loop control statements change execution from its normal sequence. When execution leaves
a scope, all automatic objects that were created in that scope are destroyed.
Break Statement
It terminates the current loop and resumes execution at the next statement, just like the
traditional break statement in C. The most common use for break is when some external
condition is triggered requiring a hasty exit from a loop. The break statement can be used in
both while and for loops. If you are using nested loops, the break statement stops the
execution of the innermost loop and start executing the next line of code after the block.
Syntax
break
Flow Diagram
Continue Statement
Syntax
continue
Flow Diagram
Pass Statement
It is used when a statement is required syntactically but you do not want any
command or code to execute. The pass statement is a null operation; nothing happens when it
executes. The pass is also useful in places where your code will eventually go, but has not
been written yet (e.g., in stubs for example)
Syntax
pass
Basis for
Break Continue
comparison
It eliminates the execution of the It will terminate only the current iteration
Task
remaining iteration of the loop of the loop.
‘break’ will resume control of the The ‘continue’ will resume the control of
Control after
program to the end of the loop the program to the next iteration of that
break/continue
enclosing that ‘break’. loop enclosing ‘continue’
Python allows the else keyword to be used with the for and while loops too.
The else block appears after the body of the loop. The statements in the else block will be
executed after all iterations are completed. The program exits the loop only after the else
block is executed.
Python Functions
Introduction:
The function helps us to organize code. The function accepts parameters as input,
processes them, and in the end, returns values as output. Let’s assume we defined a function
that computes some task. When we call that function from another function, the program
controller goes to that function, does some computation, and returns some value as output to
the caller function. You can call a function from another function
There are many types of Python Functions. And each of them is very vital in its own
way. The following are the different types of Python Functions:
The Python interpreter has a number of functions that are always available for use.
These functions are called built-in functions. For example, print() function prints the given
object to the standard output device (screen) or to the text stream file. The help() method calls
the built-in Python help system. The len() function returns the number of items (length) in an
object. type() built-in, it returns the type of the given object.
documentation strings
return [expression]
Keyword def: This is the keyword used to say that a function will be defined now, and the
next word that is there, is the function name.
Function name: This is the name that is used to identify the function. The function name
comes after the def keyword. The rules for naming a function are the same as naming a
variable. It begins with either letter from A-Z, a-z in both upper & lower cases or an
underscore (_). The rest of its name can contain underscores (_), digits (0-9), any letters in
upper or lower case.
Parameter list: Parameter list are place holders that define the parameters that go into the
function. The parameters help to generalise the transformation/computation/task that is
needed to be done. In Python, parameters are enclosed in parentheses.
Function docstrings: These are optional constructs that provide a convenient way for
associated documentation to the corresponding function. Docstrings are enclosed by triple
quotes '''you will write the docstring here'''
Function returns: Python functions returns a value. You can define what to return by
the return keyword. In the example above, the function returns result. In case you do not
define a return value, the function will return None.
Function call:
Syntax:
Function_name()
(or)
function_name(arg1, arg2)
To call a function means that you are telling the program to execute the function. If
there is a return value defined, the function would return the value, else the function would
return None. To call the function, you write the name of the function followed by
parentheses. In case you need to pass parameters/arguments to the function, you write them
inside the parentheses.
Not all variables are accessible from all parts of our program, and not all variables exist for
the same amount of time. Where a variable is accessible and how long it exists depend on
how it is defined. We call the part of a program where a variable is accessible its scope, and
the duration for which the variable exists its lifetime.
Scope: A variable is only available from inside the region it is created. This is called scope.
Life time of variable: duration for which the variable exists is called its lifetime.
A variable which is defined in the main body of a file is called a global variable. It
will be visible throughout the file, and also inside any file which imports that file. Global
variables can have unintended consequences because of their wide-ranging effects – that is
why we should almost never use them. Only objects which are intended to be used globally,
like functions and classes, should be put in the global namespace.
A variable which is defined inside a function is local to that function. It is accessible
from the point at which it is defined until the end of the function, and exists for as long as the
function is executing. The parameter names in the function definition behave like local
variables, but they contain the values that we pass into the function when we call it. When we
use the assignment operator (=) inside a function, its default behaviour is to create a new
local variable – unless a variable with the same name is already defined in the local scope.
When the value of the local variable is When the value of the global variable
Modification of
modified in one function, the changes is modified in one function changes
variable value
are not visible in another function. are visible in the rest of the program.
Global keyword is used to modify the global variable outside its current scope and
meaning. It is used to make changes in the global variable in a local context. The keyword
‘Global’ is also used to create or declare a global variable inside a function. Usually, when
you create a variable inside a function (a local variable), it can only be used within that
function. That’s where the global keyword comes in the play, which helps to create global
variables inside the function and which can be accessible in a global scope.
Syntax:
Def func():
Global variable
Resolution of names
A scope defines the visibility of a name within a block. If a local variable is defined in
a block, its scope includes that block. If the definition occurs in a function block, the scope
extends to any blocks contained within the defining one, unless a contained block introduces
a different binding for the name. When a name is used in a code block, it is resolved using the
nearest enclosing scope. The set of all such scopes visible to a code block is called the
block’s environment. When a name is not found at all, a NameError exception is raised. If the
current scope is a function scope, and the name refers to a local variable that has not yet been
bound to a value at the point where the name is used, an UnboundLocalError exception is
raised. UnboundLocalError is a subclass of NameError.
The return statement:
A return statement is used to end the execution of the function call and “returns” the
result (value of the expression following the return keyword) to the caller. The statements
after the return statements are not executed. If the return statement is without any expression,
then the special value None is returned. The return keyword can send a value back to the
main program. A value could be a string, a tuple, or any other object. This is useful because it
allows us to process data within a function. Then, we can return the data to our main
program, so we can use it outside our function.
More definitions on functions
Type of arguments:
Argument: An argument is a variable (which contains data) or a parameter that is sent to the
function as input.
1. Formal arguments: When a function is defined it (may) has (have) some parameters
within the parentheses. These parameters, which receive the values sent from the
function call, are called formal arguments.
2. Actual arguments: The parameters which we use in the function call or the
parameters which we use to send the values/data during the function call are called
actual arguments.
In python, depending on the way or format we send the arguments to the function, the
arguments can be classified into four types:
1. Required arguments
2. Keyword arguments
3. Default arguments
4. Variable length arguments
Required Arguments
Keyword argument:
In python when functions are called, the values passed are assigned to the arguments based
on their positions, which means the first value passed will be assigned to the first argument.
This position-based distribution sometimes leaves the user confused because the user never
knows the format in which function was defined. Keyword arguments are often known as
"kwargs" are the ones that allow “key = value” syntax. This means it allows the caller to pass
the argument name with its value so that the caller does not get confused with the positioning
of the arguments. It ignores the order of the arguments.
In some cases, we may want to build a function that has some default values for
parameters in case if the user doesn’t provide values for them. In such cases, we can use the
default arguments. A default argument assumes a default value if a value is not supplied as an
argument while calling the function. This can be done using the assignment operator ‘=’. We
can provide default values for one or more parameters.
Note that any number of arguments in a function can have a default value. But, using
a non-default argument after default arguments will cause a SyntaxError. The reason for this
error is because argument values are assigned to parameters in order, based on their position.
The value for a non-default argument is mandatory, but the value for a default argument is
optional.
Variable-length Arguments: Sometimes you may need more arguments to process function
then you mentioned in the definition. If we don’t know in advance about the arguments
needed in function, we can use variable-length arguments also called arbitrary arguments.
For this an asterisk (*) is placed before a parameter in function definition which can
hold non-keyworded variable-length arguments and a double asterisk (**) is placed before a
parameter in function which can hold keyworded variable-length arguments. If we use one
asterisk (*) like *var, then all the positional arguments from that point till the end are
collected as a tuple called ‘var’ and if we use two asterisks (**) before a variable like
**var, then all the positional arguments from that point till the end are collected as
a dictionary called ‘var’.
Lambda Function
The doc string line should begin with a capital letter and end with a period.
If there are more lines in the documentation string, the second line should be blank,
visually separating the summary from the rest of the description.
The following lines should be one or more paragraphs describing the object’s calling
conventions, its side effects, etc.
The docstrings are declared using ”’triple single quotes”’ or “””triple double quotes”””
just below the class, method or function declaration. All functions should have a docstring.
The docstring is included right below the def line and is enclosed in triple quotes """ """.
The triple quotes are typically included on their own lines. The syntax to add a docstring in a
function definition is below.
def function_name(arguments):
"""
<docstring text>
"""
<code>
return expression
Recursive functions:
A function that calls itself is a recursive function. This method is used when a certain
problem is defined in terms of itself. Although this involves iteration, using an iterative
approach to solve such a problem can be tedious. The recursive approach provides a very
concise solution to a seemingly complex problem. It looks glamorous but can be difficult to
comprehend! Each recursive implementation has a base case, which is when the desired state
has been reached, and a recursive case where the desired state has not been reached and the
function enters another recursive step.
The most popular example of recursion is the calculation of the factorial. Mathematically
the factorial is defined as: n! = n * (n-1)!
We use the factorial itself to define the factorial. Hence, this is a suitable case to write a
recursive function. Let us expand the above definition for the calculation of the factorial
value of 5.
5! = 5 X 4!
5 X4 X 3!
5 X4 X 3 X 2!
5 X4 X 3 X 2 X 1!
5 X4 X 3 X 2 X 1
= 120
Pros and cons of recursion in Python
Pros:
Faster when optimized: If you include recursion optimizations like tail-end recursion
and memorization, recursive approaches are faster in Python.
Less code: Recursive solutions are more compact, which means you can write
recursive solutions faster and have less code to review when debugging.
Declarative: Many developers find the logic of declaring the desired state to be more
understandable than iteration, which focuses on the steps needed to reach an unstated
goal.
Efficient Sort and Search: Recursion is especially useful for Python data science as
it is the foundation of popular sort algorithms like merge sort.
Cons
Maximum recursion depth: Python has a limited call stack that supports only 1000
nested steps. While this may seem like a lot, it becomes an issue when dealing with
large structures like lists and arrays. This can be overridden at your own rise
withsys.setrecursionlimit(1500).
Supported, not suggested: Python allows recursive calls but does not include many
built-in optimizations. Unlike iterative optimizations, developers must code all-
recursive improvements themselves.
Uses more memory: Each call saves the previous step in the call stack until the
recursive process is complete. This means recursive solutions use more memory than
iterative ones.
Recursion and iteration both repeatedly executes the set of instructions. Recursion is
when a statement in a function calls itself repeatedly. The iteration is when a loop repeatedly
executes until the controlling condition becomes false. The primary difference between
recursion and iteration is that is a recursion is a process, always applied to a function.
The iteration is applied to the set of instructions which we want to get repeatedly executed.
BASIS FOR
RECURSION ITERATION
COMPARISON
Condition If the function does not converge to If the control condition in the
some condition called (base case), iteration statement never become
it leads to infinite recursion. false, it leads to infinite iteration.
Infinite Repetition Infinite recursion can crash the Infinite loop uses CPU cycles
system. repeatedly.
Stack The stack is used to store the set of Does not uses stack.
new local variables and parameters
each time the function is called.
BASIS FOR
RECURSION ITERATION
COMPARISON
Size of Code Recursion reduces the size of the Iteration makes the code longer.
code.
Module:
When you use the import statement to import a module either in the interpreter, or a Python
script, or another module, then the interpreter searches for the imported module in the
mentioned sequence.
2. In case the interpreter does not find a built-in module of that name, it then looks out
for this file in the directory list given by the variable called sys.path.
To check out the list of directories inside the variable sys.path, you can use the following
piece of code.
>>> sys.path
The variable called sys.path is initialized from a bunch of locations. The first one is the
directory that contains the script which imports the module or the current directory. The next
one is the PYTHONPATH variable which contains a list of directories that follow the same
syntax as the PATH variable. And the final one is the default installation-dependent.
After the initialization process, the programs can modify the sys.path variable. The directory
which has the script, is placed at the top of the search path, even before the standard library
path, which means that instead of loading scripts with the same name from the standard
library, scripts from that directory will be loaded.
The PYTHONPATH is just an env variable that consists of a list of directories and can be set
using the following commands for Windows and Linux specifically.
To use the functionality, present in any module, you have to import it into your current
program. You need to use the import keyword along with the desired module name. When
interpreter comes across an import statement, it imports the module to your current program.
You can use the functions inside a module by using a dot(.) operator along with the module
name. First, let's see how to use the standard library modules.
The from...import statement allows you to import specific functions/variables from a module
instead of importing everything. In the previous example, when you
imported calculation into module_test.py, both the add() and sub() functions were imported.
But what if you only needed the add() function in your code?
print(add(1,2))
In above example, only the add() function is imported and used. Notice the use of add()? You
can now access it directly without using the module name. You can import multiple attributes
as well, separating them with a comma in the import statement. Take a look at the following
example:
You can import all attributes of a module using this statement. This will make all attributes of
imported module visible in your code.
print(add(1,2))
print(sub(3,2))
Note that in the professional world, you should avoid using from..import and from..import*,
as it makes your code less readable.
Naming a Python module is simple. You can name them whatever you want. Just make sure
that the file name ends with .py extension. As already discussed, as soon as you create a
Python module, the name of the Python modules is stored inside a variable called __name__
present inside the module.
If you want to rename a Python module while importing it, you can use the ‘as’ keyword. It
simply creates an alias for the imported module and is bound directly to it.
For example,
>>> fib.fibonacci2(1000)
You can also use the ‘as’ keyword when using the ‘from’ keyword to import modules.
>>> fib2(1000)
The above statements import the fibonacci2 function from the Fibonacci module and give it
an alias called fib2.
Please note that in order to make the execution efficient, each Python module is imported
only once in an interpreter session. Hence, if you change the modules in the middle of the
session, you need to restart the interpreter.
You can create as many modules as you want. Every file in the python is a module first create
a file and save it with .py extension.
The dir() built-in function
We can use the dir() function to find out names that are defined inside a module.
For example, we have defined a function add() in the module example that we had in the
beginning.
>>> dir(example)
['__builtins__',
'__cached__',
'__doc__',
'__file__',
'__initializing__',
'__loader__',
'__name__',
'__package__',
'add']
Here, we can see a sorted list of names (along with add). All other names that begin with an
underscore are default Python attributes associated with the module (not user-defined).
For example, the __name__ attribute contains the name of the module.
>>> example.__name__
'example'
All the names defined in our current namespace can be found out using the dir() function
without any arguments.
>>> a = 1
>>> b = "hello"
Python Namespace
Local Namespace: All the names of the functions and variables declared by a program
are held in this namespace. This namespace exists as long as the program runs. < /p>
Global Namespace: This namespace holds all the names of functions and other
variables that are included in the modules being used in the python program. It
encompasses all the names that are part of the Local namespace.
Built-in Namespace: This is the highest level of namespace which is available with
default names available as part of the python interpreter that is loaded as the
programing environment. It encompasses Global Namespace which in turn
encompasses the local namespace.
Module-private variables
Advantages of modules –
Python Package
A package folder usually contains one file named __init__.py that basically tells Python:
“Hey, this directory is a package!” The init file may be empty, or it may contain code to be
executed upon package initialization.
You’ve probably come across the term “library” as well. For Python, a library isn’t as clearly
defined as a package or a module, but a good rule of thumb is that whenever a package has
been published, it may be referred to as a library.
How to Use a Python Package
We’ve mentioned namespaces, publishing packages and importing modules. If any of these
terms or concepts aren’t entirely clear to you, we’ve got you! In this section, we’ll cover
everything you’ll need to really grasp the pipeline of using Python packages in your code.
Let’s assume that we haven’t yet installed any packages. Python comes with a big collection
of pre-installed packages known as the Python Standard Library. It includes tools for a range
of use cases, such as text processing and doing math. Let’s import the latter:
You might think of an import statement as a search trigger for a module. Searches are strictly
organized: At first, Python looks for a module in the cache, then in the standard library and
finally in a list of paths. This list may be accessed after importing sys (another standard
library module).
The sys.path command returns all the directories in which Python will try to find a package.
It may happen that you’ve downloaded a package but when you try importing it, you get an
error:
In such cases, check whether your imported package has been placed in one of Python’s
search paths. If it hasn’t, you can always expand your list of search paths:
At that point, the interpreter will have more than one more location to look for packages after
receiving an import statement.
The globals(), locals() and reload() Functions
The globals() and locals() functions can be used to return the names in the global and local
namespaces depending on the location from where they are called.
If locals() is called from within a function, it will return all the names that can be accessed
locally from that function.
If globals() is called from within a function, it will return all the names that can be accessed
globally from that function.
The return type of both these functions is dictionary. Therefore, names can be extracted using
the keys() function.
When the module is imported into a script, the code in the top-level portion of a module is
executed only once.
Therefore, if you want to reexecute the top-level code in a module, you can use
the reload() function. The reload() function imports a previously imported module again. The
syntax of the reload() function is this −
reload(module_name)
Here, module_name is the name of the module you want to reload and not the string
containing the module name. For example, to reload hello module, do the following −
reload(hello)
function redefinition