Decorators, Iterators, and Generators in Python

Decorators

Definition: A decorator is essentially a function (that decorates other functions) to add extra functionality to other functions.

Principles:

  1. Cannot modify the source code of the decorated function.
  2. Cannot change the way the decorated function is called.

Prerequisites for Implementing Decorators:

  1. Functions are 'variables'.
  2. Higher-order functions:
    • a. Pass a function name as an argument to another function (to add functionality with out modifying the decorated function).
    • b. Return a function name (with out changing the calling method).
  3. Nested functions.

Higher-order functions + Nested functions = Decorators

Simple Higher-order Function

import time

def bar():
    time.sleep(3)
    print('in the bar')

def test2(func):
    print(func)
    return func

bar = test2(bar)
bar()  # run bar

Simple Nested Function

def foo():
    print('in the foo')
    def bar():
        print('in the bar')
    bar()

foo()

Decorator = Higher-order Function + Nested Functon

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        func()
        stop_time = time.time()
        print('the func run time is %s' % (stop_time - start_time))
    return wrapper

@timer
def test1():
    time.sleep(3)
    print('in the test1')

test1()

Modified Decorator (Arbitrary Arguments)

import time

def timer(func):  # timer(test1)  func=test1
    def deco(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)  # run test1()
        stop_time = time.time()
        print("the func run time is %s" % (stop_time - start_time))
    return deco

@timer  # test1 = timer(test1)
def test1():
    time.sleep(1)
    print('in the test1')

test1()

Modified Decorator (Arbitrary Arguments v2)

import time

def timer(func):  # timer(test1)  func=test1
    def deco(*args, **kwargs):
        start_time = time.time()
        r = func(*args, **kwargs)  # run test1()
        stop_time = time.time()
        print("the func run time is %s" % (stop_time - start_time))
        return r
    return deco

@timer  # test1 = timer(test1)
def test1():
    time.sleep(1)
    print('in the test1')
    return "you are a BIG B"

@timer  # test2 = timer(test2) = deco  test2(name) = deco(name)
def test2(name, age):
    print("test2:", name, age)

a = test1()
print(a)
test2("abc", 123)

Output:

in the test1
the func run time is 1.0000011920928955
you are a BIG B
test2: abc 123
the func run time is 0.0

Advanced Decorator

import time

user, passwd = 'lance', '123456'

def auth(auth_type):
    print("auth func:", auth_type)
    def outer_wrapper(func):
        def wrapper(*args, **kwargs):
            print("wrapper func args:", *args, **kwargs)
            if auth_type == "local":
                username = input("Username:").strip()
                password = input("Password:").strip()
                if user == username and passwd == password:
                    print("\033[32;1mUser has passed authentication\033[0m")
                    res = func(*args, **kwargs)  # from home
                    print("---after authentication")
                    return res
                else:
                    exit("\033[31;1mInvalid username or password\033[0m")
            elif auth_type == "ldap":
                print("No ldap support for now...")
        return wrapper
    return outer_wrapper

@auth(auth_type="local")
def home():
    print("welcome to home page")
    return "from home"

print(home())

Output:

auth func: local
wrapper func args:
Username: lance
Password: 123456
User has passed authentication
welcome to home page
---after authentication
from home

Generators

Omitted.

Iterators

Omitted.

Tags: python decorators iterators generators

Posted on Sat, 16 May 2026 04:12:24 +0000 by dharprog