Cos 201 - Programming Language 1 Lecture Note-1
Cos 201 - Programming Language 1 Lecture Note-1
FIRST SEMESTER
ONYIANTA JOHN CHIEDOZIE
1.0 INTRODUCTION
ESSENTIALS OF COMPUTER PROGRAMMING
Essentials of Programming are the bedrock on which the structures of code are
built, much like a blueprint for mastering the language of computers. Think of
them as the ABCs of the digital realm, guiding aspiring coders through a maze of
syntax and logic.
At their core, programming basics cover essential concepts and principles that
create the framework for Software Development. From understanding variables
and data types to mastering loops and conditionals and, Object Oriented
Programming (OOP), these fundamentals provide the groundwork for crafting
elegant algorithms and robust applications.
a) AWS Cloud9
b) Visual Studio
c) NetBeans
d) Eclipse
On the other hand, coding environments might offer a more lightweight and
customisable setup, allowing programmers to select specific tools and
configurations that best fit their preferences and the requirements of their
projects.
2) View Source Code: It's highly recommended that you review the modules'
source code for deeper insight into their design structure and implementation
procedure. This will guide you in designing your own custom module for a
program.
The two important terms that we have used in the above definition are −
Sequence of instructions
Computer Programming Language
To understand these terms, consider a situation when someone asks you about how to go to a
nearby KFC. What exactly do you do to tell him the way to go to KFC?
You will use Human Language to tell the way to go to KFC, something as follows −
First go straight, after half kilometer, take left from the red light and then drive around one
kilometer and you will find KFC at the right.
Here, you have used English Language to give several steps to be taken to reach KFC. If they are
followed in the following sequence, then you will reach KFC −
1. Go straight
2. Drive half kilometer
3. Take left
4. Drive around one kilometer
5. Search for KFC at your right side
Now, try to map the situation with a computer program. The above sequence of instructions is
actually a Human Program written in English Language, which instructs on how to reach KFC
from a given starting point. This same sequence could have been given in Spanish, Hindi,
Arabic, or any other human language, provided the person seeking direction knows any of
these languages.
Now, let's go back and try to understand a computer program, which is a sequence of
instructions written in a Computer Language to perform a specified task by the computer.
Following is a simple program written in Python programming Language −
The above computer program instructs the computer to print "Hello, World!" on the computer
screen.
A computer program is also called a computer software, which can range from two lines
to millions of lines of instructions.
Computer program instructions are also called program source code and computer
programming is also called program coding.
A computer without a computer program is just a dump box; it is programs that make
computers active.
Java
C
C++
Python
PHP
Perl
Ruby
1.0.6 Uses of Computer Programs
Today computer programs are being used in almost every field, household, agriculture,
medical, entertainment, defense, communication, etc. Listed below are a few applications of
computer programs −
MS Word, MS Excel, Adobe Photoshop, Internet Explorer, Chrome, etc., are examples of
computer programs.
Computer programs are being used to develop graphics and special effects in movie
making.
Computer programs are being used to perform Ultrasounds, X-Rays, and other medical
examinations.
Computer programs are being used in our mobile phones for SMS, Chat, and voice
communication.
C Programmer
C++ Programmer
Java Programmer
Python Programmer
PHP Programmer
Perl Programmer
Ruby Programmer
1.0.7 Algorithm
From programming point of view, an algorithm is a step-by-step procedure to resolve any
problem. An algorithm is an effective method expressed as a finite set of well-defined
instructions.
Thus, a computer programmer lists down all the steps required to resolve a problem before
writing the actual code. Following is a simple example of an algorithm to find out the largest
number from a given list of numbers −
The above algorithm has been written in a crude way to help beginners understand the
concept. You will come across more standardized ways of writing computer algorithms as you
move on to advanced levels of computer programming.
Similar to Human Interface Languages, Computer Programming Languages are also made of
several elements. They have the rules that govern them the same way we have rules that
governs English language. These rules are known as Syntax.
1.0.9 Syntax
Syntax is a set of rules that defines the structure of a language. Every programming language
follows a different syntax. A programming language isn’t understandable without its syntax.
Syntax helps the computer to read and understand the code. It is like giving instructions to
the code.
For example,
int a =10;
here a is variable
int is data type
10 is value
1.0.10 Bug
Error in a code (computer program) is known as bug and the act of removing the error is
known as debugging.
1.0.11 Debugging
Debugging removes errors from computer programs and enables software development and
engineering teams to produce functioning software. Through debugging they can examine
individual code sections to ensure the program works as intended.
Programmers make mistakes. For whimsical reasons, programming errors are called bugs and
the process of tracking them down is called debugging. Programming, and especially
debugging, sometimes brings out strong emotions. If you are struggling with a difficult bug, you
might feel angry, despondent, or embarrassed.
Learning to debug can be frustrating, but it is a valuable skill that is useful for many activities
beyond programming
a) Syntax Error: This is an erroneous sequence of characters or tokens in the code that
doesn't follow the syntax of a programming language. If you do not follow the rules
defined by the programing language, then at the time of compilation, you will get syntax
errors and the program will not be compiled. From syntax point of view, even a single
dot or comma or a single semicolon matters and you should take care of such small
syntax as well. “Syntax” refers to the structure of a program and the rules about that
structure. For example, parentheses have to come in matching pairs, so (1 + 2) is legal,
but 8) is a syntax error. If there is a syntax error anywhere in your program, Python
displays an error message and quits, and you will not be able to run the program. During
the first few weeks of your programming career, you might spend a lot of time tracking
down syntax errors. As you gain experience, you will make fewer errors and find them
faster.
b) Runtime error: The second type of error is a runtime error, so called because the error
does not appear until after the program has started running. These errors are also called
exceptions because they usually indicate that something exceptional (and bad) has
happened. Runtime errors are rare in the simple programs you will see in the first few
chapters, so it might be a while before you encounter one.
c) Semantic error: The third type of error is “semantic”, which means related to meaning.
If there is a semantic error in your program, it will run without generating error
messages, but it will not do the right thing. It will do something else. Specifically, it will
do what you told it to do. Identifying semantic errors can be tricky because it requires
you to work backward by looking at the output of the program and trying to figure out
what it is doing.
2.0TYPES OF PROGRAMMING LANGUAGE:
2.0.1 Programming Paradigms
2.0.1.1 What is a Programming Paradigm?
Programming paradigms are different ways or styles in which a given program or programming
language can be organized. Each paradigm consists of certain structures, features, and opinions
about how common programming problems should be tackled.
The question of why are there many different programming paradigms is similar to why are
there many programming languages. Certain paradigms are better suited for certain types of
problems, so it makes sense to use different paradigms for different kinds of projects.
Also, the practices that make up each paradigm have developed through time. Thanks to the
advances both in software and hardware, different approaches have come up that didn't exist
before.
Human creativity gave birth to programming paradigms. As a species, we just like creating
things, improving what others have built in the past, and adapting tools to our preference or to
what seems more efficient to us.
All this results in the fact that today we have many options to choose from when we want to
write and structure a given program.
Programming languages aren't always tied to a specific paradigm. There are languages that
have been built with a certain paradigm in mind and have features that facilitate that kind of
programming more than others (Haskel and functional programming is a good example).
But there are also "multi-paradigm" languages, meaning you can adapt your code to fit a
certain paradigm or another (JavaScript and Python are good examples).
2.0.1.3Popular Programming Paradigms
Now that we have introduced what programming paradigms are and are not, let's go through
the most popular ones, explain their main characteristics, and compare them.
Keep in mind this list is not exhaustive. There are other programming paradigms not covered
here, although I'll be covering the most popular and most widely-used ones.
Imperative Programming
Imperative programming consists of sets of detailed instructions that are given to the
computer to execute in a given order. It's called "imperative" because as programmers we
dictate exactly what the computer has to do, in a very specific way.
See that we're telling the program to iterate through each element in the array, compare the
item value with 5, and if the item is bigger than 5, push it into an array.
We're being detailed and specific in our instructions, and that's what imperative programming
stands for.
Procedural Programming
Procedural programming is a derivation of imperative programming, adding to it the feature of
functions (also known as "procedures" or "subroutines").
In procedural programming, the user is encouraged to subdivide the program execution into
functions, as a way of improving modularity and organization.
Following our cake example, procedural programming may look like this:
function pourIngredients() {
- Pour flour in a bowl
- Pour a couple eggs in the same bowl
- Pour some milk in the same bowl
}
function mixAndTransferToMold() {
- Mix the ingredients
- Pour the mix in a mold
}
function cookAndLetChill() {
- Cook for 35 minutes
- Let chill
}
pourIngredients()
mixAndTransferToMold()
cookAndLetChill()
You can see that, thanks to the implementation of functions, we could just read the three
function calls at the end of the file and get a good idea of what our program does.
That simplification and abstraction is one of the benefits of procedural programming. But
within the functions, we still got same old imperative code.
Functional Programming
Functional programming takes the concept of functions a little bit further.
In functional programming, functions are treated as first-class citizens, meaning that they can be
assigned to variables, passed as arguments, and returned from other functions.
Another key concept is the idea of pure functions. A pure function is one that relies only on its inputs
to generate its result. And given the same input, it will always produce the same result. Besides, it
produces no side effects (any change outside the function's environment).
With these concepts in mind, functional programming encourages programs written mostly with
functions (surprise). It also defends the idea that code modularity and the absence of side effects
makes it easier to identify and separate responsibilities within the codebase. This therefore improves
the code maintainability.
Going back to the array filtering example, we can see that with the imperative paradigm we might use
an external variable to store the function's result, which can be considered a side effect.
console.log(result) // Output: [ 6, 7, 8, 9 ]
console.log(filterNums()) // Output: [ 6, 7, 8, 9 ]
It's almost the same code, but we wrap our iteration within a function, in which we also store
the result array. In this way, we can assure the function doesn't modify anything outside its
scope. It only creates a variable to process its own information, and once the execution is
finished, the variable is gone too.
Declarative Programming
Declarative programming is all about hiding away complexity and bringing programming
languages closer to human language and thinking. It's the direct opposite of imperative
programming in the sense that the programmer doesn't give instructions about how the
computer should execute the task, but rather on what result is needed.
This will be much clearer with an example. Following the same array filtering story, a
declarative approach might be:
See that with the filter function, we're not explicitly telling the computer to iterate over the
array or store the values in a separate array. We just say what we want ("filter") and the
condition to be met ("num > 5").
What's nice about this is that it's easier to read and comprehend, and often shorter to write.
JavaScript's filter, map, reduce and sort functions are good examples of declarative
code.
Another good example is modern JS frameworks/libraries like React. Take this code for
example:
JSX syntax (what React uses) mixes HTML and JS in the same thing, which makes it easier and
faster to write apps. But that's not what browsers read and execute. React code is later on
transpiled into regular HTML and JS, and that's what browsers run in reality.
JSX is declarative, in the sense that its purpose is to give developers a friendlier and more
efficient interface to work with.
An important thing to notice about declarative programming is that under the hood, the
computer processes this information as imperative code anyway.
Following the array example, the computer still iterates over the array like in a for loop, but
as programmers we don't need to code that directly. What declarative programming does is
to hide away that complexity from the direct view of the programmer.
Object-Oriented Programming
One of the most popular programming paradigms is object-oriented programming (OOP).
The core concept of OOP is to separate concerns into entities which are coded as objects. Each
entity will group a given set of information (properties) and actions (methods) that can be
performed by the entity.
OOP makes heavy usage of classes (which are a way of creating new objects starting out from a
blueprint or boilerplate that the programmer sets). Objects that are created from a class are
called instances.
Following our pseudo-code cooking example, now let's say in our bakery we have a main cook
(called Frank) and an assistant cook (called Anthony) and each of them will have certain
responsibilities in the baking process. If we used OOP, our program might look like this.
mixAndBake() {
- Mix the ingredients
- Pour the mix in a mold
- Cook for 35 minutes
}
}
class AssistantCook {
constructor (name) {
this.name = name
}
pourIngredients() {
- Pour flour in a bowl
- Pour a couple eggs in the same bowl
- Pour some milk in the same bowl
}
chillTheCake() {
- Let chill
}
}
What's nice about OOP is that it facilitates the understanding of a program, by the clear
separation of concerns and responsibilities.
Assignment:
This is an example of a print statement, although it doesn’t actually print anything on paper. It
displays a result on the screen. In this case, the result is the words
Hello, World!
The quotation marks in the program mark the beginning and end of the text to be displayed;
they don’t appear in the result.
In Python 2, the print statement is slightly different; it is not a function, so it doesn’t use
parentheses.
This distinction will make more sense soon, but that’s enough to get started.
The operators +, -, and * perform addition, subtraction, and multiplication, as in the following examples:
>>> 40 + 2
42
>>> 43 - 1
42
>>> 6 * 7
42
The operator / performs division:
>>> 84 / 2
42.0
You might wonder why the result is 42.0 instead of 42. I’ll explain in the next section.
Finally, the operator ** performs exponentiation; that is, it raises a number to a power:
>>> 6**2 + 6
42
These values belong to different types: 2 is an integer, 42.0 is a floating-point number, and 'Hello, World!' is a
string, so-called because the letters it contains are strung together.
If you are not sure what type a value has, the interpreter can tell you:
>>> type(2)
<class 'int'>
>>> type(42.0)
<class 'float'>
<class 'str'>
In these results, the word “class” is used in the sense of a category; a type is a category of
values.
Not surprisingly, integers belong to the type int, strings belong to str and floating-point
numbers belong to float.
What about values like '2' and '42.0'? They look like numbers, but they are in quotation marks
like strings.
>>> type('2')
<class 'str'>
>>> type('42.0')
<class 'str'>
They’re strings.
When you type a large integer, you might be tempted to use commas between groups of
>>> 1,000,000
(1, 0, 0)
Learning about the basic types of data for coding can help you better understands these
processes. Here, we define common data types in programming and provide examples of each.
10 data types
Each programming language uses a different combination of data types. Some of these types
include:
1. Integer
Integer data types often represent whole numbers in programming. An integer's value moves
from one integer to another without acknowledging fractional numbers in between. The
number of digits can vary based on the device, and some programming languages may allow
negative values.
E.g 425
65
2. Character
In coding, alphabet letters denote characters. Programmers might represent these data types
as (CHAR) or (VARGCHAR), and they can be single characters or a string of letters. Characters
are usually fixed-length figures that default to 1 octet—an 8-bit unit of digital information—but
can increase to 65,000 octets. Examples of characters include:
3. Date
This data type stores a calendar date with other programming information. Dates are typically
a combination of integers or numerical figures. Since these are typically integer values, some
programs can store basic mathematical operations like days elapsed since certain events or
days away from an upcoming event. Some examples might be:
2009-09-15
1998-11-30 09:45:87
SYSDATETIME ()
Floating-point data types represent fractional numbers in programming. There are two main
floating-point data types, which vary depending on the number of allowable values in the
string:
Float: A data type that typically allows up to seven points after a decimal.
Similar but often longer in length, an example of the floating-point double might be:
double num2 = 1.87358497267482791E+222
The floating-point double type can provide more accurate values, but it also may require additional
memory to process.
5. Long
Long data types are often 32- or 64-bit integers in code. Sometimes, these can represent
integers with 20 digits in either direction, positive or negative. Programmers use an ampersand
to indicate the data type is a long variable. Long data types are whole numbers, both positive
and negative, that have many place values. Examples include:
-398,741,129,664,271
9,000,000,125,356,546
6. Short
Similar to the long data type, a short is a variable integer. Programmers represent these as
whole numbers, and they can be positive or negative. Sometimes a short data type is a single
integer. Short data types can be up to several integers, but they are always less than long data.
Examples include:
-27,400
5,428
17
7. String
A string data type is a combination of characters that can be either constant or variable. This
often incorporates a sequence of character data types that result in specific commands
depending on the programming language. Strings can include upper and lowercase letters,
numbers and punctuation.
String a = "Open"
8. Boolean
Boolean data is what programmers use to show logic in code. It's typically one of two values—
true or false—intended to clarify conditional statements. These can be responses to "if/when"
scenarios, where code indicates if a user performs a certain action. When this happens, the
Boolean data directs the program's response, which determines the next code in the sequence.
Here are some examples of how you might use this:
bool baseballIsBest = false;
Depending on the program, the code may direct the end-user to different screens based on
their selection.
9. Nothing
The nothing data type shows that a code has no value. This might indicate that a code is
missing, the programmer started the code incorrectly or that there were values that defy the
intended logic. It's also called the "nullable type." An example of this is:
Program.WriteWords(x Is Nothing)
10. Void
Similar to the nothing type, the void type contains a value that the code cannot process. Void
data types tell a user that the code can't return a response. Programmers might use or
encounter the void data type in early system testing when there are no responses programmed
yet for future steps. . This might appear as:
int function_name (void)
1. Primitive Data Types: These data types are built-in or predefined data types and can be
used directly by the user to declare variables. example: int, char , float, bool etc. Primitive
data types are:
o Integer
o Character
o Boolean
o Floating Point
o Double Floating Point
o Valueless or Void
2. Derived Data Types: The data-types that are derived from the primitive or built-in
datatypes are referred to as Derived Data Types. These can be of four types namely:
o Function
o List
o Tuple
o Dictionary
o Array
o Pointer
o Reference
3. Abstract or User-Defined Data Types: These data types are defined by user itself. Like,
defining a class in C++ or a structure. C++ provides the following user-defined datatypes:
o Class
o Structure
o Union
o Enumeration
o Typedef defined DataType
There are other data types such as set, byte, byte array, range. These are found mostly in
python
Variables are the names you give to computer memory locations which are used to store
values in a computer program.
For example, assume you want to store two values 10 and 20 in your program and at a later
stage, you want to use these two values. Let's see how you will do it. Here are the following
three simple steps −
#include <stdio.h>
int main() {
int a;
int b;
}
The above program creates two variables to reserve two memory locations with
names a and b. We created these variables using int keyword to specify variable data
type which means we want to store integer values in these two variables. Similarly, you can
create variables to store long, float, char or any other data type.
For example −
/* variable to store long value */
long a;
Example
x = str(3) # x will be '3'
y = int(3) # y will be 3
z = float(3) # z will be 3.0
Example
x = 10
y = "Mary"
print(type(x))
print(type(y))
The output for the code above is <class 'int'> and <class 'str'> respectively.
x = 3.73
y = ‘3.72’
z = ‘M’
a = “M”
print(type(x))
print(type(y))
print(type(z))
print(type(a))
3.9 Many Values to Multiple Variables
Python allows you to assign values to multiple variables in one line:
Example
x, y, z = "Orange", "Banana", "Cherry"
print(x)
print(y)
print(z)
3.10 Expressions
An expression is a combination of operators and operands that is interpreted to produce
some other value. In any programming language, an expression is evaluated as per the
precedence of its operators. So that if there is more than one operator in an expression, their
precedence decides which operation will be performed first? We have many different types
of expressions in Python.
1. Constant Expressions: These are the expressions that have constant values only.
Example:
Python3
# Constant Expressions
x = 15 + 1.3
print(x)
Output
16.3
+ x + y Addition
– x – y Subtraction
Multiplicati
* x * y
on
/ x / y Division
x //
// Quotient
y
% x % y Remainder
x ** Exponentiati
**
y on
Example:
Let’s see an exemplar code of arithmetic expressions in Python:
Python3
# Arithmetic Expressions
x = 40
y = 12
add = x + y
sub = x - y
pro = x * y
div = x / y
print(add)
print(sub)
print(pro)
print(div)
Output
52
28
480
3.3333333333333335
3. Integral Expressions: These are the kind of expressions that produce only integer
results after all computations and type conversions.
Example:
Python3
# Integral Expressions
a = 13
b = 12.0
c = a + int(b)
print(c)
Output
25
4. Floating Expressions: These are the kind of expressions which produce floating point
numbers as result after all computations and type conversions.
Example:
Python3
# Floating Expressions
a = 13
b =5
c =a /b
print(c)
Output
2.6
print(p)
Output
True
6. Logical Expressions: These are kinds of expressions that result in either True or False. It
basically specifies one or more conditions. For example, (10 == 9) is a condition if 10 is
equal to 9. As we know it is not correct, so it will return False. Studying logical expressions,
we also come across some logical operators which can be seen in logical expressions most
often. Here are some logical operators in Python :
P and
and It returns true if both P and Q are true otherwise returns false
Q
Example:
Let’s have a look at an exemplar code :
Python3
P = (10 == 9)
Q = (7 > 5)
# Logical Expressions
R = P and Q
S = P or Q
T = not P
print(R)
print(S)
print(T)
Output
False
True
True
7. Bitwise Expressions: These are the kind of expressions in which computations are
performed at bit level.
Example:
Python3
# Bitwise Expressions
a = 12
x = a >> 2
y = a << 1
print(x, y)
Output
3 24
# Combinational Expressions
a = 16
b = 12
c = a + (b >> 1)
print(c)
Output
22
But when we combine different types of expressions or use multiple operators in a single
expression, operator precedence comes into play.
It’s a quite simple process to get the result of an expression if there is only one operator in an
expression. But if there is more than one operator in an expression, it may give different
results on basis of the order of operators executed. To sort out these confusions,
the operator precedence is defined. Operator Precedence simply defines the priority of
operators that which operator is to be executed first. Here we see the operator precedence
in Python, where the operator higher in the list has more precedence or priority:
Precedence Name Operator
1 Parenthesis ()[]{}
2 Exponentiation **
8 Bitwise XOR ^
9 Bitwise OR |
11 Equality Operators == !=
12 Assignment Operators = += -= /= *=
So, if we have more than one operator in an expression, it is evaluated as per operator
precedence. For example, if we have the expression “10 + 3 * 4”. Going without precedence
it could have given two different outputs 22 or 52. But now looking at operator precedence,
it must yield 22. Let’s discuss this with the help of a Python program:
Python3
# Multi-operator expression
a = 10 + 3 * 4
print(a)
b = (10 + 3) * 4
print(b)
c = 10 + (3 * 4)
print(c)
Output
22
52
22
Hence, operator precedence plays an important role in the evaluation of a Python
expression.
4.0 BASIC OBJECT-ORIENTED
CONCEPTS
4.1 Python OOPs Concepts
Object Oriented Programming is a fundamental concept in Python, empowering developers
to build modular, maintainable, and scalable applications. By understanding the core OOP
principles—classes, objects, inheritance, encapsulation, polymorphism, and abstraction—
programmers can leverage the full potential of Python’s OOP capabilities to design elegant
and efficient solutions to complex problems.
# Python3 program to
# demonstrate defining
# a class
class Dog:
pass
Output:
To understand the state, behavior, and identity let us take the example of the class dog
(explained above).
The identity can be considered as the name of the dog.
State or Attributes can be considered as the breed, age, or color of the dog.
The behavior can be considered as to whether the dog is eating or sleeping.
Creating an Object
This will create an object named obj of the class Dog defined above. Before diving deep into
objects and classes let us understand some basic keywords that will be used while working
with objects and classes.
Python
obj = Dog()
The Python self
1. Class methods must have an extra first parameter in the method definition. We do not
give a value for this parameter when we call the method, Python provides it
2. If we have a method that takes no arguments, then we still have to have one argument.
3. This is similar to this pointer in C++ and this reference in Java.
When we call a method of this object as myobject.method(arg1, arg2), this is automatically
converted by Python into MyClass.method(myobject, arg1, arg2) – this is all the special self is
about.
class Dog:
# class attribute
attr1 = "mammal"
# Instance attribute
self.name = name
# Driver code
# Object instantiation
Rodger = Dog("Rodger")
Tommy = Dog("Tommy")
print("Rodger is a {}".format(Rodger.__class__.attr1))
class Dog:
# class attribute
attr1 = "mammal"
# Instance attribute
self.name = name
def speak(self):
# Driver code
# Object instantiation
Rodger = Dog("Rodger")
Tommy = Dog("Tommy")
Rodger.speak()
Tommy.speak()
Output
My name is Rodger
My name is Tommy
4.3.3 Inheritance (Inheritance in Python)
In Python Object Oriented Programming, Inheritance is the capability of one class to derive or
inherit the properties from another class. The class that derives properties is called the
derived class or child class and the class from which the properties are being derived is called
the base class or parent class.
The benefits of inheritance are:
It represents real-world relationships well.
It provides the reusability of a code. We don’t have to write the same code again and
again. Also, it allows us to add more features to a class without modifying it.
It is transitive in nature, which means that if class B inherits from another class A, then all
the subclasses of B would automatically inherit from class A.
Types of Inheritance
Single Inheritance: Single-level inheritance enables a derived class to inherit
characteristics from a single-parent class.
Multilevel Inheritance: Multi-level inheritance enables a derived class to inherit
properties from an immediate parent class which in turn inherits properties from his
parent class.
Hierarchical Inheritance: Hierarchical-level inheritance enables more than one derived
class to inherit properties from a parent class.
Multiple Inheritance: Multiple-level inheritance enables one derived class to inherit
properties from more than one base class.
Inheritance in Python
We have created two classes i.e. Person (parent class) and Employee (Child Class). The
Employee class inherits from the Person class. We can use the methods of the person class
through the employee class as seen in the display function in the above code. A child class
can also modify the behavior of the parent class as seen through the details() method.
# parent class
class Person(object):
def display(self):
print(self.name)
print(self.idnumber)
def details(self):
print("My name is {}".format(self.name))
print("IdNumber: {}".format(self.idnumber))
# child class
class Employee(Person):
def __ _( init_self, name, idnumber, salary, post):
self.salary = salary
self.post = post
def details(self):
print("My name is {}".format(self.name))
print("IdNumber: {}".format(self.idnumber))
print("Post: {}".format(self.post))
# creation of an object variable or an instance
a = Employee('Rahul', 886012, 200000, "Intern")
Output
Rahul
886012
My name is Rahul
IdNumber: 886012
Post: Intern
4.3.4 Polymorphism
In object oriented Programming Python, Polymorphism simply means having many forms. For
example, we need to determine if the given species of birds fly or not, using polymorphism
we can do this using a single function.
Polymorphism in Python
This code demonstrates the concept of Python oops inheritance and method overriding in
Python classes. It shows how subclasses can override methods defined in their parent class to
provide specific behavior while still inheriting other methods from the parent class.
class Bird:
def intro(self):
print("There are many types of birds.")
def flight(self):
print("Most of the birds can fly but some cannot.")
class sparrow(Bird):
def flight(self):
print("Sparrows can fly.")
class ostrich(Bird):
def flight(self):
print("Ostriches cannot fly.")
obj_bird = Bird()
obj_spr = sparrow()
obj_ost = ostrich()
obj_bird.intro()
obj_bird.flight()
obj_spr.intro()
obj_spr.flight()
obj_ost.intro()
obj_ost.flight()
Output
There are many types of birds.
Most of the birds can fly but some cannot.
There are many types of birds.
Sparrows can fly.
There are many types of birds.
Ostriches cannot fly.
3.3.5 Encapsulation
In Python object oriented programming, Encapsulation is one of the fundamental concepts in
object-oriented programming (OOP). It describes the idea of wrapping data and the methods
that work on data within one unit. This puts restrictions on accessing variables and methods
directly and can prevent the accidental modification of data. To prevent accidental change,
an object’s variable can only be changed by an object’s method. Those types of variables are
known as private variables.
A class is an example of encapsulation as it encapsulates all the data that is member
functions, variables, etc.
Encapsulation in Python
In the above example, we have created the c variable as the private attribute. We cannot even
access this attribute directly and can’t even change its value.
# Python program to
# demonstrate private members
# "__" double underscore represents private attribute.
# Private attributes start with "__".
# Calling constructor of
# Base class
Base.__init__(self)
print("Calling private member of base class: ")
print(self.__c)
# Driver code
obj1 = Base()
print(obj1.a)
# Uncommenting print(obj1.c) will
# raise an AttributeError
Output
GeeksforGeeks
class Rectangle:
def __init__(self, length, width):
self.__length = length # Private attribute
self.__width = width # Private attribute
def area(self):
return self.__length * self.__width
def perimeter(self):
return 2 * (self.__length + self.__width)
rect = Rectangle(5, 3)
print(f"Area: {rect.area()}") # Output: Area: 15
print(f"Perimeter: {rect.perimeter()}") # Output: Perimeter: 16
Output
Area: 15
Perimeter: 16
4.0 Iterators/Enumerator
Usually, when someone iterates through an iterable using the conventional loops (for and
while), at times it becomes cumbersome to keep track of the count and the relative positions
of the elements in the iterable. When using for loops, there is no need to assign a variable to
keep the count of the elements; however, there is sometimes a need for a variable that
changes inside the loop based on some conditions.
It is common to use the enumerate method in Python to map the counter’s value along with
the iterable items. It can serve both as a counter and as a way to maintain the indices of the
elements in the iterable.
In simpler words, the enumerate function takes as input, an iterable and adds a counter to
each iterable element, and returns an enumerate object. The counter can also act as indices to
each element which can be used to reference these elements at a later stage when required.
print(a)
Output
[1, 'apple', 3.14, [5, 6]]
a = [1, 2, 3, 4, 5]
# List of strings
Output
[1, 2, 3, 4, 5]
['apple', 'banana', 'cherry']
[1, 'hello', 3.14, True]
Using the list() Constructor
We can also create a list by passing an iterable (like a string, tuple, or another list) to
the list() function.
Python
# From a tuple
a = list((1, 2, 3, 'apple', 4.5))
print(a)
Output
[1, 2, 3, 'apple', 4.5]
print(a)
print(b)
Output
[2, 2, 2, 2, 2]
[0, 0, 0, 0, 0, 0, 0]
Output
10
50
Python
# Initialize an empty list
a = []
# Inserting 5 at index 0
a.insert(0, 5)
print("After insert(0, 5):", a)
Output
After append(10): [10]
After insert(0, 5): [5, 10]
After extend([15, 20, 25]): [5, 10, 15, 20, 25]
5.5 Updating Elements into List
We can change the value of an element by accessing it using its index.
Python
print(a)
Output
[10, 25, 30, 40, 50]
Python
a = [10, 20, 30, 40, 50]
Output
After remove(30): [10, 20, 40, 50]
Popped element: 20
After pop(1): [10, 40, 50]
After del a[0]: [40, 50]
Output
apple
banana
cherry
Python
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
Output
6
6.0 Stack Data Structure
A stack is a linear data structure that follows the principle of Last In First Out (LIFO). This
means the last element inserted inside the stack is removed first.
You can think of the stack data structure as the pile of plates on top of another.
And, if you want the plate at the bottom, you must first remove all the plates on top. This is
exactly how the stack data structure works.
In the above image, although item 3 was kept last, it was removed first. This is exactly how
the LIFO (Last In First Out) Principle works.
We can implement a stack in any programming language like C, C++, Java, Python or C#, but
the specification is pretty much the same.
return stack.pop()
stack = create_stack()
push(stack, str(1))
push(stack, str(2))
push(stack, str(3))
push(stack, str(4))
print("popped item: " + pop(stack))
print("stack after popping an element: " + str(stack))
7.0 Queue Data Structure
A queue is a useful data structure in programming. It is similar to the ticket queue outside a
cinema hall, where the first person entering the queue is the first person who gets the ticket.
Queue follows the First In First Out (FIFO) rule - the item that goes in first is the item that
comes out first.
In the above image, since 1 was kept in the queue before 2, it is the first to be removed from
the queue as well. It follows the FIFO rule.
In programming terms, putting items in the queue is called enqueue, and removing items from
the queue is called dequeue.
We can implement the queue in any programming language like C, C++, Java, Python or C#, but
the specification is pretty much the same.
Simple Queue
Circular Queue
Priority Queue
Double Ended Queue
7.2 Basic Operations of Queue
A queue is an object (an abstract data structure - ADT) that allows the following operations:
Dequeue Operation
check if the queue is empty
class Queue():
def __init__(self, k):
self.k = k
self.queue = [None] * k
self.head = self.tail = -1
def printQueue(self):
if(self.head == -1):
print("No element in the queue")
else:
for i in range(self.head, self.tail + 1):
print(self.queue[i], end=" ")
print()
obj.dequeue()
print("After removing an element from the queue")
obj.printQueue()
Limitation of a queue
And we can only add indexes 0 and 1 only when the queue is reset (when all the elements have
been dequeued).
After REAR reaches the last index, if we can store extra elements in the empty spaces (0 and
1), we can make use of the empty spaces. This is implemented by a modified queue called
the circular queue.
Call Center phone systems use Queues to hold people calling them in order.
8.0 Searching
8.1 Searching Algorithms and its implementation in Python.
Searching algorithms are fundamental techniques used to find an element or a value within a
collection of data. This collection of data can take various forms, such as arrays, lists, trees, or
other structured representations. The primary objective of searching is to determine whether
the desired element exists within the data, and if so, to identify its precise location or
retrieve it. It plays an important role in various computational tasks and real-world
applications, including information retrieval, data analysis, decision-making processes, and
more.
There are many types of searching algorithms but for this course, we'll explore some of the
most commonly used searching algorithms in Python which are the Linear Search and Binary
Search.
1. Linear Search:
Linear Search, also known as Sequential Search, is one of the simplest and most
straightforward searching algorithms. It works by sequentially examining each element in
a collection of data (array or list) until a match is found or the entire collection has been
traversed.
Linear Search
8.2 Algorithm of Linear Search:
The Algorithm examines each element, one by one, in the
collection, treating each element as a potential match for
the key you’re searching for.
If it finds any element that is exactly the same as the key
you’re looking for, the search is successful, and it
returns the index of key.
If it goes through all the elements and none of them
matches the key, then that means “No match is Found”.
Comparing key with next element arr[1]. Since not equal, the iterator moves to the next
element as a potential match.
Now when comparing arr[2] with key, the value matches. So the Linear Search Algorithm
will yield a successful message and return the index of the element when key is found.
Python Implementation
def linear_search(arr, target):
"""
Perform linear search to find the target value in the given list.
Parameters:
arr (list): The list to be searched.
target: The value to be searched for.
Returns:
int: The index of the target value if found, otherwise -1.
"""
for i in range(len(arr)):
if arr[i] == target:
return i
return -1
# Example usage:
arr = [2, 3, 4, 10, 40]
target = 10
result = linear_search(arr, target)
if result != -1:
print(f"Linear Search: Element found at index {result}")
else:
print("Linear Search: Element not found")
Output
Linear Search: Element found at index 3
2. Binary Search
Binary Search is defined as a searching algorithm used in a sorted array by
repeatedly dividing the search interval in half. Binary search is a more efficient
searching algorithm suitable for sorted lists. It repeatedly divides the search
interval in half until the target value is found.
The idea of binary search is to use the information that the array is sorted and
reduce the time complexity to O(log N).
Algorithm of Binary Search:
Divide the search space into two halves by finding the middle index “mid”.
Compare the middle element of the search space with the key.
If the key is found at middle element, the process is terminated.
If the key is not found at middle element, choose which half will be used as the
next search space.
o If the key is smaller than the middle element, then the left side is used for
next search.
o If the key is larger than the middle element, then the right side is used for
next search.
This process is continued until the key is found or the total search space is
exhausted.
If the key matches the value of the mid element, the element is found and stop
search.
Parameters:
arr (list): The sorted list to be searched.
target: The value to be searched for.
low (int): The lower index of the search interval.
high (int): The upper index of the search interval.
Returns:
int: The index of the target value if found, otherwise -1.
"""
if low <= high:
mid = (low + high) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
return binary_search(arr, target, mid + 1, high)
else:
return binary_search(arr, target, low, mid - 1)
else:
return -1
# Example usage:
arr = [2, 3, 4, 10, 40]
target = 10
result = binary_search(sorted(arr), target, 0, len(arr) - 1)
if result != -1:
print(f"Binary Search: Element found at index {result}")
else:
print("Binary Search: Element not found")
Output
Binary Search: Element found at index 3
Sorting Techniques
The different implementations of sorting techniques in Python are:
Bubble Sort
Selection Sort
Insertion Sort
Bubble Sort
Bubble Sort is a simple sorting algorithm. This sorting algorithm repeatedly compares two
adjacent elements and swaps them if they are in the wrong order. It is also known as the
sinking sort. It has a time complexity of O(n2) in the average and worst cases scenarios and
O(n) in the best-case scenario. Bubble sort can be visualized as a queue where people arrange
themselves by swapping with each other so that they all can stand in ascending order of their
heights. Or in other words, we compare two adjacent elements and see if their order is wrong,
if the order is wrong we swap them. (i.e arr[i] > arr[j] for 1 <= i < j <=
s; where s is the size of the array, if array is to be in ascending order, and vice-versa).
Example
Here we sort the following sequence using bubble sort
Sequence: 2, 23, 10, 1
First Iteration
(2, 23, 10, 1) –> (2, 23, 10, 1), Here the first 2 elements are compared and remain the same
because they are already in ascending order.
(2, 23, 10, 1) –> (2, 10, 23, 1), Here 2nd and 3rd elements are compared and swapped(10 is
less than 23) according to ascending order.
(2, 10, 23, 1) –> (2, 10, 1, 23), Here 3rd and 4th elements are compared and swapped(1 is less
than 23) according to ascending order
At the end of the first iteration, the largest element is at the rightmost position which is sorted
correctly.
Second Iteration
(2, 10, 1, 23) –> (2, 10, 1, 23), Here again, the first 2 elements are compared and remain the
same because they are already in ascending order.
(2, 10, 1, 23) –> (2, 1, 10, 23), Here 2nd and 3rd elements are compared and swapped(1 is less
than 10) in ascending order.
At the end of the second iteration, the second largest element is at the adjacent position to the
largest element.
Third Iteration
(2, 1, 10, 23) –> (1, 2, 10, 23), Here the first 2 elements are compared and swap according to
ascending order.
The remaining elements are already sorted in the first and second Iterations. After the three
iterations, the given array is sorted in ascending order. So the final result is 1, 2, 10, 23.
# Python3 program for Bubble Sort Algorithm Implementation
def bubbleSort(arr):
n = len(arr)
# For loop to traverse through all
# element in an array
for i in range(n):
for j in range(0, n - i - 1):
bubbleSort(arr)
Selection Sort
This sorting technique repeatedly finds the minimum element and sort it in order. Bubble Sort
does not occupy any extra memory space. During the execution of this algorithm, two
subarrays are maintained, the subarray which is already sorted, and the remaining subarray
which is unsorted. During the execution of Selection Sort for every iteration, the minimum
element of the unsorted subarray is arranged in the sorted subarray. Selection Sort is a more
efficient algorithm than bubble sort. Sort has a Time-Complexity of O(n2) in the average,
worst, and in the best cases.
Example
Sequence: 7, 2, 1, 6
(7, 2, 1, 6) –> (1, 7, 2, 6), In the first traverse it finds the minimum element(i.e., 1) and it is
placed at 1st position.
(1, 7, 2, 6) –> (1, 2, 7, 6), In the second traverse it finds the 2nd minimum element(i.e., 2) and it
is placed at 2nd position.
(1, 2, 7, 6) –> (1, 2, 6, 7), In the third traverse it finds the next minimum element(i.e., 6) and it
is placed at 3rd position.
After the above iterations, the final array is in sorted order, i.e., 1, 2, 6, 7.
# Selection Sort algorithm in Python
def selectionSort(array, size):
for s in range(size):
min_idx = s
for i in range(s + 1, size):
# For sorting in descending order
# for minimum element in each loop
if array[i] < array[min_idx]:
min_idx = i
# Arranging min at the correct position
(array[s], array[min_idx]) = (array[min_idx], array[s])
# Driver code
data = [ 7, 2, 1, 6 ]
size = len(data)
selectionSort(data, size)
Insertion Sort
This sorting algorithm maintains a sub-array that is always sorted. Values from the unsorted
part of the array are placed at the correct position in the sorted part. It is more efficient in
practice than other algorithms such as selection sort or bubble sort. Insertion Sort has a Time-
Complexity of O(n2) in the average and worst case, and O(n) in the best case.
Example
Sequence: 7, 2, 1, 6
(7, 2, 1, 6) –> (2, 7, 1, 6), In the first iteration, the first 2 elements are compared, here 2 is less
than 7 so insert 2 before 7.
(2, 7, 1, 6) –> (2, 1, 7, 6), In the second iteration the 2nd and 3rd elements are compared, here
1 is less than 7 so insert 1 before 7.
(2, 1, 7, 6) –> (1, 2, 7, 6), After the second iteration (1, 7) elements are not in ascending order
so first these two elements are arranged. So, insert 1 before 2.
(1, 2, 7, 6) –> (1, 2, 6, 7), During this iteration the last 2 elements are compared and swapped
after all the previous elements are swapped.
# Creating a function for insertion sort algorithm
def insertion_sort(list1):
a = list1[i]
# Move elements of list1[0 to i-1],
# which are greater to one position
# ahead of their current position
j = i - 1
while j >= 0 and a < list1[j]:
list1[j + 1] = list1[j]
j -= 1
list1[j + 1] = a
return list1
# Driver code
list1 = [ 7, 2, 1, 6 ]
print("The unsorted list is:", list1)
print("The sorted new list is:", insertion_sort(list1))
Output
The unsorted list is: [7, 2, 1, 6]
The sorted new list is: [1, 2, 6, 7]
Time Complexity: O(n2)
Auxiliary Space: O(1)
RECURSIVE ALGORITHM
Recursion in Python
Recursion is the process of defining something in terms of itself.
A physical world example would be to place two parallel mirrors facing each other.
Any object in between them would be reflected recursively.
if x == 1:
return 1
else:
return (x * factorial(x-1))
num = 3
print("The factorial of", num, "is", factorial(num))
Output
The factorial of 3 is 6
Each function multiplies the number with the factorial of the number below it until it is equal
to one. This recursive call can be explained in the following steps.
Let's look at an image that shows a step-by-step process of what is going on:
Our recursion ends when the number reduces to 1. This is called the base condition.
Every recursive function must have a base condition that stops the recursion or else the
function calls itself infinitely.
The Python interpreter limits the depths of recursion to help avoid infinite recursions,
resulting in stack overflows.
By default, the maximum depth of recursion is 1000. If the limit is crossed, it results
in RecursionError. Let's look at one such condition.
def recursor():
recursor()
recursor()
Output
Traceback (most recent call last):
File "<string>", line 3, in <module>
File "<string>", line 2, in a
File "<string>", line 2, in a
File "<string>", line 2, in a
[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded
Advantages of Recursion
2. A complex task can be broken down into simpler sub-problems using recursion.
3. Sequence generation is easier with recursion than using some nested iteration.
Disadvantages of Recursion
Most programs and devices like a cellphone respond to events — things that happen. For
example, you might move your mouse, and the computer responds. Or you click a button, and
the program does something interesting.
These events can be triggered by key-press (keypress events), mouse click/movement (mouse
event) and timer (automatic event from a timer).
Here we will concentrate on Event Handling Methods, Event Propagation and Exception
Handling.
One is the class that raises the event, which is called a publisher, and the other class
responsible for receiving the raised events is known as subscribers. Similar to other
programming languages, Events in Python can call for multiple numbers of subscribers, and at
the same time, these subscribers can call for multiple numbers of publishers. This is one of the
great features related to event handling. We have also understood that multiple functions with
callback can be used for a single same event. So when the event is fired, every other event
handler, which is attached to the event, is invoked in a sequential manner.
def h2():
tess.left(45)
def h3():
tess.right(45)
def h4():
wn.bye() # Close down the turtle window
turtle.setup(400,500)
wn = turtle.Screen()
wn.title("How to handle mouse clicks on the window!")
wn.bgcolor("lightgreen")
tess = turtle.Turtle()
tess.color("purple")
tess.pensize(3)
tess.shape("circle")
EXCEPTION in Programming
Python Exceptions
An exception is an unexpected event that occurs during program execution. For example,
division by zero will throw an error.
divide_by_zero = 7 / 0
Output
Traceback (most recent call last):
File "<string>", line 1, in <module>
ZeroDivisionError: division by zero
Here, we have placed the code that might generate an exception inside
the try block. Every try block is followed by an except block.
When an exception occurs, it is caught by the except block. The except block
cannot be used without the try block.
result = numerator/denominator
print(result)
except:
print("Error: Denominator cannot be 0.")
except ZeroDivisionError:
print("Denominator cannot be 0.")
except IndexError:
print("Index Out of Bound.")
Here, we are trying to access a value to the index 5. Hence, IndexError exception
occurs.
When the IndexError exception occurs in the try block,
The ZeroDivisionError exception is skipped.
The set of code inside the IndexError exception is executed.
try:
num = int(input("Enter a number: "))
assert num % 2 == 0
except:
print("Not an even number!")
else:
reciprocal = 1/num
print(reciprocal)
Output
If we pass an odd number:
Enter a number: 1
Not an even number!
Here, the assert statement in the code checks that num is an even number; if num is
odd, it raises an AssertionError, triggering the except block.
Note: Exceptions in the else clause are not handled by the preceding except clauses.
Python try...finally
In Python, the finally block is always executed no matter whether there is an
exception or not.
The finally block is optional. And, for each try block, there can be only
one finally block.
Let's see an example,
try:
numerator = 10
denominator = 0
result = numerator/denominator
print(result)
except:
print("Error: Denominator cannot be 0.")
finally:
print("This is finally block.")
Output
Error: Denominator cannot be 0.
This is finally block.
In the above example, we are dividing a number by 0 inside the try block. Here, this code generates an
exception.
The exception is caught by the except block. And, then the finally block is executed.
Creating a String
To create a string in Python, you can simply enclose a sequence of
characters in quotes. For example:
Both single and double quotes can be used interchangeably, as long as they are used
consistently within the same string.
You can also use negative indexing to access characters from the end of the string. For
example, `-1` represents the last character, `-2` represents the second last character, and so
on.
String Slicing
String slicing allows you to extract a substring from a string. It is done by specifying the start and
end indices of the substring you want to extract. The start index is inclusive, while the end index
is exclusive. For example:
my_string = "Hello, World!"
print(my_string[0:5]) # Output: Hello
print(my_string[7:]) # Output: World!
print(my_string[:5]) # Output: Hello
print(my_string[-6:]) # Output: World!
Concatenating Strings
You can concatenate or combine strings using the `+` operator. For example:
string1 = "Hello"
string2 = "World"
concatenated_string = string1 + ' ' + string2
print(concatenated_string) # Output: Hello World
String Length
To determine the length of a string, you can use the `len()` function. It returns the number of
characters in the string. For example:
my_string = "Hello, World!"
length = len(my_string)
print(length) # Output: 13
String Methods
Python provides various built-in methods to perform operations and manipulations on strings, making it
easy to handle text data efficiently. Here are some commonly used string methods:
lower(): Converts all characters in a string to lowercase. This is useful for case-insensitive
comparisons or normalizing text data.
upper(): Converts all characters in a string to uppercase. This can be useful for making
text stand out or for case-insensitive comparisons.
text = "Hello World"
print(text.upper()) # Output: "HELLO WORLD"
strip(): Removes leading and trailing whitespace from a string. This is often used to clean up
user input or data read from files.
text = " Hello World "
print(text.strip()) # Output: "Hello World"
split(): Splits a string into a list of substrings based on a delimiter. By default, the delimiter is
any whitespace, but you can specify a different delimiter if needed.
text = "Hello World"
print(text.split()) # Output: ["Hello", "World"]
text = "apple,banana,cherry"
print(text.split(",")) # Output: ["apple", "banana", "cherry"]
replace(): Replaces occurrences of a specified substring with another substring. This is useful
for text substitution or cleaning up data.
text = "Hello World"
print(text.replace("World", "Python")) # Output: "Hello Python"
find(): Returns the index of the first occurrence of a substring in a string, or -1 if the substring
is not found. This method is useful for searching within strings.
text = "Hello World"
print(text.find("World")) # Output: 6
print(text.find("Python")) # Output: -1
These methods help streamline various text processing tasks, from cleaning and formatting
to searching and modifying strings, making Python a powerful tool for handling textual data.
These are just a few examples of string methods available in Python. There are many more
methods that you can explore and use depending on your specific needs.
String Formatting
String formatting allows you to create dynamic strings by inserting variables or values into a
string. There are several ways to format strings in Python, including using the `%` operator or
using the `format()` method.
Here’s an example using the `%` operator:
name = "Alice"
age = 25
formatted_string = "My name is %s and I am %d years old." % (name, age)
print(formatted_string) # Output: My name is Alice and I am 25 years old.
In this example, the f-string is created by prefixing the string literal with the ‘f’ character. Inside
the string, we can use curly braces to insert expressions. In this case, `{name}` will be
replaced with the value of the `name` variable, and `{age}` will be replaced with the value of
the `age` variable. The resulting string will be printed as “Hello, my name is John and
I am 25 years old.”
We can also perform operations and include expressions inside the curly braces. For example:
num = 42
result = f"The answer is {num * 2}"
print(result)
Here, the expression `{num * 2}` is evaluated to `84` and replaced inside the string. The
output will be “The answer is 84”.
The f-string method is very powerful and flexible. It allows us to include any valid Python
expression inside the curly braces, making it easy to format and interpolate values within
strings.
Lastly, if you need the index while iterating, you can use `enumerate()`,
which provides the index and the character at the same time:
```python
s = “Hello, World!”
for i, char in enumerate(s):
print(f”Character at index {i} is {char}”)
```
In this example, for each iteration of the loop, `i` is the index and `char` is
the character at that index in the string `s`. The `f-string` is used to
print a formatted string with the index and character.