Saturday, May 17, 2025

Iterators and Generators

 In Python, iterators and generators are tools for working with sequences of data one item at a time, which is very memory-efficient—especially for large data sets.

What is an iterator?

An iterator is an object that implements:

  • __iter__() → returns the iterator itself

  • __next__() → returns the next item or raises StopIteration when done

nums = [1, 2, 3]
it = iter(nums)

print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
print(next(it))  # Raises StopIteration
# The StopIteration exception is raised when there are no more items to iterate over.
# This is a built-in exception in Python that indicates the end of an iterator.


class CountUpTo:
    def __init__(self, max):
        self.max = max
        self.current = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.current > self.max:
            raise StopIteration
        num = self.current
        self.current += 1
        return num

counter = CountUpTo(3)
for num in counter:
    print(num)
# # This is a custom iterator that counts up to a specified maximum value.
# # The __iter__ method returns the iterator object itself, and the __next__ method
# # returns the next value in the sequence.
# # When the maximum value is reached, a StopIteration exception is raised.
# # This is a common pattern in Python for creating custom iterators.


What is GENERATORS

A generator is a simpler way to create an iterator using:

  • A function with yield (instead of return)

  • It automatically creates an iterator object

def count_up_to(max):
    current = 1
    while current <= max:
        yield current
        current += 1

for num in count_up_to(3):
    print(num)



Decorators in Python

In Python, decorators are a powerful and elegant way to modify or enhance the behaviour of functions or methods without changing their code.

What is a decorator?

A decorator is a function that takes another function as input and returns a new function with added behaviour.

def my_decorator(func):
    def wrapper():
        print("Before the function runs")
        func()
        print("After the function runs")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()
# This is a simple decorator that adds functionality before and after the
# function call.
# You can use decorators to modify the behaviour of functions or methods in Python.
# # Decorators are often used in web frameworks like Flask and Django
#  to add functionality to routes or views.
# # For example, in Flask, you can use decorators to define routes and
# Add middleware functionality.
# # # Here's an example of a Flask route using a decorator:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
   return 'Hello, World!'
# # In this example, the @app.route('/') decorator tells Flask to call the
# # hello_world function when the root URL is accessed.

Built-in Decorators Examples

1.Set a Static Method

class MyClass:
    @staticmethod
    def greet():
        print("Hello")


2. Set a Instance Method

class MyClass:
    name = "Python"
   
    @classmethod
    def show(cls):
        print(cls.name)

3. Set a Property.
class Circle:
    def __init__(self, radius):
        self._radius = radius
   
    @property
    def area(self):
        return 3.14 * self._radius ** 2

Decorator Example

class FakeDBConnection:
    def connect(self):
        print(" DB connected")
   
    def commit(self):
        print("Transaction committed")
   
    def rollback(self):
        print("Transaction rolled back")
   
    def close(self):
        print("DB connection closed")

db = FakeDBConnection()

# Decorator without @wraps
def db_transaction(func):
    def wrapper():
        db.connect()
        try:
            result = func()
            db.commit()
            return result
        except Exception as e:
            db.rollback()
            print(f"Error: {e}")
        finally:
            db.close()
    return wrapper

# Function using the decorator
@db_transaction
def insert_user():
    """Insert a new user into the database."""
    print("Inserting user into database")
    # raise Exception("Simulated insert error")

insert_user()


Chaining of Decorators in Python

Chaining decorators means applying multiple decorators to a single function,

one after the other.

def decorator_one(func):
    def wrapper():
        print("Decorator One: Before")
        func()
        print("Decorator One: After")
    return wrapper

def decorator_two(func):
    def wrapper():
        print("Decorator Two: Before")
        func()
        print("Decorator Two: After")
    return wrapper

@decorator_one
@decorator_two
def say_hello():
    print("👋 Hello")

say_hello()
# This example demonstrates how to use multiple decorators on a single function.
# The order of decorators matters; the innermost decorator is applied first.

Decorator pattern for lofging in text file.

import datetime

def log_to_file(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        with open("log.txt", "a") as f:
            f.write(f"{datetime.datetime.now()}: Called {func.__name__}\n")
        return result
    return wrapper

@log_to_file
def say_hello():
    print("Hello!")

if __name__ == "__main__":
    say_hello()




Friday, May 9, 2025

Python Flask

What is Web API?

A Web API (Application Programming Interface) enables communication between different applications over the web. 
Uses standardized protocols like HTTP, data formats like JSON/XML.
Allows automation and data exchange across platforms.



What is Web API Used For?

  • Data Exchange: Fetching or sending structured information.

  • Third-Party Integration: Payment gateways, social media APIs, etc.

  • Microservices Architecture: Independent services working together.



Where is Web API Used?

  • Web Applications: Frontend communicates with backend via API.

  • Mobile Apps: Sends API requests to retrieve data.

  • IoT Devices: Smart devices sync via API calls.

  • Cloud Services: SaaS applications expose APIs for automation.


What is Flask?

Flask is a web application framework written in Python. 

It is developed by Armin Ronacher, who leads an international group of Python enthusiasts named Pocco. 


Prerequisite

It is recommended that Flask should be installed on Python 2.7.


How to Install Flask

pip install flask


E:\Software\Google Drive\PRWATECH\BATCH-A>C:\Users\user\AppData\Local\Programs\Python\Python38-32\Scripts\pip install flask
Collecting flask
  Downloading Flask-1.1.2-py2.py3-none-any.whl (94 kB)
     |████████████████████████████████| 94 kB 325 kB/s
Requirement already satisfied: Werkzeug>=0.15 in c:\users\user\appdata\local\programs\python\python38-32\lib\site-packages (from flask) (1.0.1)
Requirement already satisfied: Jinja2>=2.10.1 in c:\users\user\appdata\local\programs\python\python38-32\lib\site-packages (from flask) (2.11.1)
Requirement already satisfied: itsdangerous>=0.24 in c:\users\user\appdata\local\programs\python\python38-32\lib\site-packages (from flask) (1.1.0)
Requirement already satisfied: click>=5.1 in c:\users\user\appdata\local\programs\python\python38-32\lib\site-packages (from flask) (7.1.1)
Requirement already satisfied: MarkupSafe>=0.23 in c:\users\user\appdata\local\programs\python\python38-32\lib\site-packages (from Jinja2>=2.10.1->flask) (1.1.1)
Installing collected packages: flask
Successfully installed flask-1.1.2


After installing flask, now its time to code and understand the fundamentals.


Below code is the very basic code to host an web api.

from flask import Flask  #Importing Flask Module
app=Flask("mywebsite")   #Creating Flask object.

#Business logic layer, producing result via api
@app.route('/')          #The route() function of the Flask class is a decorator, which tells the application which URL should call the associated function.
def defaultmethod():     #Creating api, which is a default method when we run the website.
   return 'This is default method'

app.run()               #Running the web application .


When the application is run, the application is hosted on local machine and exposed via url as shown below.

E:\Software\Google Drive\PRWATECH\BATCH-A> cd "e:\Software\Google Drive\PRWATECH\BATCH-A" && cmd /C "C:\Users\user\AppData\Local\Programs\Python\Python38-32\python.exe c:\Users\user\.vscode\extensions\ms-python.python-2020.5.80290\pythonFiles\lib\python\debugpy\no_wheels\debugpy\launcher 51318 -- "e:\Software\Google Drive\PRWATECH\BATCH-A\learningflask.py" "
 * Serving Flask app "mywebsite" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Focus on the last line, it says "Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)"


Now go to the browser, preferably chrome, and open the web application by url.


 The result is presented in the form of string published on the html page.


Take away with the above example.


app.route('/') is a decorator, which the which tells the application which URL should call the associated function.

‘/’ URL is bound with default() function. Hence, when the home page of web server is opened in browser, the output of this function will be rendered.


Debug mode

A Flask application is started by calling the run() method. However, while the application is under development, it should be restarted manually for each change in the code. To avoid this inconvenience, enable debug support. The server will then reload itself if the code changes. It will also provide a useful debugger to track the errors if any, in the application.


Routing Continues

Now if we want to navigate  api using name,

from flask import Flask  #Importing Flask Module
app=Flask("mywebsite")   #Creating Flask object.

#Business logic layer, producing result via api
@app.route('/')        #The route() function of the Flask class is a decorator, which tells the application which URL should call the associated function.
def defaultmethod():     #Creating api, which is a default method when we run the website.
   return 'This is default function'

@app.route('/m1')        #This help to call the named api
def m1():
   return 'This is  M1 Method'

app.run(debug=True)               #Running the webapplication .

How to call the named api,


http://127.0.0.1:5000/m1










Multilevel Api Calling


@app.route('/m1/m2')#This is multi level api calling.
def m2():
   return 'This is  M2 Method'












Passing parameter to the api.



@app.route('/m3/<param>')#Passing parameter to the API
def m3(param):
   return 'This is  M3 Method :: '+param













Rules can be set to pass specific datatype parameters.


@app.route('/m4/<int:param>')#passing parameters to the api
def m4(param):
   
   returndata='Type of parameter passed::'+str(param)

   return 'This is  M4 Method :: '+returndata







Test case


















Consuming WebAPI

#write a code to consume the API and print the response using flask
import requests
from flask import Flask, jsonify

def consume_api():
    # URL of the API endpoint
    url = 'http://127.0.0.1:5000/myfunction'
    # Make a GET request to the API
    response = requests.get(url)
   
    # Check if the request was successful (status code 200)
    if response.status_code == 200:
        # Parse the JSON response
 
        data = response.json()
       
        print(data)
    else:
        print(f"Error: {response.status_code}")    

consume_api()