Python Object-Oriented Programming PDF
Document Details
Uploaded by ResoluteJasper1495
Tags
Summary
This document provides an introduction to Python Object-Oriented Programming (OOP). It explains concepts like classes, objects, attributes, and behaviors, and discusses inheritance and other important OOP features. The document also provides examples and code snippets to illustrate the concepts.
Full Transcript
Unit1: Python Object Oriented Programming Python is a versatile programming language that supports various programming styles, including object-oriented programming (OOP) through the use of objects and classes. An object is any entity that has attributes and behavior...
Unit1: Python Object Oriented Programming Python is a versatile programming language that supports various programming styles, including object-oriented programming (OOP) through the use of objects and classes. An object is any entity that has attributes and behaviors. For example, a parrot is an object. It has attributes - name, age, color, etc. behavior - dancing, singing, etc Similarly, a class is a blueprint for that object. So what are objects? Objects are anything that has properties and some behaviors. The properties of objects are often referred to as variables of the object, and behaviors are referred to as the functions of the objects. Objects can be real-life or logical. Some Major Benefits of OOPS Include: i. They reduce the redundancy of the code by writing clear and reusable codes (using inheritance). ii. They are easier to visualize because they completely relate to real-world scenarios. For example, the concept of objects, inheritance, and abstractions, relate very closely to real- world scenarios(we will discuss them further in this article). iii. Every object in OOPS represent a different part of the code and has its own logic and data to communicate with each other. So, there are no complications in the code. Class and Objects in Python Suppose you wish to store the number of books you have, you can simply do that by using a variable. Or, say you want to calculate the sum of 5 numbers and store it in a variable, well, that can be done too! Primitive data structures like numbers, strings, and lists are designed to store simple values in a variable. Suppose, your name, or square of a number, or count of some marbles (say). But what if you need to store the details of all the Employees in your company? For example, you may try to store every employee in a list, you may later be confused about which index of the list represents what details of the employee(e.g. which is the name field, or the empID etc.) employee1 = ['John Smith', 104120, "Developer", "Dept. 2A"] employee2 = ['Mark Reeves', 211240, "Database Designer", "Dept. 11B"] employee3 = ['Steward Jobs', 131124, "Manager", "Dept. 2A"] Even if you try to store them in a dictionary, after an extent, the whole codebase will be too complex to handle. So, in these scenarios, we use Classes in python. A class is used to create user-defined data structures in Python. Classes define functions, which are termed methods, that describe the behaviors and actions that an object created from a class can perform. OOPS concepts in Python majorly deal with classes and objects. Classes make the code more manageable by avoiding complex codebases. It does so, by creating a blueprint or a design of how anything should be defined. In fig1.1, It defines what properties or functions, any object which is derived from the class should have An instance of a class is called the object. It is the implementation of the class and exists in real. An object is a collection of data (variables) and methods (functions) that access the data. It is the real implementation of a class. Fig.1.1 Consider this example, here Human is a class - It is just a blueprint that defines how Human should be, and not a real implementation. You may say that "Human" class just exists logically. However, "Ron" is an object of the Human class (please refer to the image given above for understanding). That means, Ron is created by using the blueprint of the Human class, and it contains the real data. "Ron" exists physically, unlike "Human" (which just exists logically). He exists in real, and implements all the properties of the class Human, such as, Ron have a name, he is 15 years old, he is a male, and lives in Delhi. Also, Ron implements all the methods of Human class, suppose, Ron can walk, speak, eat, and sleep. How to Define a Class in Python? Classes in Python can be defined by the keyword class, which is followed by the name of the class and a colon. Syntax: class Human: pass 'pass' is commonly used as a placeholder, in the place of code whose implementation we may skip for the time being. "pass" allows us to run the code without throwing an error in Python Python Objects objectName = ClassName() Example 1: Python Class and Objects # define a class class Bike: name = "" gear = 0 # create object of class bike1 = Bike() # access attributes and assign new values bike1.gear = 11 bike1.name = "Mountain Bike" print(f"Name: {bike1.name}, Gears: {bike1.gear} ") Output: Name: Moutain Bike, Gears:11 Create Multiple Objects of Python Class We can also create multiple objects from a single class. For example, # define a class class Employee: # define an attribute employee_id = 0 # create two objects of the Employee class employee1 = Employee() employee2 = Employee() # access attributes using employee1 employee1.employeeID = 1001 print(f"Employee ID: {employee1.employeeID}") # access attributes using employee2 employee2.employeeID = 1002 print(f"Employee ID: {employee2.employeeID}") Output: Employee ID: 1001 Employee ID: 1002 Python Methods We can also define a function inside a Python class. A Python Function defined inside a class is called a method. # create a class class Room: length = 0.0 breadth = 0.0 # method to calculate area def calculate_area(self): print("Area of Room =", self.length * self.breadth) # create object of Room class study_room = Room() # assign values to all the attributes study_room.length = 42.5 study_room.breadth = 30.8 # access method inside class study_room.calculate_area() Output: Area of Room = 1309.0 What is an _init_ Method? The properties that all Human objects must have been defined in a method called init(). Every time a new Human object is created, __init__() sets the initial state of the object by assigning the values we provide inside the object’s properties. That is, __init__() initializes each new instance of the class. __init__() can take any number of parameters, but the first parameter is always a variable called self. The self parameter is a reference to the current instance of the class. It means, the self parameter points to the address of the current object of a class, allowing us to access the data of its(the object's) variables. So, even if we have 1000 instances (objects) of a class, we can always get each of their individual data due to this self because it will point to the address of that particular object and return the respective value. class Human: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender Suppose, we try to create objects of our Human class, then we also need to pass the values for name, age, and gender. There are 2 types of attributes in Python: 1. Class Attribute: These are the variables that are the same for all instances of the class. They do not have new values for each new instance created. They are defined just below the class definition. Code: class Human: #class attribute book = "python programming" Here, the book will have a fixed value for any object we create. Code: class Human: #class attribute species = "Homo Sapiens" Here, the species will have a fixed value for any object we create. 2. Instance Attribute: Instance attributes are the variables that are defined inside of any function in class. Instance attributes have different values for every instance of the class. These values depend upon the value we pass while creating the instance. class Human: #class attribute species = "Homo Sapiens" def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender Here, name, age, and gender are the instance attributes. They will have different values for new instances of the class. Creating an Object in Class When we create a new object from a class, it is called instantiating an object. An object can be instantiated by the class name followed by the parentheses. We can assign the object of a class to any variable Syntax: x = ClassName() Example: class Human: #class attribute species = "Homo Sapiens" def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender x = Human("Haris", 15, "Male") y = Human("Afreen", 22, "Female") print(x.name) print(y.name) Output: Heena Afreen So, we find that we can access the instance and class attributes just by using the dot operator. Warning: If we do not pass the required arguments, it will throw a TypeError: TypeError: init() missing 3 required positional arguments: 'name', 'age', and 'gender Example: class Human: species = "Animal" def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender # x and y are instances of class Human x = Human("Heena", 15, "female") y = Human("Leeba", 22, "female") print(x.species) # species are class attributes, hence will have same value for all instances print(y.species) # name, gender and age will have different values per instance, because they are instance attributes print(f"Hi! My name is {x.name}. I am a {x.gender}, and I am {x.age} years old") print(f"Hi! My name is {y.name}. I am a {y.gender}, and I am {y.age} years old") Output: Animal Animal Hi! My name is Heena. I am a female, and I am 15 years old Hi! My name is Leeba. I am a female, and I am 22 years old In the above example, we have our class attributes values same "Animal", but the instance attributes values are different as per the value we passed while creating our object. However, we can change the value of class attributes, by assigning classname.classAttribute with any new value. Example: class Human: #class attribute species = "Animal" def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender Human.species = "alliance " obj = Human("Heena",11,"female") print(obj.species) Output: alliance Fundamentals of OOPS in Python There are four fundamental concepts of Object-oriented programming – 1. Inheritance 2. Encapsulation 3. Polymorphism 4. Data abstraction Inheritance People often say to newborn babies that they have got similar facial features to their parents, or that they have inherited certain features from their parents. It is likely that you too have noticed that you have inherited some or the other features from your parents. Inheritance too is very similar to the real-life scenario. But here, the "child classes" inherit features from their "parent classes." And the features they inherit here are termed as "properties" and "methods"! The class whose properties are inherited is the Parent class, and the class that inherits the properties from the Parent class is the Child class. Let us see the syntax of inheritance in Python: class parent_class: #body of parent class class child_class( parent_class): # inherits the parent class #body of child class class Animal: def speak(self): print("Animal Speaking") #child class Dog inherits the base class Animal class Dog(Animal): def bark(self): print("dog barking") d = Dog() d.bark() d.speak() Output: dogbarking Animal Speaking Types of Inheritance 1. Single Inheritance: Single inheritance enables a derived class to inherit properties from a single parent class, thus enabling code reusability and the addition of new features to existing code. Example: # Python program for demonstrating single inheritance # Here, we will create the base class or the Parent class class Parent1: def func_1(self): print ("This function is defined inside the parent class.") # now, we will create the Derived class class Child1(Parent1): def func_2(self): print ("This function is defined inside the child class.") # Driver's code object = Child1() object.func_1() object.func_2() 2. Multiple Inheritance: When a class can be derived from more than one base class this type of inheritance is called multiple inheritances. In multiple inheritances, all the features of the base classes are inherited into the derived class Example: class Mother1: mothername1 = "" def mother1(self): print(self.mothername1) # Here, we will create the Base class 2 class Father1: fathername1 = "" def father1(self): print(self.fathername1) # now, we will create the Derived class class Son1(Mother1, Father1): def parents1(self): print ("Father name is :", self.fathername1) print ("Mother name is :", self.mothername1) # Driver's code s1 = Son1() s1.fathername1 = "Raju" s1.mothername1 = "Rani" s1.parents1() 3. Multilevel Inheritance : In multilevel inheritance, features of the base class and the derived class are further inherited into the new derived class. This is similar to a relationship representing a child and a grandfather. Example: # Python program to demonstrate # multilevel inheritance # Base class class Grandfather: def __init__(self, grandfathername): self.grandfathername = grandfathername # Intermediate class class Father(Grandfather): def __init__(self, fathername, grandfathername): self.fathername = fathername # invoking constructor of Grandfather class Grandfather.__init__(self, grandfathername) # Derived class class Son(Father): def __init__(self, sonname, fathername, grandfathername): self.sonname = sonname # invoking constructor of Father class Father.__init__(self, fathername, grandfathername) def print_name(self): print('Grandfather name :', self.grandfathername) print("Father name :", self.fathername) print("Son name :", self.sonname) # Driver code s1 = Son('Prince', 'Rampal', 'Lal mani') print(s1.grandfathername) s1.print_name() 4. Hierarchical Inheritance: When more than one derived class are created from a single base this type of inheritance is called hierarchical inheritance. In this program, we have a parent (base) class and two child (derived) classes. Example: # Python program to demonstrate # Hierarchical inheritance # Base class class Parent: def func1(self): print("This function is in parent class.") # Derived class1 class Child1(Parent): def func2(self): print("This function is in child 1.") # Derivied class2 class Child2(Parent): def func3(self): print("This function is in child 2.") # Driver's code object1 = Child1() object2 = Child2() object1.func1() object1.func2() object2.func1() object2.func3() 5. Hybrid Inheritance: Inheritance consisting of multiple types of inheritance is called hybrid inheritance. Example: # Python program to demonstrate # hybrid inheritance class School: def func1(self): print("This function is in school.") class Student1(School): def func2(self): print("This function is in student 1. ") class Student2(School): def func3(self): print("This function is in student 2.") class Student3(Student1, School): def func4(self): print("This function is in student 3.") # Driver's code object = Student3() object.func1() object.func2() Polymorphism Suppose, you are scrolling through your Instagram feeds on your phone. You suddenly felt like listening to some music as well, so you opened Spotify and started playing your favorite song. Then, after a while, you got a call, so you paused all the background activities you were doing, to answer it. It was your friend's call, asking you to text the phone number of some person. So, you messaged him the number, and resumed your activities. Did you notice one thing? You could scroll through feeds, listen to music, attend/make phone calls, message -- everything just with a single device - your Mobile Phone! Whoa! So, Polymorphism is something similar to that. 'Poly' means multiple and 'morph' means forms. So, polymorphism altogether means something that has multiple forms. Or, 'some thing' that can have multiple behaviours depending upon the situation. Polymorphism in OOPS refers to the functions having the same names but carrying different functionalities. Or, having the same function name, but different function signature(parameters passed to the function). Example 1: Polymorphism in addition operator We know that the + operator is used extensively in Python programs. But, it does not have a single usage. For integer data types, + operator is used to perform arithmetic addition operation. num1 = 1 num2 = 2 print(num1+num2) Similarly, for string data types, + operator is used to perform concatenation str1 = "Python" str2 = "Programming" print(str1+" "+str2) Like in other programming languages, the child classes in Python also inherit methods and attributes from the parent class. We can redefine certain methods and attributes specifically to fit the child class, which is known as Method Overriding. Polymorphism allows us to access these overridden methods and attributes that have the same name as the parent class. class Birds: def intro1(self): print("There are multiple types of birds in the world.") def flight1(self): print("Many of these birds can fly but some cannot.") class sparrow1(Birds): def flight1(self): print("Sparrows are the bird which can fly.") class ostrich1(Birds): def flight1(self): print("Ostriches are the birds which cannot fly.") obj_birds = Birds() obj_spr1 = sparrow1() obj_ost1 = ostrich1() obj_birds.intro1() obj_birds.flight1() obj_spr1.intro1() obj_spr1.flight1() obj_ost1.intro1() obj_ost1.flight1() Output: There are multiple types of birds in the world. Many of these birds can fly but some cannot. There are multiple types of birds in the world. Sparrows are the bird which can fly. There are multiple types of birds in the world. Ostriches are the birds which cannot fly. Encapsulation You must have seen medicine capsules, where all the medicines remain enclosed inside the cover of the capsule. Basically, a capsule encapsulates several combinations of medicine. Similarly, in programming, the variables and the methods remain enclosed inside a capsule called the 'class'! Yes, we have learned a lot about classes in Python and we already know that all the variables and functions we create in OOP remain inside the class. In other words, encapsulation is a programming technique that binds the class members (variables and methods) together and prevents them from being accessed by other classes. Getters and Setters We mainly use encapsulation for Data Hiding. We do so by defining getter and setter methods for our classes. If anyone wants some data, they can only get it by calling the getter method. And, if they want to set some value to the data, they must use the setter method for that, otherwise, they won't be able to do the same. class Library: def __init__(self, id, name): self.bookId = id self.bookName = name def setBookName(self, newBookName): #setters method to set the book name self.bookName = newBookName def getBookName(self): #getters method to get the book name print(f"The name of book is {self.bookName}") book = Library(101,"The Witchers") book.getBookName() book.setBookName("The Witchers Returns") book.getBookName() Output The name of book is The Witchers The name of book is The Witchers Returns In the above example, we defined the getter getBookName() and setter setBookName() to get and set the names of books respectively. So, now we can only get and set the book names upon calling the methods, otherwise, we cannot directly get or modify any value. This promotes high security to our data, because others are not aware at a deep level of how the following methods are implemented(if their access is restricted). We can also promote safety of our data using access modifiers. Let's see what are access modifiers. Access Modifiers Access modifiers limit access to the variables and methods of a class. Python provides three types of access modifiers private, public, and protected. In Python, we don’t have direct access modifiers like public, private, and protected. We can achieve this by using single underscore and double underscores. Public Member: Accessible anywhere from outside the class. Private Member: Accessible only within the class Protected Member: Accessible within the class and it's sub-classes Single underscore _ represents Protected class. Double underscore __ represents Private class. Suppose we try to make an Employee class: class Employee: def __init__(self, name, employeeId, salary): self.name = name #making employee name public self._empID = employeeId #making employee ID protected self.__salary = salary #making salary private def getSalary(self): print(f"The salary of Employee is {self.__salary}") employee1 = Employee("Heena Shaikh", 110514, "$1500") print(f"The Employee's name is {employee1.name}") print(f"The Employee's ID is {employee1._empID}") print(f"The Employee's salary is {employee1.salary}") #will throw an error because salary is defined as private Here, we have made the employee's name public, employee's ID protected, and the employee's salary private. Suppose we try to print all the values. Now, we will be able to access the employee's name or his ID, but not the salary(because it is private). Look into the error below: Output: The Employee's name is Heena Shaikh The Employee's ID is 110514 Traceback (most recent call last): File "", line 14, in AttributeError: 'Employee' object has no attribute 'salary' However, we can access the employee's salary by calling that getter method getSalary() we have created in our Employee class. Now, you might have understood the importance of getters and setters, and also the access modifiers which restricts the access to your data. Complete code class Employee: def __init__(self, name, employeeId, salary): self.name = name #making employee name public self._empID = employeeId #making employee ID protected self.__salary = salary #making salary private def getSalary(self): print(f"The salary of Employee is {self.__salary}") employee1 = Employee("John Gates", 110514, "$1500") print(f"The Employee's name is {employee1.name}") print(f"The Employee's ID is {employee1._empID}") employee1.getSalary() #will be able to access the employee's salary now using the getter method Output: The Employee's name is John Gates The Employee's ID is 110514 The salary of Employee is $1500 A protected data member is used when inheritance is used and you want the data members to have access only to the child classes. So, encapsulation protects an object from unauthorized access. It allows private and protected access levels to prevent accidental data modification. Abstraction It is likely that you are reading this article on your laptop, phone, or tablet. You are also probably making notes, and highlighting important points, and you may be saving some points in your internal files while reading it. As you read this, all you see before you is a 'screen' and all this data that is shown to you. As you type, all you see are the keys on the keyboard and you don't have to worry about the internal details, like how pressing a key may lead to displaying that word onscreen. Or, how clicking on a button on your screen could open a new tab! So, everything we can see here is at an abstract level. We are not able to see the internal details, but just the result it is producing(which actually matters to us). Abstraction in a similar way just shows us the functionalities anything holds, hiding all the implementations or inner details. The main goal of Abstraction is to hide background details or any unnecessary implementation about the data so that users only see the required information. It helps in handling the complexity of the codes. Key Points of Abstract Classes Abstraction is used for hiding the background details or any unnecessary implementation of the data, so that users only see the required information. In Python, abstraction can be achieved by using abstract classes A class that consists of one or more abstract methods is called the "abstract class". Abstract methods do not contain any implementation of their own. Abstract class can be inherited by any subclass. The subclasses that inherit the abstract classes provide the implementations for their abstract methods. Abstract classes can act like blueprint to other classes, which are useful when we are designing large functions. And the subclass which inherits them can refer to the abstract methods for implementing the features. Python provides the abc module to use the abstraction. syntax from abc import ABC class ClassName(ABC): ABC stands for Abstract Base class. The abc module provides the base for defining Abstract Base classes (ABC). Code: from abc import ABC class Vehicle(ABC): # inherits abstract class #abstract method def no_of_wheels(self): pass class Bike(Vehicle): def no_of_wheels(self): # provide definition for abstract method print("Bike have 2 wheels") class Tempo(Vehicle): def no_of_wheels(self): # provide definition for abstract method print("Tempo have 3 wheels") class Truck(Vehicle): # provide definition for abstract method def no_of_wheels(self): print("Truck have 4 wheels") bike = Bike() bike.no_of_wheels() tempo = Tempo() tempo.no_of_wheels() truck = Truck() truck.no_of_wheels() Output: Bike have 2 wheels Tempo have 3 wheels Truck have 4 wheels Here, we have an abstract class Vehicle. It is abstract because it is inheriting the abstract class abc. The class Vehicle have an abstract method called no_of_wheels, which do not have any definition, because abstract methods are not defined(or abstract methods remain empty, and they expects the classes inheriting the abstract classes to provide the implementation for the method ). But, other classes which inherits the Vehicle class, like Bike, Tempo or Truck, defines the method no_of_wheels, and they provide their own implementation for the abstract method. Suppose, bike have 2 wheels, so it prints "Bike have 2 wheels" in the inherited abstract method no_of_wheels. And, similarly, Tempo and Truck classes also provide their own implementations. Some notable points on Abstract classes are: 5. Abstract classes cannot be instantiated. In simple words, we cannot create objects for the abstract classes. 6. An Abstract class can contain the both types of methods -- normal and abstract method. In the abstract methods, we do not provide any definition or code. But in the normal methods, we provide the implementation of the code needed for the method. Advantages of OOPS in Python There are numerous advantages of OOPS concepts in Python, making it favorable for writing serious softwares. Let us look into a few of them -- 7. Effective problem solving because, for each mini-problem, we write a class that does what is required. And then we can reuse those classes, which makes it even quicker to solve the next problem. 8. Flexibility of having multiple forms of a single class, through polymorphism 9. Reduced high complexity of code, through abstraction. 10. High security and data privacy through encapsulation. 11. Reuse of code, by the child class inheriting properties of parent class through inheritance. 12. Modularity of code allows us to do easy debugging, instead of looking into hundreds of lines of code to find a single issue. Data Hiding Data hiding is a method used in object-oriented programming (OOP) to hide the details of an object and function. Or in other words, data hiding means isolating the client from the implementation part of the application. In Python, modules are enough to understand how to use a particular application correctly, but users can’t know how the application is working and what processes are running inside it. Thus, data hiding is the most essential feature because it avoids dependency and provides security. Data hiding is also known as information hiding or encapsulation. Syntax In python, if we want to hide any variable, then we have to use the double underscore() before the variable name. This makes the class members inaccessible and private to other classes. __variablename Example 1 In the below example, you can see that we are accessing the username and password from inside the class. In the method creden, as you can see that we have passed only Self. If you want to access the instance variables then we have to use the Self. Like here, username and password are the instance variables and we want to access their values. class Authentication: # Private members __username = ‘Heena' __password = '123456' def creden(self): print(f"Username: {self.__username}") print(f"Password:{self.__password}") p = Authentication() p.creden() Output: Username: Heena Password:123456 Note: If we try to access a private member of a class from outside of a class, then it will throw an error Example 2 To access private members of the class, we can use the following syntax: objectName._className.__attrName. class Authentication: # Private members __username = ‘Heena' __password = ‘123456' def creden(self): print(f"Username: {self.__username}") print(f"Password: {self.__password}") p = Authentication() print(p._Authentication__username) print(p._Authentication__password) Output: Heena 123456 Example 3 As you can see in the below code, the username is a private attribute while the password is a protected attribute class Authentication: __username = 'Heena' # Private member _password = '123456' # Protected member def creden(self): print(f"Username: {self.__username}") print(f"Password: {self._password}") p = Authentication() p.creden() Output: Username: Heena Password: 123456 Chapter 2: Python File I/OPython File Operation A file is a container in computer storage devices used for storing data.When we want to read from or write to a file, we need to open it first. When we are done, it needs to be closed so that the resources that are tied with the file are freed. Hence, in Python, a file operation takes place in the following order: 1. Open a file 2. Read or write (perform operation) 3. Close the file Opening Files in Python In Python, we use the open() method to open files. To demonstrate how we open files in Python, let's suppose we have a file named test.txt with the following content. Now, let's try to open data from this file using the open() function # open file in current directory file1 = open("test.txt") Here, we have created a file object named file1. This object can be used to work with files and directories. By default, the files are open in read mode (cannot be modified). The code above is equivalent to test = open("file1.txt", "r") Here, we have explicitly specified the mode by passing the "r" argument which means file is opened for reading Different Modes to Open a File in Python Reading Files in Python After we open a file, we use the read() method to read its contents. For example test = open('file1.txt', 'r') print(test.read()) Output: Closing Files in Python When we are done with performing operations on the file, we need to properly close the file.Closing a file will free up the resources that were tied with the file. It is done using the close() method in Python. For example, # open a file test = open("file1.txt", "r") # read the file read_content = test.read() print(read_content) # close the file test.close() Here, we have used the close() method to close the file.After we perform file operation, we should always close the file; it's a good programming practice. Use of with...open Syntax In Python, we can use the with...open syntax to automatically close the file. For example, with open("file1.txt", "r") as test: read_content = test.read() print(read_content) Note: Since we don't have to worry about closing the file, make a habit of using the with...open syntax. Writing to Files in Python There are two things we need to remember while writing to a file. If we try to open a file that doesn't exist, a new file is created. If a file already exists, its content is erased, and new content is added to the file. In order to write into a file in Python, we need to open it in write mode by passing "w" inside open() as a second argument. Suppose, we don't have a file named test2.txt. Let's see what happens if we write contents to the test2.txt file. with open('test2.txt', 'w') as file2: # write contents to the test2.txt file file2.write('Welcome to ') file2.write(“SIES college") Output Here, a new test2.txt file is created and this file will have contents specified inside the write() method. Opening file in append mode fileptr = open("test2.txt", "a") # overwriting the content of the file fileptr.write(" \n Python has an easy syntax and user-friendly interaction.") # closing the opened file fileptr.close() Output Syntax: The syntax of read() method of a file in Python is given below fileobj.read() Here, the count is the number of bytes to be read from the file starting from the beginning of the file. If the count is not specified, then it may read the content of the file until the end. #open the file.txt in read mode. causes error if no such file exists. fileptr = open("test2.txt","r") #stores all the data of the file into the variable content content = fileptr.read(10) print(content) #closes the opened file fileptr.close() Read file through for loop We can use read() method when we open the file. Read method is also done through the for loop. We can read the file using for loop. Consider the following example. Program code 1 for Read File using For Loop: Here we give an example of read file using for loop. The code is given below - #open the file.txt in read mode. causes an error if no such file exists. fileptr = open("test2.txt","r"); #running a for loop for i in fileptr: print(i) # i contains each line of the file Output: Iterables and iterators Introduction to Iterators in Python Python is an Object-Oriented Language, everything in python is considered as an object, including variables, functions, lists, tuples, set, etc. There are some objects which are iterable, which means we can traverse over them and they will return their member value one by one. Examples of iterable objects are: List, Tuple, Dictionary Just like all other things, iterators in python are also objects. They are used for iterating over iterable objects. This simply means that we can use iterators on lists, tuples, dictionaries, and strings. Iterators are implemented using two special methods in Python which are iter() and next(). They are collectively called iterator protocol. Using Python Iterators The iter() method is used to create the iterator over the iterable object. It returns an iterator for the object you give it. The next() method returns the next item from the iterator. Example: mySecret = ["I", "Love", "Python"] myIter = iter(mySecret) print(myIter) print(next(myIter)) print(next(myIter)) print(next(myIter)) If we try to run next() again then we will get a StopIteration exception: How to Make Custom Iterators in Python? Just like any other thing in python, making a custom iterator from scratch is super easy. For making our own iterator we have to use two dunder/magic methods provided by Python. Dunder/Magic methods are methods that have two underscores before and after their name; their invocation generally happens internally from a class or some action. The two dunder methods we have to use are: 1. __iter__() 2. __next__() These are similar to iter() and next(). __iter__() should return the iterator object. If required, some initialization can be performed. __next__() should return the next item in the sequence. On reaching the end it should raise StopIteration. Example: class Sample: def __iter__(self): self.a = 1 return self def __next__(self): x = self.a self.a += 2 return x # creating an object s = Sample() output # creating an iterator object my_iter = iter(s) print(next(my_iter)) print(next(my_iter)) print(next(my_iter)) 0utput: Iterator vs Iterable in Python With so much programming jargon it is easy to forget the difference between an Iterator and Iterable. Here is a simple explanation. An iterator is an object which consists of __iter__() and __next__() (collectively these are known as iterator protocol). An iterable is anything we can loop over using a loop. This is the easiest explanation that will help you differentiate between the two.