Thursday, April 24, 2025

Dictionaries

 Dictionary: A data type built into Python


The dictionary is a compound data type in Python. Its basic items (elements) are key-value pairs. The key must be of an immutable data type (string, tuple, or number), and the value may be of any type, including lists and dictionaries.  Some examples are as values

dict1 = {'Python': 'data science', 'Java': 'enterprise level', 'C++': 'system level'}

In this example, Python, Java and C++ are keys, and their corresponding values are 'data science', 'enterprise level', and 'system level.

The values in a dictionary are accessed using keys. Some examples with outputs (commented text) are as follows.

print(dict1['Python'])            # prints data science
print(dict1['Java'])                # prints enterprise level
print(dict1['C++'])                # prints system level

Keys in the dictionary are unique and adding a new item with the same key eliminates the earlier value. For example, updating the dict1 with an existing key but a different value yields the following result.

dict1['Python'] = 'scientific'
print(dict1)                   # prints {'Python': 'scientific', 'Java': 'enterprise level', 'C++': 'system level'}

This also shows that dictionaries are a mutable type. New items are added to the existing dictionary as follows.

dict1['C'] = 'system level'
print(dict1)    #{'Python': 'scientific', 'Java': 'enterprise level', 'C++': 'system level', 'C': 'system level'}

This also shows that added items appear at the end of the dictionary and different keys can have the same value. Searching for a non-existent key results in an error.

print(dict1['R'])           # Python interpreter throws KeyError 

An empty dictionary can be created using empty braces as follows.

dict2 = {}

The key-value pairs can be added dynamically to the existing dictionary.

in and not in operators with dictionary

The in and not in operators are useful to find whether a particular key exists in the dictionary or not. The following code snippet shows the usage of these to operators. 

dict1 = {'Python': 'data science', 'Java': 'enterprise level', 'C++': 'system level'}
if 'Python' in dict1:
    print("Key  'Python' exists in dict1")            # True
else:
    print("Key  'Python' does not exist in dict1")
    
Similarly,
'R' not in dict1        # results in True
'R' in dict1        # results in False
It results in True and False.

Alternate ways of creating  dictionaries

The dict() constructors (based on oop concept) are used to create the dictionary as follows.

dict_new =  dict([('Python', 'data science'), ('Java', 'enterprise level'), ('C++', 'system level')])

By carefully observing, you can see that dict is similar to a function, and the argument is a list of tuples. If the keys are simple strings, the following simple way can be used to create new dicitonary.

dict_new =  dict(Python = 'data science', Java =  'enterprise level', C  =  'system level')

Observe that keys are without quotes, whereas values are within quotes. The ++ with C and = gives a syntax error and hence changed to 'C'.

Nested dictionary

It is possible to have a dictionary as a value for a key. The following code snippet shows the same and also accessing the nested dictionary values using keys.

nest_dict = {
    "student1": {"name": "Steve", "age": 19},
    "student2": {"name": "Peter", "age": 20}
}
stu_detail = nest_dict['student1']          # access the entire record of the student1 (inner dictionary)
print(stu_detail)
age_student1 = nest_dict["student1"]["age"]        # access the age of the student2 
print(age_student1)   # Output: 19

The dictionaries can be nested to any number of levels.


Some methods of the dictionary type

Extract keys: The method keys() is useful to extract only keys from the dictionary.  It is as follows.

dict1 = {'Python': 'data science', 'Java': 'enterprise level', 'C++': 'system level'}

list_type = dict1.keys()  # returns dict_keys(['Python', 'Java', 'C++'])

Similarly, values of the dictionary can be extracted as follows.

Extract values: The method values() is useful to extract only values from the list. The following code lines illustrated the same.

dict1 = {'Python': 'data science', 'Java': 'enterprise level', 'C++': 'system level'}
list_type = dict1.values()  # returns dict_values(['scientific', 'enterprise level', 'system level'])

Extract items: The method items() extracts the items (key-value pair) as illustrated in the following code lines.

dict1 = {'Python': 'data science', 'Java': 'enterprise level', 'C++': 'system level'}
list_type = dict1.items()  

The output is as follows.
dict_items([('Python', 'scientific'), ('Java', 'enterprise level'), ('C++', 'system level')])

Dictionary to list conversion: The dictionary can be converted into a list using list() with a dictionary as an argument. The list consists of only keys. 

dict1 = {'Python': 'data science', 'Java': 'enterprise level', 'C++': 'system level'}
lt = list(dict1)   #   The list is  ['Python', 'Java', 'C++'] 
If you want sorted keys (requirement in many situations), use the sorted() function on the created list

lt = sorted(lt)            # the sorted list is ['C++', 'Java', 'Python']

Observe that sorted is a general function in Python for sorting in ascending or descending order.

Deleting an item from the dictionary: The general del statement of Python is used to delete the key-value pair or the entire dictionary.

del dict1['C++']         # deletes the key value pair 'C++': 'system level'
print(dict1)                # prints  {'Python': 'scientific', 'Java': 'enterprise level'}

del dict1                    # deletes the entire dictionary
print(dict1)                # results in NameError

Avoid error using the get() method: While fetching the value for a key that does not exist, the interpreter ends the running of your script with an error. To avoid this and continue running the script, use the following get() method to access the value of the key.

dict1 = {'Python': 'data science', 'Java': 'enterprise level', 'C++': 'system level'}
print(dict1.get('R', 'different'))

The key 'R' does not exist, the get() method returns the second argument ('different'). 

Adding key-value pair using the setdefault() method: This method is useful to add new key-value pairs to the existing dictionary.  But, if the key already exists in the dictionary, the method returns the value of that key. The following code illustrates the same.

dict1 = {'Python': 'data science', 'Java': 'enterprise level', 'C++': 'system level'}
dict1.setdefault('Matlab', ''prototype')
print(dict1)  

The dictionary dict1 is now,
{'Python': 'data science', 'Java': 'enterprise level', 'C++': 'system level', 'Matlab': 'prototype'}

Now, let us try to add the existing key to the dict1.

dict1.setdefault('Python', ''prototype')        # returns 'data science'

This method is useful to retain already existing key-value pairs.

Lists Vs Dictionaries

Feature List Dictionary
Definition            An ordered collection of items Collection of key–value pairs
Syntax       lt = [1, 2, 3] dict = {"a": 1, "b": 2}

Indexing

            by position; lt[0] 

By key; dict['a']

Order 

            Preserves insertion order

Preserves insertion order

Duplicates
            
            Allows duplicate values

Keys must be unique (values can duplicate)

Mutability
            
            Mutable (can change items)

Mutable (can change values, add/remove pairs)

Use case
            
            When order matters, 

When data is paired (label & value)






Wednesday, April 23, 2025

Strings

 Strings 


String is treated as a basic data type in Python. The string value is always enclosed within (single/double/triple) quotes. 

>>> var = "python"        # var = 'python'
>>> type(var)
<class 'str'>

The type function shows that the variable var is of type (class) str. 

The indexing and slicing in strings is as follows. 

Indexing

The forward as well as backward (reverse) indexing is possible with strings. The forward indesing is as follows. The index starts with zero, for example

>>> var = "python"        # var = 'python'
>>> var[0]
p
>>> var[5]
n

                           p        y        t        h        o        n
forward index     0        1        2        3        4        5
reverse index    -6       -5      -4       -3       -2      -1                                

The reverse/backward indexing starts with the index -1. For example,

>>> var[-1]
n
>>> var[-6]
p

Referring to any out-of-index of any string is a syntax error named as IndexError. For example, the following referencing of the string var results in an IndexError

>>> var[-7]                # results in IndexError
>>> var[6]                    # results in IndexError

The IndexError can be handled using try-except block.

var = 'python'
try:                
    print(var[6])                # out of index reference
except IndexError:
    print("error occured")        # error handling code

print("continued execution...")        # continue running application

The error IndexError is handled by the code within except block.

string slices

The slice of strings can be fetched as follows.

>>> var = 'python'
>>> var[0:3]                # from index 0 to 2
'pyt'
>>> var[2:]                 # from index 2 to end
'thon'
>>> var[:4]                # from index 0 to 3
'pyth'
>>> var[:]                  # entire string
'python'

String slices can also be obtained using reverse indexing. Some examples are as follows.

>>> var[-1:-4]            # This is not the way to get a substring 
''
>>> var[-6:-3]            # Yes. This is the way. start=-6, end=-3-1=-4
'pyt'

>>> var[:-2]                # from the start of the string to (-2-1 = -3)
'pyth'

>>> var[-2:]                # from -2 to the end of the string
'on'

String slice can also be using the combination of positive and negative indexing. Some examples are as follows.
>>> var[-10:-3]            # substring is from -6 to -4
'pyt'

>>> var[5:10]                # last character index is 5 and up to 10 nothing
'n'

>>> var[-6:4]                # start = -6 and stop = 4-1=3
'pyth'

>>> var[0:-1]                  # start=0 and stop=-1-1=-2
'pytho'        

Out-of-index in slices: Out-of-indexing in slices always results in an empty string. Some examples are as follows.
>>> var[-14:-7]                # start = -14, stop = -7-1=-8
''
>>> var[8:10]
''

Finding a substring in strings ( in and not in)

 The in and not in operators are useful to verify the existence of substrings in strings. The following examples illustrate the same.

>>> var = "Python Programming Language"
>>> "Python" in var                        # substrin 'Python' present in var
True
>>> 'python' in var                         # substring 'python' not present (lower case p)
False

Same thing can be achieved using not in operator

>>> var = "Python Programming Language"
>>> "Python" not in var                        # substring 'Python' present in var
False
>>> 'python' not in var                         # substring 'python' not present (lower case p) in var
True
  
Similarly
>>> 'Py' in 'Python'
True
>>> 'Jy' not in 'Python'
True

Strings with single, double and triple quotes

Double quote strings are useful to include single quotes as part of the string and vice versa. The following examples illustrate the same.

>>> var = "string's"                    # single quote is part of the string 
>>> var
"string's"
>>> var = 'string "and" str'            # double quote is part of the string
>>> var
'string "and" str'
  
The escape sequence is another way to use quotes as a part of the string. Some of the escape sequences are as follows. 
_____________________________
Escape character           print as 
_____________________________
\'                                        '
\"                                       "
\\                                        \
\t                                        tab
\n                                       newline
____________________________

Some examples using escape sequence is as follows
>>> var = 'string\'s'                # \' is replaced by '
>>> var
'string's

>> var = "string \"and\" string"                # \" is replaced by "
>>> var
string "and" string

Triple quotes are used to enclose the string of multiple lines with some text format. The following example illustrates the same.

>>> var = """ Subject                marks
                        C                          45
                        Java                      55
                        Python                  65
"""
>>> print(var)
""" Subject                marks
       C                          45
       Java                      55
       Python                  65
"""
The triple quote strings are also used as multi-line comments in Python programs.

Strings are immutable

Strings, once created, cannot be modified. They are immutable in nature. For example

>>> var = "Python'
>>> var[0] = 'J'        # results in TypeError

String (type str) objects do not support item assignment. But, it is possible to create new strings from existing strings. For example, 

>>> new_var = 'J' + var[1:]            # 'J' + 'ython' = 'Jython'
>>> new_var
'Jython'

New string named as new_var is created using the existing string var.

String methods

There are a handful of methods available to analyze strings and to create new stings, substrings, and slices from the existing strings. Remember that the strings immutable, once created cannot be modified. Let us study them.

Methods for case conversion and verification in strings

The methods for case conversion and verfications are as follows.
lower(): This method coverts the alphbets of the string into lower case.
>>> var = 'PYTHON'
>>> var.lower()                    # var string is converted into lowercase 
'python'
>>> var                                # remember that the strings are immutable
'PYTHON'

The preceding code shows that the the string value of the variable var is not changed. If the changed value is need for further reference, assgin the converted string into another string variable. This is as shown here.

>>> new_var = var.lower()
>>> new_var
'python'

This is also possible to assign the newly created (converted into lower case) string to the same string variable. 

>>> var = var.lower()            # new string is assigned to var
>>> var
'python'

Similarly, the upper() method in strings also works.

upper(): This method converts the string into uppercase. It is used as follows.

>>> 'java'.upper()
'JAVA'
>>> var = 'c++'
>>> var.upper()
'C++'

isupper() and islower(): These two methods are useful to verify the case of the strings. The following code snippet illustrate the same.

>>> 'python123'.islower()            # all alphabets are lowercase
True
>>> 'Python'.islower()                # 'P' is uppercase
False

Similarly, the isupper() function also used to verify the case of strings.

>>> 'JAVA'.isupper()            # all alphabets are in uppercase
True
>>> var = 'Java'
>>> var.isupper()            # there are lower case alphabets in var
False

All these methods return string. These methods can be called in chain as shown next.

>>> var ='python'
>>> var.upper().lower().upper()    # 'python -> 'PYTHON'  -> 'python' ->  'PYTHON'

The evaluation is from left to right. The result of the last method (right extreme) is returned.

Methods in the String class to verify alphanumeric in string objects

There are also methods available to verify the string to observe the numeric digits. They are as follows.

isalpha()            # is a string that contains only letters (a-z, A-Z)
isalnum()          # is a string value that is alphanumeric
isdecimal()        # is string value is decimal
isspace()            # is a string that contains only spaces
istitle()               # is the string obeys the upper and lower case rules for titles

>>> 'pYthon'.isalpha()            # only letters
True
>>> 'pyTHon123'.isalnum()        # letters and numbers
True
>>> '12321'.isdecimal()            # only numbers
True
>>>'44.53'.isdecimal()            # only digits allowed
False
>>> 'Python Programming Language'.istitle()    # First letter of each word is uppercase 
True

String beginning (startswith()) and ending (endswith())

The startswith() and endswith() functions of the String class are used to verify whether the string object starts and ends with a particular substring respectively. The following code lines illustrate these two functions.

>>> var = 'Hello world'
>>> var.startswith('hello')
True
>>> var.endswith('world')
True

Also
>>> 'Python'.startswith('Python')
True
>>> 'Python'.endswith('Python')
True
>>> 'Python'.endswith('ho')
False

List to string conversion (join()) and string to list conversation (split())

The following code lines help you to understand the conversion from string to list elements.

>>> var = 'Python Programming Language'
>>> lt = var.split()
>>> print(lt)
['Python', 'Programming', 'Language']

By default, the split is based on white space. The coder can specify the split basis as an argument of the split function. In the following example, the split basis is the newline character.
>>> var = '''Python                            # multiline string
Programming
Language'''
>>> lt = var.split('\n')
>> print(lt)
['Python', 'Programming', 'Language']

The opposite is conversion from a list to a string using the function join(). The following example illustrates the same. 

>>> lt = ['Java', 'Programming', 'Language']
>>> string_obj = '\n'.join(lt)
>>>print(string_obj)
Java
Programming
Language
The elements of the strings can be joined using a blank space as follows.
>>> string_obj = ' '.join(lt)
>>> print(string_obj)
Java Programming Language

Formatting string contents using ljust(), rjust() and center() functions

String class has some functions for formatting the string content. These functions are useful to display the results with improved aesthetic. 

ljust() -> This function is used to justify the content to the left.
rjust() -> This function is used to justify the content to the right.
center() -> This function is used to center the content of the string

The following examples illustrate the same.
>>> var = 'Python'
>>> var.ljust(10)                # left justify, remaining 4 characters are blank to the right
'Python    '
>>> var.rjust(10)                # right justify, remaining 4 characters are blank to the left
'    Python'
>>> var.center(10)            # center content; 2 characters are blank on both sides
'  Python  '
>>> var.center(10, *)        # can fill blank space with specific character    
'**Python**'

Functions to remove white space from strings

The following String class functions are useful to remove the whitespace from strings.

lstrip() -> removes left-side whitespace of the strings
rstrip() -> removes right-side whitespace of the strings
strip() -> removes both sides whitespace of the strings

The following code lines illustrate the same.
>>> var = '     Python     '
>>> var.lstrip()
'Python     '
>>> var.rstrip()
'     Python'
>>> var.strip()
'Python'
This is much beyond simple striping. Both side striping characters can be passed as an argument

>>> 'string'.lstrip('st')
'ring'
>>> 'python'.rstrip('on')
'pyth'
>>> 'python'.strip('pyon')        # strips 'py' from left and 'on' from right side
'th'
>>> var = 'StringstringString'
>>> var.strip('Stgn')
'ringstringStri'

Copy and paste through clipboard of computer

The Python module referred to as pyperclip has copy and paste functions to use the clipboard of the computer. You can copy the string from one place to the clipboard and paste it into another place using these functions. The following code line illustrates the same.

>>> import pyperclip
>>> pyperclip.copy('Python Programming Language')  # copied to the clipboard
>>> pyperclip.paste()                # pasted onto the screen
'Python Programming Language'


















Tuesday, April 22, 2025

Reading from and writing into files

 

Files and file paths

The programs/applications need to perform various operations on files existing in the computer systems. It is the operating system that connects your programs to the file system. The program writer/application developer can use the os package in Python for this purpose.  The os package has many functions and subpackages, which are illustrated in this section.

Some os package functions

The following os functions are useful to move around the file system of the computer system. 

getcwd(), chdir() and makedir() functions

The getcwd() is used to find the current working directory, whereas chdir() is used to change the directory from current to the specified directory. The following code lines illustrate the same

import os
current_dir = os.getcwd()    # returns the current working directory as str 
print(current_dir)

os.chdir('C:\\windows\\my_dir')        # change directory
print(os.getcwd())            # prints C:\\windows\\my_dir

But Python throws FileNotFoundError if you try to change the cwd to a directory that does not exist in your system. The following code lines show how the makedirs() function is used to create a directory in the file system of your computer system.

os.makedirs('C:\\Users\\hp\\Desktop\\Create_dir')

Look at your desktop for the newly created directory.

File path

The file path is the address of the file in the computer's file system. There are two ways of specefiyin the path of the file: absolute path and relative path

Absolute path: The Absolute path specifies the complete route for any file starting from the root directory (which may be C:\\ \ or D:\\ \ in windows)
For example, C:\\windows\\my_dir\\my_file.py
Relative path: The absolute path is the path of the file relative to the current working directory. It uses a dot (.) to represent the current directory and double dots (..) to represent the parent directory of the current working directory. Consider the following scenario to understand the relative path.

The cwd is C:\\windows\\my_folder.
The folder has my_file.py

Now the relative path for 
--    the file my_file.py is                        .\my_file.py
--    the cwd my_folder is                        .\
--    parent directory windows is              ..\

There are plenty of functions in os package to establish an interface with the operating system. Consult Python documentation if necessary.

os.path module

This module has functions for relative path, absolute path, to compute file size, and aggregating file sizes, listing directory contents, etc.
abspath() and isabs() functions: The abspath() function returns the absolute path for its argument of relative path. Both argument and return type are str. 

import os.path
abs_path = os.path.abspath('.')        # dot represents cwd (assume cwd is my_folder)
print(abs_path)                        #  prints C:\\windows\\users\my_folder

os.path.isabs('.')                                # returns False; 
os.path.isabs(abs_path)                    # returns True

The function os.path.isabs()  function verifies whether its argument is an absolute path of str type. If yes, returns True.

The os.path.relpath() returns the relative path of its absolute argument.

os.path.relpath('C:\\Users\\hp\\Desktop\\Create_dir')

The above code line returns its relative path as '.\' if the current directory is Create_dir. 
The above code line returns its relative path as  '.\Create_dir' if the cwd is Desktop.

basename(), split() and dirname() functions: The basename() function returns the filename of the absolute path argument (str), whereas the dirname() returns the directory name (absolute path) of its absolute path argument. The split() function returns a tuple of the directory name and filename. The following code line illustrates the same.

>>> import os.path
>>> file = os.path.basename('C:\\Users\\hp\\Desktop\\Create_dir\\sample.py')  
'sample.py'                                                                                    # file name
>>> dir = os.path.dirname('C:\\Users\\hp\\Desktop\\Create_dir\\sample.py') 
'C:\\Users\\hp\\Desktop\\Create_dir                # directory and its path
>>> both = os.path.split('C:\\Users\\hp\\Desktop\\Create_dir\\sample.py')
('C:\\Users\\hp\\Desktop\\Create_dir', 'sample.py)        # tuple

Next, you can learn about finding the file size and directory contents.

getsize() and listdir() functions: The os.path.getsize() function returns the size of the file (passed as an argument) in bytes. The listdir() function returns a list of files and subdirectories in the directory passed as an argument. The following code lines illustrate the same.
import os
print(os.path.getsize('C:\\Users\\hp\\Desktop\\PythonScripts'))
print(os.path.getsize('C:\\Users\\hp\\Desktop\\PythonScripts\prettypython.py'))
print(os.listdir('C:\\Users\\hp\\Desktop\\PythonScripts'))

Observe the getsize() and listdir() functions inside the print functions. They display the following on the screen
4096                # size of entire directory (aggregate of all file sizes) in bytes
575                    # size of prettypython.py file in bytes
['autoML_decision trees.zip',  'New folder', 'new.pdf', prettypython.py]

Checking the existence (validity) of files and directories: The functions exists(), isdir(), and isfile() in os.path are used to check the existence of files and directories in your computer system.

print(os.path.exists('C:\\Users\\hp\\Desktop\\PythonScripts'))
print(os.path.isdir('C:\\Users\\hp\\Desktop\\PythonScripts'))
print(os.path.isfile('C:\\Users\\hp\\Desktop\\PythonScripts'))

Observe the functions inside the print function. The print functions print the result of these os.path module functions. The result is
True                # The path exists
True                # yes, the argument is a directory
False                # no, the argument is not a file

Operations on files

Files can be opened and used in two different modes: text mode (also known as string mode) or binary mode. Python offers several functions for performing various operations on files. They are discussed in this post. These are discussed first with text mode and then with binary mode.

File operations in text mode

File open and close

The function open() is used to open a file in various modes: read mode, write mode, read and write mode, and append mode. The function has many parameters, but the open() is shown next with three most important parameters.

The function signature is as follows.
open (file, mode, encoding)        # all three parameters are string (str) type

file: path of the file to be opened as a str type
mode: the mode in which the file to be opened ( 'r', 'w', 'a', 'r+')
encoding: the default type depends on the system. The de facto standard is 'utf-8'.

Some examples of opening the file in the current working directory are as follows.

f1 = open('file_name1', 'r', encoding = 'utf-8')        # file opened in read mode
f2 = open('file_name2', 'w', encoding = 'utf-8')        # file opened in write mode
f3 = open('file_name3', 'r+', encoding = 'utf-8')        # file opened in read and write mode
f4 = open('file_name4', 'a', encoding = 'utf-8')        # file opened in append mode

The open() function returns the file object (eg. f1) on which various functions are invoked to perform operations such as read() and write(). After completing the purpose of opening the file, the opened files must be closed. The function used is close() on the file object. The file_name1 opened to read its content can be closed using the following line of code.

f1.close()    # it closes the file file_name1. 

File read()

It is better to use file functions and file objects along with the 'with' keyword. It automatically closes the file after the completion of the listed file operations. The following code snippet opens the file 'file_name1' using the 'with' keyword to read its contents.

with open('file_name1', 'r', encoding='utf-8') as f:
    file_content = f.read()            

The file read() function reads the entire file and returns it as a string.  The file_content holds everything of the file as a string value. The 'with' keyword automatically closes the file  'file_name1'. This can be verified using the following code line using the Python interpreter.

>>> f.closed()
True                        

The file once closed, must be opened again to perform any operations on that. The following line of code throws a ValueError because it is closed.

>>> f.read()  # throws ValueError because f is closed.

readline()  and readlines() functions

The file contents can be read line by line using the readline() function as follows. Assuming the file is already open and f is the file object,

>>> f.readline()
'first line is this \n'            # returns the read line as a string
>>> f.readline()
'second line is this \n'       # the returned string last character is always \n
....
>>> f.readline()
''                                # empty string indicates no more lines to read

But, there is an efficient and fast code lines in Python to read text line by line. It is as follows.

for text_line in f:
    print(text_line, end=' ')            # prints the read text_line; 

The end argument in the print function is to avoid its newline.

The readlines() function reads all lines from the file and returns as a list with each line as a string list item.

>>> lt =  f.readlines()
>>> print(lt)

The file contents are printed as list items in string form.

file write() function

The write() function argument is a string value. It writes the string to the designated file through file object. The following code lines show all these.

f = open('file_name1', 'w')         # file_name1 opened in write mode

f.write('This is first line')            # string is passed directly
st = 'This is second line.'
f.write(st)                                    # string variable is passed as an argument 

Copy contents from one file to another file:

f1 = open('file_name1', 'r')
f2 = open('file_name2', 'w')

file_content = f1.read()
f2.write(file_content)

seek() and tell() functions

The tell() function is used to find the current position of the cursor from where you can continue to operate. The following code lines help you to understand the tell() function.

>>> f = open('file_name1', 'r')
>>> f.tell() 
0                                    # because nothing is read from the file
>>> f.readline()
>>> f.tell()                    # indicates total number of characters read
15                                               
>>> f.readline()            # read another line
35                   # reflects the total number of characters from the 1st and 2nd line

The seek() function is useful for moving the cursor (reference) to the specified position from the beginning of the file. 

>>> f = open('file_name1', 'r')
>>> f.seek(14)        # move the reference point to the 15th character
>>> f.tell()                # validation for seek() function
15
>>> f.seek(0,2)           # moves the reference to the end of the file

These functions are useful to update the file content.

File operations in binary mode

The set of functions used in text mode can be used in binary mode as well. The character 'b' must be appended to 'r' or 'w'. The data in the file is read as byte objects and written as byte objects. You cannot specify encoding when the file is opened in binary mode

f1 = open('file_name1', 'rb')        # file opened in read binary mode
f2 = open('file_name2', 'rb+')     # file opened in read and write binary mode
f3 = open('file_name3', 'wb+')    # file opened in write binary mode

The binary mode is useful to copy pdf files, image files of various formats into other files. The following code lines show reading bytes from the pdffile.pdf (f1) and writing into new.pdf file (using f2 object).

f1 = open('pdffile.pdf', 'rb')
f2 = open('new.pdf', 'wb')
f2.write(f1.read())
f1.close()
f2.close()

There are many less frequently used functions for file objects. Consult the Python doc if necessary.

Saving variables values in files

You may want to reopen the app from where you left off. To achieve this, the state of the app (program) must be saved to the disk before exiting. This task is part of your program. The variables of the program may have to be stored in the file as part of this. The Python PL has modules and packages for this: the shelve module and the pprint module.

shelve module

The shelve module has many functions which are similar to file operations and a dictionary. The file is opened using open and closed using close functions of the shelve module. The variables values are stored in the file using keys. The same keys are used to read them from the file. The following code snippet helps you to understand the usage of the shelve module for the mentioned task.

import shelve
f1 = shelve.open('var_value')            # creation of shelve oobject
PL = ['C', 'C++', 'Java']                      # variable to save
st = 'programming'
f1['languages'] = PL                        # save variable PL in the file using 'languages' as key
f1['string'] = st
f1.close()

The file var_value file has two variables values stored and now it is closed. When reopened, the values can be read as follows using the keys 'languages' and 'string'.

import shelve
f1 = shelve.open('var_value')
PL = f1['languages']
st = f1['string']
print(PL)                        # verify storage and retrieval of variables
print(st)

Also, if necessary get all keys and variables in list form for any processing using keys() and values() functions of the shelve module respectively.
keys = list(f1.keys())                        # get keys of variables in list form
values = list(f1.values())                    # get values of variables in list form
print(keys)
print(values)                                    # verify all keys and values

f1.close()
After usage, close the file using close() function of the shelve module.

pprint module

The pprint is another module for saving variables values and then retrieving them whenever necessary. The following code lines show how the variable values are stored in the file (pretty.py) using this module. The function pprint.pformat() simply converts its argument to a string type. The list PL is passed as an argument and file object write() function completes saving PL into the file pretty.py

import pprint
f1 = open('pretty.py', 'w')            # pretty.py is used as module
PL = ['C', 'C++', 'Java']
PL_str = pprint.pformat(PL)
f1.write('PL=' + PL_str )        # PL = '['C', 'C++', 'Java']' is saved in pretty.py
f1.close()                        # file closed

Import the file pretty.py (it is a module) and access the saved variable value using its name (key).
lt = pretty.PL
print(lt)

There may be many other functions and packages/and modules for saving variables into the file. Check Python documentation.