Iterators

An iterator is an object that contains a countable number of values.

For loop give all the output at once only

but what if i need the output one at a time used iterator

Iterator Class

step

To make any Object Iterable

To call the next() to get the new element

we will make the list iterable

print("without iterable class")
st=[12,13,14,15,16]
for i in st:
print(i)
print("Using iterable class")
result=iter(st)
print(next(result))
print(next(result))
print(next(result))

Custom iterator

class PowTwo:
def __init__(self, max=0):
self.max = max
def __iter__(self):
self.n = 0
return self
def __next__(self):
if self.n <= self.max:
result = 2 ** self.n
self.n += 1
return result
else:
raise StopIteration
# create an object numbers = PowTwo(3)
# create an iterable from the object
numbers = PowTwo(3)
i = iter(numbers)
# Using next to get to the next iterator element
print(next(i)) # prints 1
print(next(i)) # prints 2
print(next(i)) # prints 4
print(next(i)) # prints 8
print(next(i)) # raises StopIteration exception

Python - Generators

A generator in Python is a special type of function that returns an iterator object.A generator is a simpler way of defining iterators. However, instead of return statement at the end, generator uses the yield keyword.

Syntax

def generator():
. . .
. . .
yield obj
it = generator()
next(it)
. . .

It is easy to create a Python generator,as a developer defines it as a standard function with Yield statement rather than the return statement. so if a function contains even one yield statement, it is a generator funcyion.It is true that yield and return both fetch some value from a function, however is a difference.while a return statement ends the function completely,a yield statement stop the function at that point,saves its state(context and continues to execute upon receiving successive calls.

Example

def table(n):
   for i in range(1,11):
      yield n*i
      i = i+1
for i in table(15):
   print(i)

Example-2(Fibonacci Numbers)


def fibonacci(n):
    a, b = 0, 1
    while True:
        c=a+b
        if c>=n:
            break
         yield c
         a, b = b, c
     return

f = fibonacci(10)
while True:
     try:
       print (next(f))
     except StopIteration:
       break

Python - Decorators

A Decorator in Python is a function that receives another function as argument. The argument function is the one to be decorated by decorator. The behaviour of argument function is extended by the decorator without actually modifying it.

Syntax

def decorator(arg_function): #arg_function to be decorated
     def nested_function():
         #this wraps the arg_function and extends its behaviour
         #call arg_function
         arg_function()
      return nested_function



You can now decorate this function to extend its behaviour by passing it to decorator −

function=decorator(function)

simple example of decorator


def my_function(x):
    print("The number is=",x)
def my_decorator(some_function,num):
    def wrapper(num):
       print("Inside wrapper to check odd/even")
       if num%2 == 0:
          ret= "Even"
       else:
          ret= "Odd!"
       some_function(num)
       return ret
    print ("wrapper function is called")
    return wrapper
no=10
my_function = my_decorator(my_function, no)
print ("It is ",my_function(no))

Decorator-using @ Symbol


def my_decorator(some_function):
          def wrapper(num):
                    print("Inside wrapper to check odd/even")
                    if num%2 == 0:
                              ret= "Even"
                    else:
                              ret= "Odd!"
                    some_function(num)
                    return ret
          print ("wrapper function is called")
          return wrapper

@my_decorator
def my_function(x):
          print("The number is=",x)
no=10
print ("It is ",my_function(no))