Python Notes
Python Notes
C:\pythonapp>myvenv\scripts\activate
(myvenv) C:\pythonapp>
total = item_one + \
item_two + \
item_three
triple quotes are used to span the string across multiple lines.
paragraph = """This is a paragraph. It is made up of multiple
lines and sentences."""
Memory Addresses
id() function returns the address where the object is stored.
Open Compiler
a=True;
b=10.5;
c=a+b;
print (c);
This will produce the following result:
11.5
### list() separates each character in the string and builds the list
obj=list(c)
<<< obj
['H', 'e', 'l', 'l', 'o']
To make two lines appear in the same line, define end parameter in the first
print() function and set it to a whitespace string " ".
print("City:", city, end=" ")
print("State:", state)
if expression1:
statement(s)
elif expression2:
statement(s)
elif expression3:
statement(s)
else:
statement(s)
match-case Statement
Syntax
match variable_name:
case 'pattern 1' : statement 1
case 'pattern 2' : statement 2
...
case 'pattern n' : statement n
match n:
case 0: return "Monday"
case 1: return "Tuesday"
case 2: return "Wednesday"
case _: return "Invalid day number"
match user:
case "admin" | "manager": return "Full access"
case "Guest": return "Limited access"
case _: return "No access"
Keyword Arguments
Keyword arguments are related to the function calls. When you use keyword
arguments in a function call, the caller identifies the arguments by the
parameter name. This allows you to skip arguments or place them out of
order because the Python interpreter is able to use the keywords provided to
match the values with parameters.
Default Arguments
A default argument is an argument that assumes a default value if a value
is not provided in the function call for that argument.
printinfo( name="miki" )
Keyword-only arguments
Those arguments that must be specified by their name while calling the
function is known as Keyword-only arguments. They are defined by placing
an asterisk ("*") in the function's parameter list before any keyword-only
parameters.
printinfo( 10 )
printinfo( 70, 60, 50 )
The argument list begins with the positional-only args, followed by the
slash (/) symbol.
It is followed by regular positional args that may or may not be called
as keyword arguments.
Then there may be one or more args with default values.
Next, arbitrary positional arguments represented by a variable prefixed
with single asterisk, that is treated as tuple. It is the next.
If the function has any keyword-only arguments, put an asterisk before
their names start. Some of the keyword-only arguments may have a
default value.
Last in the bracket is argument with two asterisks ** to accept arbitrary
number of keyword arguments.
Example:
sum = lambda arg1, arg2: arg1 + arg2;
# Now you can call sum as a function
print ("Value of total : ", sum( 10, 20 ))
result = add(10,20,30,40)
print (result)
result = add(1,2,3)
print (result)
The args variable prefixed with "*" stores all the values passed to it. Here,
args becomes a tuple. We can run a loop over its items to add the
numbers.
Python Modules
A module is a file containing definition of functions, classes, variables,
constants or any other Python object. Contents of this file can be made
available to any other program. Python has the import keyword for this
purpose.
Locating Modules
When you import a module, the Python interpreter searches for the module in
the following sequences −
Module Attributes
In Python, a module is an object of module class, and hence it is characterized by
attributes.
Following are the module attributes −
__file__ returns the physical name of the module.
__package__ returns the package to which the module belongs.
__doc__ returns the docstring at the top of the module if any
__dict__ returns the entire scope of the module
__name__ returns the name of the module
Save [Link] and with the following code -
def sum(x,y):
return x+y
print (sum(10,20))
You can see that [Link] has some executable statements(like execution
of the functions) along with the function definitions within the same script in
which it is defined.
What we want to happen is that when a module is imported, only the function should
be imported, its executable statements should not run. This can be done by checking
the value of __name__. If it is __main__, means it is being run and not imported.
Include the executable statements like function calls conditionally.
Updating Strings
You can "update" an existing string by (re)assigning a variable to
another string. The new value can be related to its previous value or to a
completely different string altogether. For example −
Sr.N
Format Symbol & Conversion
o.
%c
1
character
%s
2
string conversion via str() prior to formatting
%i
3
signed decimal integer
%d
4
signed decimal integer
%u
5
unsigned decimal integer
%o
6
octal integer
%x
7
hexadecimal integer (lowercase letters)
%f
8
floating point real number
var = '''
Welcome To
Python Tutorial
from TutorialsPoint
'''
Built-in String Methods
Python includes the following built-in methods to manipulate strings −
capitalize()
1
Capitalizes first letter of string.
casefold()
2 Converts all uppercase letters in string to lowercase. Similar to lower(),
but works on UNICODE characters alos.
center(width, fillchar)
3 Returns a space-padded string with the original string centered to a total
of width columns.
decode(encoding='UTF-8',errors='strict')
5 Decodes the string using the codec registered for encoding. encoding
defaults to the default string encoding.
encode(encoding='UTF-8',errors='strict')
6 Returns encoded string version of string; on error, default is to raise a
ValueError unless errors is given with 'ignore' or 'replace'.
expandtabs(tabsize=8)
8 Expands tabs in string to multiple spaces; defaults to 8 spaces per tab if
tabsize not provided.
format(*args, **kwargs)
10
This method is used to format the current string value.
11 format_map(mapping)
This method is also use to format the current string the only difference
is it uses a mapping object.
isalnum()
13 Returns true if string has at least 1 character and all characters are
alphanumeric and false otherwise.
isalpha()
14 Returns true if string has at least 1 character and all characters are
alphabetic and false otherwise.
isascii()
15 Returns True is all the characters in the string are from the ASCII
character set.
isdecimal()
16 Returns true if a unicode string contains only decimal characters and
false otherwise.
isdigit()
17
Returns true if string contains only digits and false otherwise.
isidentifier()
18
Checks whether the string is a valid Python identifier.
islower()
19 Returns true if string has at least 1 cased character and all cased
characters are in lowercase and false otherwise.
isnumeric()
20 Returns true if a unicode string contains only numeric characters and
false otherwise.
isprintable()
21
Checks whether all the characters in the string are printable.
isspace()
22 Returns true if string contains only whitespace characters and false
otherwise.
istitle()
23
Returns true if string is properly "titlecased" and false otherwise.
isupper()
24 Returns true if string has at least one cased character and all cased
characters are in uppercase and false otherwise.
join(seq)
25 Merges (concatenates) the string representations of elements in
sequence seq into a string, with separator string.
ljust(width[, fillchar])
26 Returns a space-padded string with the original string left-justified to a
total of width columns.
lower()
27
Converts all uppercase letters in string to lowercase.
lstrip()
28
Removes all leading white space in string.
maketrans()
29
Returns a translation table to be used in translate function.
partition()
30
Splits the string in three string tuple at the first occurrence of separator.
removeprefix()
31
Returns a string after removing the prefix string.
removesuffix()
32
Returns a string after removing the suffix string.
rfind(str, beg=0,end=len(string))
34
Same as find(), but search backwards in string.
rjust(width,[, fillchar])
36 Returns a space-padded string with the original string right-justified to a
total of width columns.
rpartition()
37
Splits the string in three string tuple at the ladt occurrence of separator.
rsplit()
38
Splits the string from the end and returns a list of substrings.
rstrip()
39
Removes all trailing whitespace of string.
split(str="", num=[Link](str))
40 Splits string according to delimiter str (space if not provided) and
returns list of substrings; split into at most num substrings if given.
splitlines( num=[Link]('\n'))
41 Splits string at all (or num) NEWLINEs and returns a list of each line
with NEWLINEs removed.
startswith(str, beg=0,end=len(string))
Determines if string or a substring of string (if starting index beg and
42
ending index end are given) starts with substring str; returns true if so
and false otherwise.
strip([chars])
43
Performs both lstrip() and rstrip() on string.
swapcase()
44
Inverts case for all letters in string.
title()
45 Returns "titlecased" version of string, that is, all words begin with
uppercase and the rest are lowercase.
translate(table, deletechars="")
46 Translates string according to translation table str(256 chars), removing
those in the del string.
upper()
47
Converts lowercase letters in string to uppercase.
zfill (width)
Returns original string leftpadded with zeros to a total of width
48
characters; intended for numbers, zfill() retains any sign given (less one
zero).
[Link]
Function with Description
.
len(list)
1
Returns the length of the string.
max(list)
2
Returns the max alphabetical character from the string str.
min(list)
3
Returns the min alphabetical character from the string str.
String slicing is a way of creating a sub-string from a given string. In this
process, we extract a portion or piece of a string. slice operator "[ : ]" to
perform slicing.
var[x:y] separates characters from xth position to (y-1)th position from the
original string.
String modification
a string (object of str class) is of immutable type. Unlike a list, we cannot
overwrite any character in the sequence, nor can we insert or append
characters to it directly.
String formatting
Using % operator
name = "Tutorialspoint" print("Welcome to %s!",name)
output −
Welcome to Tutorialspoint!
Using f-string
The f-strings, also known as formatted string literals, is used to embed
expressions inside string literals. The "f" in f-strings stands for formatted and
prefixing it with strings creates an f-string. The curly braces "{}" within the
string will then act as placeholders that is filled with variables, expressions,
or function calls.
item1 = 2500
item2 = 300
total = f ' Total: {item1} , {item2} sums to {item1 + item2 }'
print(total)
Updating Lists
list[2] = 2001;
[Link](obj)
1
Appends object obj to list.
[Link]()
2
Clears the contents of list.
[Link]()
3
Returns a copy of the list object.
[Link](obj)
4
Returns count of how many times obj occurs in list
[Link](seq)
5
Appends the contents of seq to list
[Link](obj)
6
Returns the lowest index in list that obj appears
[Link](index, obj)
7
Inserts object obj into list at offset index
[Link](obj=list[-1])
8
Removes and returns last object or obj from list
[Link](obj)
9
Removes object obj from list
[Link]()
10
Reverses objects of list in place
[Link]([func])
11
Sorts objects of list, use compare func if given
[Link]
Function with Description
.
cmp(list1, list2)
1
Compares elements of both lists.
len(list)
2
Gives the total length of the list.
max(list)
3
Returns item from the list with max value.
min(list)
4
Returns item from the list with min value.
list(seq)
5
Converts a tuple into list.
Change Consecutive List Items
list1 = ["a", "b", "c", "d"]
['H', 'E', 'L', 'L', 'O', 'W', 'O', 'R', 'L', 'D']
list1=[1,2,3]
list2=[4,5,6]
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
Conditionals in Python List Comprehension
list1=[x for x in range(1,21) if x%2==0]
even though we only modify the first element of the first sublist in the
shallow copied list, the same change is reflected in the original list as well.
This is because a shallow copy only creates new references to the original
objects, rather than creating copies of the objects themselves
when we modify the first element of the first sublist in the deep copied list, it
does not affect the original list.
This is because a deep copy creates a new object and recursively copies all
the nested objects, ensuring that the copied object is fully independent from
the original one
Python tuple is a sequence of comma separated items, enclosed in
parentheses (). The items in a Python tuple need not be of same data type.
Updating Tuples
tup1 = (12, 34.56);
# Following action is not valid for tuples -> tup1[0] = 100;
cmp(tuple1, tuple2)
1
Compares elements of both tuples.
len(tuple)
2
Gives the total length of the tuple.
max(tuple)
3
Returns item from the tuple with max value.
min(tuple)
4
Returns item from the tuple with min value.
tuple(seq)
5
Converts a list into tuple.
tup1 = (10,20,30)
x, y = tup1
x, y, p, q = tup1 # ValueError: not enough values to unpack (expected 4,
got 3)
Unpack Tuple Items Using Asterisk (*)
In such a case, the "*" symbol is used for unpacking. Prefix "*" to "y", as
shown below −
tup1 = (10,20,30)
x, *y = tup1
print ("x:",x,"y:",y)
x: 10 y: [20, 30]
The first value in tuple is assigned to "x", and rest of items to "y" which
becomes a list.
Example 2
In this example, the tuple contains 6 values and variables to be unpacked are
3. We prefix "*" to the second variable.
Here, values are unpacked in "x" and "z" first, and then the rest of values are
assigned to "y" as a list.
Example 3
What if we add "*" to the first variable?
Open Compiler
tup1 = (10,20,30, 40, 50, 60)
*x, y, z = tup1
print ("x: ",x, "y: ", y, "z: ", z)
It will produce the following output −
x: [10, 20, 30, 40] y: 50 z: 60
Here again, the tuple is unpacked in such a way that individual variables take
up the value first, leaving the remaining values to the list "x".
T1 = (10,20,30,40)
T2 = ('one', 'two', 'three', 'four')
L1 = list(T1)
L2 = list(T2)
[Link](L2)
T1 = tuple(L1)
print ("Joined Tuple:", T1)
Sets in Python
In Python, a set is an unordered collection of unique elements. Unlike lists or
tuples, sets do not allow duplicate values i.e. each element in a set must be
unique. Sets are mutable, meaning you can add or remove items after a set
has been created.
Sets are defined using curly braces {} or the built-in set() function.
my_set = {1, 2, 3, 4, 5}
print (my_set)
{1, 2, 3, 4, 5}
Duplicate Elements in Set
Sets in Python are unordered collections of unique elements. If you try to
create a set with duplicate elements, duplicates will be automatically
removed −
my_set = {1, 2, 2, 3, 3, 4, 5, 5}
print (my_set)
{1, 2, 3, 4, 5}
Ex- my_set.add(4)
Ex- my_set.update([4])
my_set = {1, 2, 3, 4}
if 2 in my_set:
print("2 is present in the set")
Set Operations
Union − It combine elements from both sets using the union() function
or the | operator.
Intersection − It is used to get common elements using the
intersection() function or the & operator.
Difference − It is used to get elements that are in one set but not the
other using the difference() function or the - operator.
Symmetric Difference − It is used to get elements that are in either
of the sets but not in both using the symmetric_difference() method or
the ^ operator.
Example
In the following example, we are creating a set containing the squares of
numbers from 1 to 5 using a set comprehension −
Frozen Sets
In Python, a frozen set is an immutable collection of unique elements, similar
to a regular set but with the distinction that it cannot be modified after
creation. Once created, the elements within a frozen set cannot be added,
removed, or modified, making it a suitable choice when you need an
immutable set.
my_frozen_set = frozenset([1, 2, 3])
[Link]
Methods with Description
.
[Link]()
1
Add an element to a set.
[Link]()
2
Remove all elements from a set.
[Link]()
3
Return a shallow copy of a set.
[Link]()
4
Remove an element from a set if it is a member.
[Link]()
5
Remove and return an arbitrary set element.
[Link]()
6
Remove an element from a set; it must be a member.
Set Operations
These methods perform set operations such as union, intersection,
difference, and symmetric difference −
[Link]
Methods with Description
.
[Link]()
1
Update a set with the union of itself and others.
set.difference_update()
2
Remove all elements of another set from this set.
[Link]()
3
Returns the intersection of two sets as a new set.
set.intersection_update()
4
Updates a set with the intersection of itself and another.
[Link]()
5
Returns True if two sets have a null intersection.
[Link]()
6
Returns True if another set contains this set.
[Link]()
7
Returns True if this set contains another set.
set.symmetric_difference()
8
Returns the symmetric difference of two sets as a new set.
set.symmetric_difference_update()
9
Update a set with the symmetric difference of itself and another.
10 [Link]()
Returns the union of sets as a new set.
[Link]()
11
Returns the difference of two or more sets as a new set.
Dictionaries in Python
a dictionary is a built-in data type that stores data in key-value pairs. It is an
unordered, mutable, and indexed collection. Each key in a dictionary is
unique and maps to a value
numbers = {10:"Ten", 20:"Twenty", 30:"Thirty",40:"Forty"}
Key Features of Dictionaries
Following are the key features of dictionaries −
Creating a Dictionary
using curly braces
sports_player = {
"Name": "Sachin Tendulkar",
"Age": 48,
"Sport": "Cricket"
}
using the dict() function
student_info = dict(name="Alice", age=21, major="Computer Science")
Accessing Dictionary Items
student_info = {
"name": "Alice",
"age": 21,
"major": "Computer Science"
}
# Accessing values using square brackets
name = student_info["name"]
value = [Link]("key")
popitem() method
dictionary_name.popitem(key)
[Link]
Methods with Description
.
[Link]()
1
Removes all elements of dictionary dict
[Link]()
2
Returns a shallow copy of dictionary dict
[Link]()
3
Create a new dictionary with keys from seq and values set to value.
[Link](key, default=None)
4
For key key, returns value or default if key not in dictionary
dict.has_key(key)
5
Returns true if key in dictionary dict, false otherwise
[Link]()
6
Returns a list of dict's (key, value) tuple pairs
[Link]()
7
Returns list of dictionary dict's keys
[Link](key, default=None)
8 Similar to get(), but will set dict[key]=default if key is not already in
dict
[Link](dict2)
9
Adds dictionary dict2's key-values pairs to dict
[Link]()
10
Returns list of dictionary dict's values
Sr.N
Function with Description
o.
cmp(dict1, dict2)
1
Compares elements of both dict.
len(dict)
2 Gives the total length of the dictionary. This would be equal to the
number of items in the dictionary.
str(dict)
3
Produces a printable string representation of a dictionary
type(variable)
4 Returns the type of the passed variable. If passed variable is dictionary,
then it would return a dictionary type.
Updating Multiple Dictionary Values
person = {'name': 'Alice', 'age': 25, 'city': 'New York'}
# Updating multiple values
[Link]({'age': 26, 'city': 'Los Angeles'})
Copy Dictionaries
1. Shallow Copy
- using the copy() method
original_dict = {"name": "Alice", "age": 25}
shallow_copy = original_dict.copy()
2. Deep Copy
- using the deepcopy() method
original_dict = {"name": "Alice", "age": 25}
deep_copy = [Link](original_dict)
Syntax
import array as array_name
# creating array
obj = array_name.array(typecode[, initializer])
Where,
typeco
Python data type Byte size
de
append(x)
1
Appends a new item with value x to the end of the array.
extend(iterable)
2
Appends items from iterable to the end of the array.
insert(i, x)
3
Inserts a new item with value x before position i.
array_name.pop([i])
4 Removes and returns the item with index i. If i is not specified, removes and returns the
last item.
array_name.remove(item)
5
Removes the first occurrence of item from the array.
Sr.N
Methods with Description
o.
buffer_info()
1 Returns a tuple (address, length) giving the current memory address and the length in
elements of the buffer used to hold the arrays contents.
count(x)
2
Returns the number of occurrences of x in the array.
[Link]
Methods with Description
.
reverse()
1
Reverses the order of the items in the array.
byteswap()
2 "Byteswaps" all items of the array, useful for reading data from a file written on a
machine with a different byte order.
Conversion Methods
These methods are used to convert arrays to and from bytes, files, lists, and
Unicode strings.
[Link]
Methods with Description
.
frombytes(buffer)
1 Appends items from the bytes-like object, interpreting its content as an array of machine
values.
tobytes()
2
Converts the array to a bytes representation.
fromfile(f, n)
3
Reads n items from the file object f and appends them to the array.
tofile(f)
4
Writes all items to the file object f.
fromlist(list)
5
Appends items from the list to the array.
tolist()
6
Converts the array to a list with the same items.
fromunicode(s)
7 Extends the array with data from the given Unicode string. The array must have type
code 'u'.
tounicode()
8
Converts the array to a Unicode string. The array must have type code 'u'.
Using indexing
numericArray = array('i', [111, 211, 311, 411, 511])
print (numericArray[0])
Using iteration
numericArray = [Link]('i', [111, 211, 311, 411, 511])
for i in numericArray:
print(i)
Using array_name.insert(index,item)
a = [Link]('i', [1, 2, 3])
[Link](1,20)
# converting to list
sortedList = [Link]()
print(check(4))
used the built-in int function to convert each string in the list s
into an integer. The map() function takes care of
applying int() to every element
Syntax of the map() function
map(function, iterable)
Parameter:
function: The function we want to apply to every
element of the iterable.
iterable: The iterable whose elements we want to
process.
By default, the map() function returns a map object, which is
an iterator. In many cases, we will need to convert
this iterator to a list/tuple to work with the results directly.
Output
[2, 4, 6, 8]
Explanation:
The map() function returned an iterator, which we then
converted into a list using list(). This is a common
practice when working with map()
We used a custom function to double each value in
the list a. The result was mapped and converted into a
list for easy display.
Output
[2, 4, 6, 8]
Explanation: We used lambda x: x * 2 to double each value in
the list a. The result was mapped and converted into a list for
easy display.
filter() in python
The filter() method filters the given sequence with the help of a
function that tests each element in the sequence to be true or not
Python filter() Syntax
The filter() method in Python has the following syntax:
Syntax: filter(function, sequence)
function: A function that defines the condition to filter
the elements. This function should return True for items
you want to keep and False for those you want to
exclude.
iterable: The iterable you want to filter (e.g., list, tuple,
set).
a = [1, 2, 3, 4, 5, 6]
b = filter(even, a)
print(list(b))
Output
[2, 4, 6]
Here, the lambda function replaces even and directly defines the
condition x % 2 == 0 inline.
Decorators in Python
A decorator is essentially a function that takes another
function as an argument and returns a new function with
enhanced functionality. Decorators modify or extend the
behavior of functions or methods, without changing their
actual code.
This can happen only because python functions are 1st
class citizens.
There are 2 types of decorators available in python
Built in
decorators like @staticmethod, @classmethod, @abstractme
thod, @property etc
User defined decorators that we programmers can create
according to our needs
Syntax of Decorator Parameters
def decorator_name(func):
def wrapper(*args, **kwargs):
# Add functionality before the original function call
result = func(*args, **kwargs)
# Add functionality after the original function call
return result
return wrapper
@decorator_name
def function_to_decorate():
# Original function code
pass
Explanation of Parameters
1. decorator_name(func):
decorator_name: This is the name of the decorator
function.
func: This parameter represents the function being
decorated. When you use a decorator, the decorated
function is passed to this parameter.
2. wrapper(*args, **kwargs):
wrapper: This is a nested function inside the decorator.
It wraps the original function, adding additional
functionality.
*args: This collects any positional arguments passed to
the decorated function into a tuple.
**kwargs: This collects any keyword arguments passed
to the decorated function into a dictionary.
The wrapper function allows the decorator to handle
functions with any number and types of arguments.
3. @decorator_name:
This syntax applies the decorator to
the function_to_decorate function. It is equivalent to
writing function_to_decorate =
decorator_name(function_to_decorate).
Decorator Examples:
# simple example
def my_decorator(func):
def wrapper():
print('***********************')
func()
print('***********************')
return wrapper
def hello():
print('hello')
def display():
print('hello nitish')
a = my_decorator(hello)
a()
b = my_decorator(display)
b()
Output
***********************
hello
***********************
***********************
hello nitish
***********************
Example 2:
def wrapper():
print("Before calling the function.")
func()
print("After calling the function.")
return wrapper
greet()
Output
Before calling the function.
Hello, World!
After calling the function.
Explanation:
decorator takes the greet function as an argument.
It returns a new function (wrapper) that first prints a
message, calls greet() and then prints another message.
The @decorator syntax is a shorthand for greet =
decorator(greet).
Types of Decorators
1. Function Decorators:
The most common type of decorator, which takes a function as
input and returns a new function. The example above
demonstrates this type.
def simple_decorator(func):
def wrapper():
print("Before calling the function.")
func()
print("After calling the function.")
return wrapper
@simple_decorator
def greet():
print("Hello, World!")
greet()
Output
Before calling the function.
Hello, World!
After calling the function.
Explanation:
simple_decorator(func): This decorator takes the
function greet as an argument (func) and returns a new
function (wrapper) that adds some functionality before
and after calling the original function.
@simple_decorator: This is the decorator syntax. It
applies the simple_decorator to the greet function.
Calling greet(): When greet() is called, it doesn't just
execute the original function but first runs the added
behavior from the wrapper function.
import time
def timer(func):
def wrapper(*args):
start = [Link]()
func(*args)
print('time taken by',func.__name__,[Link]()-start,'secs')
return wrapper
@timer
def hello():
print('hello wolrd')
[Link](2)
@timer
def square(num):
[Link](1)
print(num**2)
@timer
def power(a,b):
print(a**b)
hello()
square(2)
power(2,3)
class MyClass:
@method_decorator
def say_hello(self):
print("Hello!")
obj = MyClass()
obj.say_hello()
Output
Before method execution
Hello!
After method execution
Explanation:
method_decorator(func): The decorator takes the
method (say_hello) as an argument (func). It returns a
wrapper function that adds behavior before and after
calling the original method.
wrapper(self, *args, **kwargs): The wrapper must
accept self because it is a method of an instance. self is
the instance of the class and *args and **kwargs allow
for other arguments to be passed if needed.
@method_decorator: This applies the
method_decorator to the say_hello method of MyClass.
Calling obj.say_hello(): The say_hello method is now
wrapped with additional behavior.
3. Class Decorators
Class decorators are used to modify or enhance the behavior of a
class. Like function decorators, class decorators are applied to
the class definition. They work by taking the class as an
argument and returning a modified version of the class.
Example:
def fun(cls):
cls.class_name = cls.__name__
return cls
@fun
class Person:
pass
print(Person.class_name)
Output
Person
Explanation:
add_class_name(cls): This decorator adds a new
attribute, class_name, to the class cls. The value of
class_name is set to the name of the class
(cls.__name__).
@add_class_name: This applies the add_class_name
decorator to the Person class.
Result: When the Person class is defined, the decorator
automatically adds the class_name attribute to it.
print(Person.class_name): Accessing the class_name
attribute that was added by the decorator prints the
name of the class, Person.
@classmethod
def set_raise_amount(cls, amount):
cls.raise_amount = amount
Output
1.1
Explanation:
set_raise_amount is a class method defined with the
@classmethod decorator.
It can modify the class variable raise_amount for the
class Employee and all its instances.
@property
The @property decorator is used to define a method as a
property, which allows you to access it like an attribute. This is
useful for encapsulating the implementation of a method while
still providing a simple interface.
Example:
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@[Link]
def radius(self, value):
if value >= 0:
self._radius = value
else:
raise ValueError("Radius cannot be negative")
@property
def area(self):
return 3.14159 * (self._radius ** 2)
Output
5
78.53975
314.159
Explanation:
radius and area are properties defined with the
@property decorator.
The radius property also has a setter method to allow
modification with validation.
These properties provide a way to access and modify
private attributes while maintaining encapsulation.
class Dog:
sound = "bark"
Output
Buddy
Canine
Explanation:
dog1 = Dog("Buddy", 3): Creates an object of the Dog
class with name as "Buddy" and age as 3.
[Link]: Accesses the instance attribute name of
the dog1 object.
[Link]: Accesses the class attribute species of
the dog1 object.
Self Parameter
self parameter is a reference to the current instance of the class.
It allows us to access the attributes and methods of the object.
class Dog:
def __init__(self, name, age):
[Link] = name
[Link] = age
def bark(self):
print(f"{[Link]} is barking!")
Output
Buddy is barking!
Explanation:
Inside bark(), [Link] accesses the specific dog's name
and prints it.
When we call [Link](), Python automatically passes
dog1 as self, allowing access to its attributes.
__str__ Method
__str__ method in Python allows us to define a custom string
representation of an object. By default, when we print an object
or convert it to a string using str(), Python uses the default
implementation, which returns a string like
<__main__.ClassName object at 0x00000123>.
class Dog:
def __init__(self, name, age):
[Link] = name
[Link] = age
def __str__(self):
return f"{[Link]} is {[Link]} years old." # Correct: Returning a
string
dog1 = Dog("Buddy", 3)
dog2 = Dog("Charlie", 5)
print(dog1)
print(dog2)
Output
Buddy is 3 years old.
Charlie is 5 years old.
Explanation:
__str__ Implementation: Defined as a method in the
Dog class. Uses the self parameter to access the
instance's attributes (name and age).
Readable Output: When print(dog1) is called, Python
automatically uses the __str__ method to get a string
representation of the object. Without __str__, calling
print(dog1) would produce something like <__main__.Dog
object at 0x00000123>.
Class Variables
These are the variables that are shared across all instances of a
class. It is defined at the class level, outside any methods. All
objects of the class share the same value for a class variable
unless explicitly overridden in an object.
Instance Variables
Variables that are unique to each instance (object) of a class.
These are defined within __init__ method or other instance
methods. Each object maintains its own copy of instance
variables, independent of other objects.
Example:
class Dog:
# Class variable
species = "Canine"
# Create objects
dog1 = Dog("Buddy", 3)
dog2 = Dog("Charlie", 5)
Output
Canine
Buddy
Charlie
Max
Feline
Feline
Explanation:
Class Variable (species): Shared by all instances of
the class. Changing [Link] affects all objects, as it's
a property of the class itself.
Instance Variables (name, age): Defined in the
__init__ method. Unique to each instance (e.g.,
[Link] and [Link] are different).
Accessing Variables: Class variables can be accessed
via the class name ([Link]) or an object
([Link]). Instance variables are accessed via the
object ([Link]).
Updating Variables: Changing [Link] affects all
instances. Changing [Link] only affects dog1 and
does not impact dog2.
Output
Maths
Science
Explanation: In this example, self.attr1 and self.attr2 refer to
the attributes of the current object, ensuring that each object
can have its own values for these attributes.
def show(self):
print("Model is", [Link])
print("Color is", [Link])
Output
Model is Audi A4
Color is Blue
Model is Ferrari 488
Color is Green
Explanation: In this example, self allows each instance to retain
its unique attributes, such as model and color and
the show() method displays them.
class sampleclass:
count = 0 # class attribute
def increase(self):
[Link] += 1
print([Link])
Output:
1
2
2
Instance Attributes
Unlike class attributes, instance attributes are not shared by
objects. Every object has its own copy of the instance attribute (In
case of class attributes all object refer to single copy). To list the
attributes of an instance/object, we have two functions:- 1.
class emp:
def __init__(self):
[Link] = 'xyz' # instance attribute
[Link] = 4000 # instance attribute
def show(self):
print([Link])
print([Link])
e1 = emp()
print("Dictionary form :", vars(e1))
print(dir(e1))
Syntax:
# create NameOfOuterClass class
class NameOfOuterClass:
# Constructor method of outer class
def __init__(self):
[Link] = Value
# create Inner class object
[Link] = [Link]()
Example:
First, we create a class and then the constructor of the
class.
After creating a class, we will create another class within
that class, the class inside another class will be called an
inner class.
class Color:
# constructor method
def __init__(self):
# object attributes
[Link] = 'Green'
[Link] = [Link]()
def show(self):
print('Name:', [Link])
# create Inner Lightgreen class
class Lightgreen:
def __init__(self):
[Link] = 'Light Green'
[Link] = '024avc'
def display(self):
print('Name:', [Link])
print('Code:', [Link])
# method calling
[Link]()
# create a Lightgreen
# inner class object
g = [Link]
[Link]()
Output:
Name: Green
Name: Light Green
Code: 024avc
# Accessing attributes
print([Link])
print([Link])
Output
John Doe
25
Explanation:
__init__ method takes two parameters, name and age
and initializes them for each instance.
We then create an instance called a and pass the values
"John Doe" and 25 to the constructor.
We can access the instance's attributes using dot
notation, such as [Link] and [Link].
Explanation:
Animal is a base class with one attribute species.
Dog inherits from Animal and uses super() to set
species as "Dog".
dog object has a name and age along with inherited
species.
def get_bal(self):
return self.__bal
Explanation:
__bal attribute is private, meaning it cannot be accessed
directly from outside the class.
methods deposit(), withdraw() and get_bal() provide
safe access and modification to the balance.
After depositing 200 and withdrawing 150, the final
balance is 550.
Example 1:
class GFG:
employee = True
# Driver Code
e1 = GFG()
e2 = GFG()
[Link] = False
[Link] = "Nikhil"
print([Link])
print([Link])
print([Link])
# this will raise an error as name is a dynamic attribute created only for
the e2 object
print([Link])
Constructors in Python
The method __new__ is the constructor that creates a new
instance of the class while __init__ is the initializer that sets up
the instance's attributes after creation. These methods work
together to manage object creation and initialization.
__new__ in Python
Syntax
class ClassName:
def __new__(cls, *args, **kwargs):
# Custom instance creation logic
instance = super(ClassName, cls).__new__(cls, *args, **kwargs)
return instance
Parameters:
cls : The class itself.
*args : Positional arguments passed to __new__ .
**kwargs : Keyword arguments passed to __new__ .
Return Value:
Must return an instance of the class (cls) or another
class.
If __new__ returns an object of another type, __init__ will
not be called.
Example:
class A:
def __new__(cls):
print("Creating instance")
return super(A, cls).__new__(cls)
def __init__(self):
print("Initializing instance")
A()
Output
Creating instance
Initializing instance
Explanation: __new__ method is called first to create an
instance of class A and then returns the newly created instance.
After that, the __init__ method initializes the instance.
def __init__(self):
print("Initializing instance")
print(A())
Output
Creating instance
None
Explanation: __new__ method does not return an instance of
the class. Since __new__ must return an instance, but it lacks a
return statement, it implicitly returns None.
print(A())
Output
Creating instance
Hello, World!
Explanation : __new__ method should return a new object
of class A, but here it returns the string "Hello, World!". Because
of this, Python does not create an instance of A, so the __init__
method is never called. Instead, print(A()) simply prints "Hello,
World!".
class Geek:
def __new__(cls):
return GeeksforGeeks()
def __init__(self):
print("Inside init")
print(Geek())
Output
GeeksforGeeks Instance
Explanation :__new__ method of Geek returns an instance of
GeeksforGeeks instead of Geek, so the __init__ method is never
called. When print(Geek()) is executed, it prints "GeeksforGeeks
Instance" from the __str__ method of GeeksforGeeks.
__init__ Method
This method initializes the newly created instance and is
commonly used as a constructor in Python. It is called
immediately after the object is created by __new__ method and
is responsible for initializing attributes of the instance.
Syntax:
class ClassName:
def __init__(self, parameters):
[Link] = value
__new__ method:
Responsible for creating a new instance of the class.
Rarely overridden but useful for customizing object
creation and especially in singleton or immutable
objects.
__init__ method:
Called immediately after __new__.
Used to initialize the created object.
Types of Constructors
1. Default Constructor
A default constructor does not take any parameters other
than self. It initializes the object with default attribute values.
class Car:
def __init__(self):
Output
Toyota
Corolla
2. Parameterized Constructor
A parameterized constructor accepts arguments to initialize
the object's attributes with specific values.
class Car:
def __init__(self, make, model, year):
Output
Honda
Civic
2022
Encapsulation in Python
How Encapsulation Works :
Data Hiding: The variables (attributes) are kept private
or protected, meaning they are not accessible directly
from outside the class. Instead, they can only be
accessed or modified through the methods.
Access through Methods: Methods act as the interface
through which external code interacts with the data
stored in the variables. For instance, getters and setters
are common methods used to retrieve and update the
value of a private variable.
Public Members
Public members are accessible from anywhere, both inside and
outside the class. These are the default members in Python.
Example:
class Public:
def __init__(self):
[Link] = "John" # Public attribute
def display_name(self):
print([Link]) # Public method
obj = Public()
obj.display_name() # Accessible
print([Link]) # Accessible
Explanation:
Public Attribute (name): This attribute is declared
without any underscore prefixes. It is accessible from
anywhere, both inside and outside of the class.
Public Method (display_name): This method is also
accessible from any part of the code. It directly accesses
the public attribute and prints its value.
Object (obj): An instance of Public is created, and the
display_name method is called, demonstrating how
public attributes and methods can be accessed directly.
Protected members
Protected members are identified with a single underscore (_).
They are meant to be accessed only within the class or its
subclasses.
Example:
class Protected:
def __init__(self):
self._age = 30 # Protected attribute
class Subclass(Protected):
def display_age(self):
print(self._age) # Accessible in subclass
obj = Subclass()
obj.display_age()
Explanation:
Protected Attribute (_age): This attribute is prefixed
with a single underscore, which by convention, suggests
that it should be treated as a protected member. It's not
enforced by Python but indicates that it should not be
accessed outside of this class and its subclasses.
Subclass: Here, a subclass inherits from Protected.
Within this subclass, we can still access the
protected attribute _age.
Method (display_age): This method within the subclass
accesses the protected attribute and prints its value. This
shows that protected members can be accessed within
the class and its subclasses.
Private members
Private members are identified with a double
underscore (__) and cannot be accessed directly from outside
the class. Python uses name mangling to make private members
inaccessible by renaming them internally.
Note: Python's private and protected members can be accessed
outside the class through python name mangling .
class Private:
def __init__(self):
self.__salary = 50000 # Private attribute
def salary(self):
return self.__salary # Access through public method
obj = Private()
print([Link]()) # Works
#print(obj.__salary) # Raises AttributeError
Explanation:
Private Attribute (__salary): This attribute is prefixed
with two underscores, which makes it a private member.
Python enforces privacy by name mangling, which means
it renames the attribute in a way that makes it hard to
access from outside the class.
Method (salary): This public method provides the only
way to access the private attribute from outside the
class. It safely returns the value of __salary.
Direct Access Attempt: Trying to access the private
attribute directly (obj.__salary) will result in an
AttributeError, showing that direct access is blocked. This
is Python's way of enforcing encapsulation at a language
level.
Inheritance in Python
Syntax
class ParentClass:
# Parent class code here
pass
class ChildClass(ParentClass):
# Child class code here
pass
class Animal:
def __init__(self, name):
def sound(self):
class Dog(Animal):
def sound(self):
# Dog-specific sound
return "Woof!"
# Creating instances
# Animal instance with generic name
a = Animal("Generic Animal")
Output
Generic Animal
Buddy
Woof!
def area(self):
class Circle(Shape):
def __init__(self, color, radius):
def area(self):
# Creating instances
# Shape instance with color 'Red'
s = Shape("Red")
Output
Red
Blue
5
78.5
super() Function
super() function is used to call the parent class’s methods. In
particular, it is commonly used in the child class’s __init__()
method to initialize inherited attributes. This way, the child class
can leverage the functionality of the parent class.
Example:
# Parent Class: Person
class Person:
def __init__(self, name, idnumber):
[Link] = name
[Link] = idnumber
def display(self):
print([Link])
print([Link])
def display(self):
print([Link])
print([Link])
# Constructor
def __init__(self):
[Link] = "Inside Parent"
# Constructor
def __init__(self):
super().__init__() # Call parent constructor
[Link] = "Inside Child"
# Driver's code
obj1 = Parent()
obj2 = Child()
+ __add__(self, other)
- __sub__(self, other)
* __mul__(self, other)
__truediv__(self,
/ other)
__floordiv__(self,
// other)
__mod__(self,
% other)
** __pow__(self, other)
__rshift__(self,
>> other)
__lshift__(self,
<< other)
| __or__(self, other)
^ __xor__(self, other)
print(ob1 + ob2)
print(ob3 + ob4)
Output
3
GeeksFor
Here, We defined the special function "__add__( )" and when
the objects ob1 and ob2 are coded as "ob1 + ob2", the special
function is automatically called as ob1.__add__(ob2) which
simply means that ob1 calls the __add__( ) function with ob2 as
an Argument and It actually means A .__add__(ob1, ob2).
Hence, when the Binary operator is overloaded, the object before
the operator calls the respective function with object after
operator as parameter.
Python super()
Last Updated : 19 Mar, 2025
In Python, the super() function is used to refer to the parent class
or superclass. It allows you to call methods defined in the
superclass from the subclass, enabling you to extend and
customize the functionality inherited from the parent class.
# Constructor
def __init__(self, name, id):
[Link] = name
[Link] = id
class Emp(Person):
def Print(self):
print("Emp class called")
Output :
class Person:
# Constructor
def __init__(self, name, id):
[Link] = name
[Link] = id
class Emp(Person):
def __init__(self, name, id):
self.name_ = name
super().__init__(name, id)
def Print(self):
print("Emp class called")
# Driver Code
Carol = Animal("Dog")
Output :
The class Animal inherits from two-parent classes - canFly and
canSwim. So, the subclass instance Carol can access both of the
parent class constructors using super()
MultipleInheritance
When a class is derived from more than one base class it is
called multiple Inheritance. The derived class inherits all the
features of the base case.
class Class1:
def m(self):
print("In Class1")
class Class2(Class1):
def m(self):
print("In Class2")
super().m()
class Class3(Class1):
def m(self):
print("In Class3")
super().m()
obj = Class4()
obj.m()
Output:
In Class4
In Class2
In Class3
In Class1
Example:
# Python program to demonstrate
# super()
class Class1:
def m(self):
print("In Class1")
class Class2(Class1):
def m(self):
print("In Class2")
super().m()
class Class3(Class1):
def m(self):
print("In Class3")
super().m()
Polymorphism in OOPs
In OOP, polymorphism allows methods in different classes to
share the same name but perform distinct tasks.
Example:
class Shape:
def area(self):
return "Undefined"
class Rectangle(Shape):
def __init__(self, length, width):
[Link] = length
[Link] = width
def area(self):
return [Link] * [Link]
class Circle(Shape):
def __init__(self, radius):
[Link] = radius
def area(self):
return 3.14 * [Link] ** 2
Compile-time Polymorphism
behavior of a function or operator is resolved during the
program's compilation phase.
Examples include method overloading and operator
overloading, where multiple functions or operators can
share the same name but perform different tasks based
on the context.
Runtime Polymorphism
Occurs when the behavior of a method is determined at
runtime based on the type of the object.
In Python, this is achieved through method overriding: a
child class can redefine a method from its parent class to
provide its own specific implementation.
print(res)
add('int', 5, 6)
add('str', 'Hi ', 'Geeks')
Abstract Methods
Abstract methods are methods that are defined in an abstract
class but do not have an implementation. They serve as a
blueprint for the subclasses, ensuring that they provide their own
implementation.
Example:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def make_sound(self):
pass # Abstract method, no implementation here
Abstract Properties
Abstract properties work like abstract methods but are used
for properties. These properties are declared with
the @property decorator and marked as abstract
using @abstractmethod. Subclasses must implement these
properties.
Example:
from abc import ABC, abstractmethod
class Animal(ABC):
@property
@abstractmethod
def species(self):
pass # Abstract property, must be implemented by subclasses
class Dog(Animal):
@property
def species(self):
return "Canine"
# Instantiate the concrete subclass
dog = Dog()
print([Link])
Explanation:
species is an abstract property in the Animal class and it
is marked as @abstractmethod.
The Dog class implements the species property, making
it a concrete subclass that can be instantiated.
Abstract properties enforce that a subclass provides the
property’s implementation.
Python-interface module
Declaring interface
In python, interface is defined using python class statements and
is a subclass of [Link] which is the parent
interface for all interfaces.
Syntax :
class IMyInterface([Link]):
# methods and attributes
Example
import [Link]
class MyInterface([Link]):
x = [Link]("foo")
def method1(self, x):
pass
def method2(self):
pass
# get attribute
x = MyInterface['x']
print(x)
Implementing interface
Syntax :
@[Link](*interfaces)
class Class_name:
# methods
Example
import [Link]
class MyInterface([Link]):
x = [Link]("foo")
def method1(self, x):
pass
def method2(self):
pass
@[Link](MyInterface)
class MyClass:
def method1(self, x):
return x**2
def method2(self):
return "foo"
We declared that MyClass implements MyInterface. This means
that instances of MyClass provide MyInterface.
Methods
implementedBy(class) - returns a boolean value, True
if class implements the interface else False
providedBy(object) - returns a boolean value, True if
object provides the interface else False
providedBy(class) - returns False as class does not
provide interface but implements it
list([Link](class)) - returns
the list of interfaces implemented by a class
list([Link](object)) - returns the
list of interfaces provided by an object.
list([Link](class)) - returns
empty list as class does not provide interface but
implements it.
import [Link]
class MyInterface([Link]):
x = [Link]('foo')
def method1(self, x, y, z):
pass
def method2(self):
pass
@[Link](MyInterface)
class MyClass:
def method1(self, x):
return x**2
def method2(self):
return "foo"
obj = MyClass()
Interface Inheritance
Interfaces can extend other interfaces by listing the other
interfaces as base interfaces.
Functions
import [Link]
class BaseI([Link]):
def m1(self, x):
pass
def m2(self):
pass
class DerivedI(BaseI):
def m3(self, x, y):
pass
@[Link](DerivedI)
class cls:
def m1(self, z):
return z**3
def m2(self):
return 'foo'
def m3(self, x, y):
return x ^ y
classmethod() in Python
The classmethod() is an inbuilt function in Python, which returns a
class method for a given function. This means that classmethod()
is a built-in Python function that transforms a regular method into
a class method. When a method is defined using the
@classmethod decorator (which internally calls classmethod()),
the method is bound to the class and not to an instance of the
class. As a result, the method receives the class (cls) as its first
argument, rather than an instance (self).
classmethod() Syntax
class MyClass:
@classmethod
def class_method(cls, *args, **kwargs):
# Method implementation
Pass
classmethod() Function
In Python, the classmethod() function is used to define a
method that is bound to the class and not the instance of
the class. This means that it can be called on the class itself
rather than on instances of the class.
Class Method vs Static Method
A class method takes class(cls) as the first parameter
while a static method needs no specific parameters.
A class method can access or modify the class state
while a static method can’t access or modify it.
In general, static methods know nothing about the class
state. They are utility-type methods that take some
parameters and work upon those parameters. On the
other hand class methods must have class as a
parameter.
We use @classmethod decorator in Python to create a
class method and we use @staticmethod decorator to
create a static method in Python.
class Geeks:
course = 'DSA'
list_of_instances = []
@classmethod
def get_course(cls):
return f"Course: {[Link]}"
@classmethod
def get_instance_count(cls):
return f"Number of instances: {len(cls.list_of_instances)}"
@staticmethod
def welcome_message():
return "Welcome to Geeks for Geeks!"
# Creating instances
g1 = Geeks('Alice')
g2 = Geeks('Bob')
Output
Course: DSA
Number of instances: 2
Welcome to Geeks for Geeks!
class Student:
# create a variable
name = "Geeksforgeeks"
# create a function
def print_name(obj):
print("The name is : ", [Link])
Student.print_name = classmethod(Student.print_name)
o Instance Method: Takes self as the first
parameter. It is used to access or modify
instance attributes and can call other
instance methods.
o Example:
class MyClass:
def instance_method(self):
return "This is an instance
method"
Class Method:
o Class Method: Takes cls as the first
parameter. It is used to access or modify
class state that applies across all instances.
o Decorated with: @classmethod
o Example:
class MyClass:
@classmethod
def class_method(cls):
return "This is a class method"
def __del__(self):
# body of destructor
# Initializing
def __init__(self):
print('Employee created.')
obj = Employee()
del obj
Output
Employee created.
Destructor called, Employee deleted.
Note : The destructor was called after the program ended or
when all the references to object are deleted i.e when the
reference count becomes zero, not when object went out of
scope.
class Employee:
# Initializing
def __init__(self):
print('Employee created')
# Calling destructor
def __del__(self):
print("Destructor called")
def Create_obj():
print('Making Object...')
obj = Employee()
print('function end...')
return obj
Output
Calling Create_obj() function...
Making Object...
Employee created
function end...
Program End...
Destructor called
Hello!!!
Welcome to TutorialsPoint!!!
file_object.read(size)
Where, size is the number of bytes to read from the file. This
parameter is optional. If omitted or set to a negative value, the method reads
until the end of the file.
print(content)
Hello!!!
Welcome to TutorialsPoint!!!
Hello!!!
Welcome to TutorialsPoint!!!
To write data to a file, use the write() or writelines() methods. When opening
a file in write mode ('w'), the file's existing content is erased.
Example
In this example, we open the file for writing, write data to the file, and then
close the file using the close() method −
Example
In this example, the file is automatically closed at the end of the with block,
so there is no need to call close() method explicitly −
Open Compiler
with open("[Link]", "w") as file:
[Link]("This is an example using the with statement.")
print ("File closed successfully!!")
try:
file = open("[Link]", "w")
[Link]("This is an example with exception handling.")
finally:
[Link]()
print ("File closed successfully!!")
File closed successfully!!
with open('[Link]','r') as f:
[Link]()
# Read the binary data from the file and convert it back to an integer
with open('[Link]', 'rb') as f:
data = [Link]()
n = int.from_bytes(data, 'big')
print(n)
# Open the file in binary write mode and write the packed data
with open('[Link]', 'wb') as f:
[Link](data)
import struct
with open('[Link]','r') as f:
chunk_size = 10
seek()
The seek() function in Python is used to move the file cursor to the
specified location. When we read a file, the cursor starts at the
beginning, but we can move it to a specific position by passing an arbitrary
integer (based on the length of the content in the file) to the seek() function.
We’ve moved the cursor to the 62nd position, which means that if we read
the file, we’ll begin reading after the 62nd character.
Syntax
seek(offset, whence)
Here,
[Link](offset[, whence])
Where,
offset − This is the position of the read/write pointer within the file.
whence − This is optional and defaults to 0 which means absolute file
positioning, other values are 1 which means seek relative to the
current position and 2 means seek relative to the file's end.
Example
The following program demonstrates how to open a file in read-write mode
('w+'), write some data, seek a specific position, and then overwrite part of
the file's content −
If we open the file in read mode (or seek to the starting position while in 'w+'
mode) and read the contents, it will show the following −
If the file is opened for appending using either 'a' or 'a+', any
seek() operations will be undone at the next write.
If the file is opened only for writing in append mode using 'a', this
method is essentially a no-op, but it remains useful for files
opened in append mode with reading enabled (mode 'a+').
If the file is opened in text mode using 't', only offsets returned
by tell() are legal. Use of other offsets causes undefined
behavior.
Note that not all file objects are seekable.
Example
The following example demonstrates how to use the seek() method to
perform simultaneous read/write operations on a file. The file is opened in w+
mode (read-write mode), some data is added, and then the file is read and
modified at a specific position −
Open Compiler
# Open a file in read-write mode
fo = open("[Link]", "w+")
Syntax
[Link]()
[Link](20)
print([Link]())
print([Link]())
[Link]()
Output:
20
When you have to explain it, it’s bad.
Explanation:
seek(20) moves the cursor to character 20.
tell() confirms the cursor is at position 20.
readline() reads from that position onward.
[Link](-10, 2)
print([Link]())
print([Link]().decode('utf-8'))
[Link]()
Output:
47
, its bad.
Explanation:
File is opened in binary mode ('rb').
seek(-10, 2) moves 10 bytes before the end of the file.
readline() reads from that point to the end.
Output is decoded from binary to string.
The process of encoding JSON is usually called serialization. This term refers to
the transformation of data into a series of bytes (hence serial) to be stored or
transmitted across a network. To handle the data flow in a file, the JSON library in
Python uses dump() function to convert the Python objects into their respective
JSON object, so it makes it easy to write data to files. See the following table given
below.
import json
# Data to be written
dictionary = {
"id": "04",
"name": "sunil",
"department": "HR"
}
# Serializing json
json_object = [Link](dictionary, indent = 4)
print(json_object)
Output
{
"id": "04",
"name": "sunil",
"department": "HR"
}
JSON
Python Equivalent
dict object
list,
array
tuple
str string
True true
False false
None null
Method 1: Writing JSON to a file in Python using [Link]()
The JSON package in Python has a function called [Link]() that helps in
converting a dictionary to a JSON object. It takes two parameters:
dictionary: the name of a dictionary which should be converted to a
JSON object.
indent: defines the number of units for indentation
After converting the dictionary to a JSON object, simply write it to a file using the
"write" function.
import json
dictionary = {
"name": "sathiyajith",
"rollno": 56,
"cgpa": 8.6,
"phonenumber": "9976770500"
}
# Serializing json
json_object = [Link](dictionary, indent=4)
# Writing to [Link]
with open("[Link]", "w") as outfile:
[Link](json_object)
Output:
Method 2: Writing JSON to a file in Python using [Link]()
Another way of writing JSON to a file is by using [Link]() method The JSON
package has the "dump" function which directly writes the dictionary to a file in
the form of JSON, without needing to convert it into an actual JSON object. It
takes 2 parameters:
dictionary - the name of a dictionary which should be converted to a
JSON object.
file pointer - pointer of the file opened in write or append mode.
import json
# Data to be written
dictionary = {
"name": "sathiyajith",
"rollno": 56,
"cgpa": 8.6
}
Output:
Deserializing/Decoding JSON:
Reading data from files
Here, we have used the open() function to read the JSON file.
Then, the file is parsed using [Link]() method which gives us a
dictionary named data.
import json
# Closing file
[Link]()
Output:
import json
Output:
Note:
It is worth mentioning here that the JSON object which is
created during serialization is just a Python string, that's
why you'll find the terms "JSON object" and "JSON string"
used interchangeably in this article
Also it is important to note that a JSON object
corresponds to a Dictionary in Python. So when you use
loads method, a Python dictionary is returned by
default (unless you change this behaviour as discussed
in the custom decoding section of this article)
Encoding and Decoding Custom
Objects
Serializing/Encoding Python Objects into
JSON
class Person:
def __init__(self,fname,lname,age,gender):
[Link] = name
[Link] = age
[Link] = gender
# As a string
def show_object(person):
if isinstance(person,Person):
return "{} age -> {} gender ->
{}".format([Link] ,[Link], [Link])
with open('[Link]','w') as f:
[Link](person, f, default=show_object)
# As a dictionary
def show_object(person):
if isinstance(person,Person):
return {'name':[Link] + ' ' +
[Link],'age':[Link],'gender':[Link]}
with open('[Link]','w') as f:
[Link](person, f, default=show_object, indent=4)
Example:
import json
class Student:
def __init__(self, name, roll_no, address):
[Link] = name
self.roll_no = roll_no
[Link] = address
def to_json(self):
'''
convert the instance of this class to json
'''
return [Link](self, indent = 4, default=lambda o:
o.__dict__)
class Address:
def __init__(self, city, street, pin):
[Link] = city
[Link] = street
[Link] = pin
# Encoding
student_json = student.to_json()
print(student_json)
print(type(student_json))
# Decoding
student = [Link](student_json)
print(student)
print(type(student))
Output:
{ "name": "Raju", "roll_no": 53, "address": { "city": "Bulandshahr",
"street": "Adarsh Nagar", "pin": "203001" } } <class 'str'> {'name':
'Raju', 'roll_no': 53, 'address': {'city': 'Bulandshahr', 'street': 'Adarsh
Nagar', 'pin': '203001'}} <class 'dict'>
Example:
import json
from json import JSONEncoder
class Student:
def __init__(self, name, roll_no, address):
[Link] = name
self.roll_no = roll_no
[Link] = address
class Address:
def __init__(self, city, street, pin):
[Link] = city
[Link] = street
[Link] = pin
class EncodeStudent(JSONEncoder):
def default(self, o):
return o.__dict__
# Decoding
student = [Link](student_JSON)
print()
print(student)
print(type(student))
Output:
{ "name": "Raju", "roll_no": 53, "address": { "city": "Bulandshahr",
"street": "Adarsh Nagar", "pin": "203001" } } <class 'str'> {'name':
'Raju', 'roll_no': 53, 'address': {'city': 'Bulandshahr', 'street': 'Adarsh
Nagar', 'pin': '203001'}} <class 'dict'>
import json
from collections import namedtuple
Output:
import json
from collections import namedtuple
Output:
# database
db = {}
db['Omkar'] = Omkar
db['Jagdish'] = Jagdish
# For storing
# type(b) gives <class 'bytes'>;
b = [Link](db)
# For loading
myEntry = [Link](b)
print(myEntry)
Output:
{'Omkar': {'key': 'Omkar', 'name': 'Omkar Pathak', 'age': 21,
'pay': 40000},
'Jagdish': {'key': 'Jagdish', 'name': 'Jagdish Pathak',
'age': 50, 'pay': 50000}}
import pickle
def storeData():
# initializing data to be stored in db
Omkar = {'key' : 'Omkar', 'name' : 'Omkar Pathak',
'age' : 21, 'pay' : 40000}
Jagdish = {'key' : 'Jagdish', 'name' : 'Jagdish Pathak',
'age' : 50, 'pay' : 50000}
# database
db = {}
db['Omkar'] = Omkar
db['Jagdish'] = Jagdish
# source, destination
[Link](db, dbfile)
[Link]()
def loadData():
# for reading also binary mode is important
dbfile = open('examplePickle', 'rb')
db = [Link](dbfile)
for keys in db:
print(keys, '=>', db[keys])
[Link]()
storeData()
loadData()
Output:
Omkar => {'key': 'Omkar', 'name': 'Omkar Pathak', 'age': 21,
'pay': 40000}
Jagdish => {'key': 'Jagdish', 'name': 'Jagdish Pathak',
'age': 50, 'pay': 50000}
import pickle
class ModelTrainer:
def __init__(self) -> None:
[Link] = [0,0,0]
def train(self):
for i in range(len([Link])):
[Link][i] = [Link]()
def get_weights(self):
return [Link]
# Create an object
model = ModelTrainer()
Namespaces
A namespace is a space that holds names(identifiers).Programmatically
speaking, namespaces are dictionary of identifiers(keys) and their
objects(values)
There are 4 types of namespaces:
Builtin Namespace
Global Namespace
Enclosing Namespace
Local Namespace
Scope
A scope is a textual region of a Python program where a namespace is directly
accessible.
LEGB Rule
The interpreter searches for a name from the inside out, looking in the local,
enclosing, global, and finally the built-in scope. If the interpreter doesn’t find the
name in any of these locations, then Python raises a NameError exception.
def temp():
# local var
a = 3
print(a)
temp()
print(a)
output:
3
2
# local and global -> local does not have but global has
a = 2
def temp():
# local var
print(a)
temp()
print(a)
output:
2
2
def temp():
# local var
a += 1
print(a)
temp()
print(a)
a = 2
def temp():
# local var
global a
a += 1
print(a)
temp()
print(a)
output:
3
3
temp()
print(a)
Built-in Scope:
Enclosing scope:
In case of nested functions , the outer function is called
the enclosing scope .
# Enclosing scope
def outer():
def inner():
print(a)
inner()
print('outer function')
outer()
print('main program')
Iterables
Iterables are objects that can return an iterator. These include
built-in data structures like lists, dictionaries, and sets.
Essentially, an iterable is anything you can loop over using a for
loop. An iterable implements the __iter__() method, which is
expected to return an iterator object.
Iterators are the objects that actually perform the iteration.
Iterators
Iterators are the objects that actually perform the iteration. An
iterator holds a sequence of values and provide sequential
traversal through a collection of items such as lists, tuples and
dictionaries. . The Python iterators object is initialized using
the iter() method. It uses the next() method for iteration.
1. __iter__(): __iter__() method initializes and returns the
iterator object itself.
2. __next__(): the __next__() method retrieves the next
available item, throwing a StopIteration exception when
no more items are available.
print(next(it))
print(next(it))
print(next(it))
Output
G
F
G
What is an Iteration
Iteration is a general term for taking each item of something, one after
another. Any time you use a loop, explicit or implicit, to go over a group of
items, that is iteration.
num = [1,2,3]
for i in num:
print(i)
What is Iterator
An Iterator is an object that allows the programmer to traverse through a
sequence of data without having to store the entire data in the memory
What is Iterable
Iterable is an object, which one can iterate over. It generates an Iterator
when passed to iter() method.
L = [1,2,3]
type(L) # L is an iterable
type(iter(L)) # iter(L) --> iterator
Point to remember
Every Iterator is also and Iterable
Not all Iterables are Iterators
StopIteration Exception
The StopIteration exception is integrated with Python’s iterator
protocol. It signals that the iterator has no more items to return.
Once this exception is raised, further calls to next() on the same
iterator will continue raising StopIteration.
Example:
li = [100, 200, 300]
it = iter(li)
Output
100
200
300
End of iteration
In this example, the StopIteration exception is manually handled
in the while loop, allowing for custom handling when the iterator
is exhausted.
Creating a custom iterator
Creating a custom iterator in Python involves defining a class
that implements the __iter__() and __next__() methods according
to the Python iterator protocol.
Define the Class: Start by defining a class that will act
as the iterator.
Initialize Attributes: In the __init__() method of the
class, initialize any required attributes that will be used
throughout the iteration process.
Implement __iter__(): This method should return the
iterator object itself. This is usually as simple as
returning self.
Implement __next__(): This method should provide the
next item in the sequence each time it's called.
class EvenNumbers:
def __iter__(self):
self.n = 2 # Start from the first even number
return self
def __next__(self):
x = self.n
self.n += 2 # Increment by 2 to get the next even number
return x
Output
2
4
6
Explanation:
Initialization: The __iter__() method initializes the
iterator at 2, the first even number.
Iteration: The __next__() method retrieves the current
number and then increases it by 2, ensuring the next call
returns the subsequent even number.
Usage: We create an instance of EvenNumbers, turn it
into an iterator and then use the next() function to fetch
even numbers one at a time.
for x in some_iterable:
print(x)
_iterator = iter(some_iterable)
while True:
try:
x = next(_iterator)
print(x)
except StopIteration:
break
def mera_khudka_for_loop(iterable):
iterator = iter(iterable)
while True:
try:
print(next(iterator))
except StopIteration:
break
a = [1,2,3]
b = (1,2,3)
mera_khudka_for_loop(a)
1
2
3
class range:
def __init__(self, start, stop):
[Link] = start
[Link] = stop
def __iter__(self):
return range_Iterator([Link], [Link])
class range_Iterator:
def __init__(self, start, stop):
[Link] = start
[Link] = stop
def __next__(self):
if [Link] >= [Link]:
raise StopIteration
val = [Link]
[Link] += 1
return val
Now:
for num in range(0, 3):
print(num)
Boom — prints 0, 1, 2
def __init__(self,start,end):
[Link] = start
[Link] = end
def __iter__(self):
return mera_range_iterator(self)
def __init__(self,iterable_obj):
[Link] = iterable_obj
def __iter__(self):
return self
def __next__(self):
current = [Link]
[Link]+=1
return current
x = mera_range(1,11)
type(x)
iter(x)
# initializing list 1
li1 = [1, 4, 5, 7]
# initializing list 2
li2 = [1, 6, 5, 9]
# initializing list 3
li3 = [8, 10, 5, 4]
# using accumulate()
# prints the successive summation of elements
print ("The sum after each iteration is : ",end="")
print (list([Link](li1)))
# using accumulate()
# prints the successive multiplication of elements
print ("The product after each iteration is : ",end="")
print (list([Link](li1,[Link])))
# initializing list 1
li1 = [1, 4, 5, 7]
# initializing list 2
li2 = [1, 6, 5, 9]
# initializing list 3
li3 = [8, 10, 5, 4]
# initializing list
li = [2, 4, 5, 7, 8]
iter_a = iter(a)
print(next(iter_a))
print(next(iter_a))
print(next(iter_a))
print(next(iter_a))
print(next(iter_a))
Output
a
e
i
o
u
Explanation: List a is converted into an
iterator iter_a and next() retrieves each element sequentially.
Once exhausted, further calls to next(iter_a) raise
a StopIteration exception.
Python __iter__()
The __iter__() function in Python returns an iterator for the given
object (e.g., array, set, tuple, or a custom object). It creates an
object that can be accessed one element at a time using
__next__(). This is particularly useful when dealing with loops.
Syntax:
iter(object)
iter(callable, sentinel)
object: The object whose iterator is created. It can be a collection
like a list or a user-defined object.
callable, sentinel:
callable: A function that generates values dynamically.
sentinel: The value at which iteration stops.
Example: Using iter(callable,sentinel)
import random
rand_iter = iter(lambda: [Link](1, 10), 5) # Stops when 5 is
generated
Output
8
7
1
1
7
9
Explanation: This code creates an iterator that generates
random numbers from 1 to 10, stopping when 5 appears. The for
loop prints numbers until 5 is encountered, making the output
vary each run.
Python __next__()
The __next__() function in Python returns the next element of an
iteration. If there are no more elements, it raises
the StopIteration exception. It is part of the iterable and
iterator interface, which allows us to create custom iterable
objects, such as generators, and control how elements are
retrieved one at a time.
Example 1. Using __next__() in loop
a = [11, 22, 33, 44, 55]
iter_a = iter(a)
while True:
try:
print(iter_a.__next__())
except StopIteration:
break
Output
11
22
33
44
55
Explanation: List a is converted into an iterator iter_a and a
while True loop is used to retrieve elements using __next__().
A try-except block handles StopIteration, ensuring iteration stops
gracefully when the iterator is exhausted.
Example 2. Exception handling
a = ['Cat', 'Bat', 'Sat', 'Mat']
iter_a = iter(a)
try:
print(iter_a.__next__())
print(iter_a.__next__())
print(iter_a.__next__())
print(iter_a.__next__())
print(iter_a.__next__()) # Raises StopIteration error
except StopIteration:
print("\nThrowing 'StopIterationError': Cannot iterate further.")
Output
Cat
Bat
Sat
Mat
Throwing 'StopIterationError': Cannot iterate further.
Explanation: List a is converted into an
iterator iter_a and__next__() retrieves elements sequentially.
When exhausted, StopIteration is caught, displaying a custom
message.
Using __iter__() and __next__() in user-defined objects
We can implement the iterator protocol in user-defined classes by
defining __iter__() and __next__() methods.
The __iter__() method should return the iterator object
and __next__() should return the next element in the sequence.
Example:
class Counter:
def __init__(self, start, end):
[Link] = start
[Link] = end
def __iter__(self):
return self
def __next__(self):
if [Link] > [Link]:
raise StopIteration
else:
[Link] += 1
return [Link] - 1
# Driver code
if __name__ == '__main__':
a, b = 2, 5
c1 = Counter(a, b)
c2 = Counter(a, b)
# Using iter()
obj = iter(c2)
try:
while True: # Iterate until StopIteration is raised
print("Counting:", next(obj))
except StopIteration:
print("\nIteration completed.")
Output
Print the range without iter():
Counting: 2
Counting: 3
Counting: 4
Counting: 5
Iteration completed.
Explanation: The Counter class iterates from start to end,
with __iter__() returning itself and __next__() incrementing
until StopIteration. The first loop iterates over c1, while the
second uses iter(c2) and next(obj), handling exhaustion
gracefully.
WHY USE ITERATORS ??
L = [x for x in range(100000)]
This creates a list — it stores all 100,000 numbers in memory at once.
x = range(10000000)
This creates a range object — which acts like an iterator factory, but doesn't store all
the numbers.
You're asking:
“How much memory do these two objects actually take up?”
x = range(10000000)
This doesn't store 10 million numbers! It’s an iterable that creates numbers on demand,
only when you need them instead of storing them all at once. It just stores: start (default is
0), stop (10,000,000), step (default is 1)
def fun(max):
cnt = 1
while cnt <= max:
yield cnt
cnt += 1
ctr = fun(5)
for n in ctr:
print(n)
Output
1
2
3
4
5
Explanation: This generator function fun yields numbers from 1
up to a specified max. Each call to next() on the generator
object resumes execution right after the yield statement,
where it last left off.
Instead of doing:
def square(num):
result = []
for i in range(1, num+1):
[Link](i**2)
return result
You write:
def square(num):
for i in range(1, num+1):
yield i**2
The yield turns this from a boring ol' function into a generator function.
It just returns a generator object: something that’s ready to produce values, but hasn’t started
yet.
Now,
print(next(gen))
Then again:
print(next(gen)) # 4
print(next(gen)) # 9
Then we do:
for i in gen:
print(i)
1
4
9
16
25
36
49
64
81
100
But only because the for loop picked up after the first 3 values were already consumed.
It has yield
It returns a lazy iterator — no list stored in memory
It supports next() and can be used in a for loop
Let’s compare:
😵 Manual iterator (without using generators):
class Square:
def __init__(self, num):
[Link] = num
[Link] = 1
def __iter__(self):
return self
def __next__(self):
if [Link] > [Link]:
raise StopIteration
val = [Link] ** 2
[Link] += 1
return val
😎 Generator version:
def square(num):
for i in range(1, num+1):
yield i**2
def __init__(self,start,end):
[Link] = start
[Link] = end
def __iter__(self):
return mera_range_iterator(self)
def __init__(self,iterable_obj):
[Link] = iterable_obj
def __iter__(self):
return self
def __next__(self):
x = mera_range(1,11)
iter(x)
for i in mera_range(15,26):
print(i)
Syntax:
(expression for item in iterable)
Example:
4. Chaining Generators
def fibonacci_numbers(nums):
x, y = 0, 1
for _ in range(nums):
x, y = y, x+y
yield x
def square(nums):
for num in nums:
yield num**2
print(sum(square(fibonacci_numbers(10))))