Exception Handling and Generator Functions

This page contains the CBSE Computer Science with Python class 12 Unit-2 chapter 4 Exception Handling and Generator Functions. You can find the solutions for chapter 4 of CBSE class 12 Computer Science with Python Exercise. So is the case if you are looking for CBSE class 12 Computer Science with Python related topic Exception Handling and Generator Functions questions and answers for the Exercise.
Exercise
Question 1
1. What all can be possible outputs of the following code?
def myfunc(x=None):
result = ""
if x is None:
result = "No argument given"
elif x == 0:
result = "Zero"
elif 0 < x <= 3:
result = "x is between 0 and 3"
else:
result = "x is more than 3"
return result
Answer 1
Possible outputs depend on the value passed to x:
myfunc() or myfunc(None) ->No argument given
myfunc(0) ->Zero
myfunc(1), myfunc(2), myfunc(3) ->x is between 0 and 3
myfunc(4) (or any value > 3) ->x is more than 3
Sample Call 1: calling myfunc() without arguments
# Sample call
  print myfunc()
Sample Output 1
No argument given
Sample Call 2: calling myfunc(None)
# Sample call
  print myfunc(None)
Sample Output 2
No argument given
Sample Call 3: calling myfunc(0)
# Sample call
  print myfunc(0)
Sample Output 3
Zero
Sample Call 4: calling myfunc(1)
# Sample call
  print myfunc(1)
Sample Output 4
x is between 0 and 3
Sample Call 5: calling myfunc(3)
# Sample call
  print myfunc(3)
Sample Output 5
x is between 0 and 3
Sample Call 6: calling myfunc(4)
# Sample call
  print myfunc(4)
Sample Output 6
x is more than 3
Question 2
2. We will try to read input from the user. Press Ctrl + d and see what happens:
>>> s = raw_input('Enter something --> ')
Answer 2
Pressing Ctrl + D sends end-of-file (EOF) input. Python raises an EOFError if it is not handled.
# Example handling
try:
    s = raw_input('Enter something --> ')
except EOFError:
    print "EOF received"
EOF received
Question 3
3. What will happen when following functions are executed?
def fib():
x, y = 1, 1
while True:
yield x
x, y = y, x + y
def odd(seq):
for number in seq:
if number % 2:
yield number
def underFourMillion(seq):
for number in seq:
if number > 4000000:
break
yield number
print sum(odd(underFourMillion(fib())))
Answer 3
The program creates a generator pipeline:
1.
fib() generates Fibonacci numbers infinitely.
2.
underFourMillion() stops values above 40,00,000.
3.
odd() keeps only odd values.
4.
sum(...) adds the resulting values.
The printed output is: 4613732.
Output:
4613732
Question 4
4. Find out the situation(s) in which following code may crash:
while loop == 1:
try:
a = input('Enter a number to subtract from > ')
b = input('Enter the number to subtract > ')
except NameError:
print "\nYou cannot subtract a letter"
continue
except SyntaxError:
print "\nPlease enter a number only."
continue
print a - b
try:
loop = input('Press 1 to try again > ')
except (NameError, SyntaxError):
loop = 0
Answer 4
This code may crash in these situations:
At start: loop is used before assignment in while loop == 1 (NameError).
EOF input: pressing Ctrl + D raises EOFError (not handled).
Invalid type operations: if a and b are non-subtractable values, TypeError may occur.
Keyboard interrupt: Ctrl + C raises KeyboardInterrupt (not handled).
Sample Output:
Traceback (most recent call last):
  File "exception_handling_and_generator_functions_q_4.py", line 1, in <module>
    while loop == 1:
NameError: name 'loop' is not defined
Question 5
5. Describe what the following module is doing:
def test(start=0):
c = start
while True:
value = yield c
if value != None:
c = value
else:
c += 1
Answer 5
This is a generator/coroutine:
It starts from start and yields current value c.
If a value is sent using send(), it resets c to that value.
If no value is sent (None), it increments c by 1.
How it works step-by-step:
1.
On first next(), it yields start.
2.
After each yield, execution pauses at value = yield c.
3.
If caller does g.send(10), then value becomes 10 and next yielded value starts from 10.
4.
If caller does next(g), value is None, so counter increases by 1.
So this generator can act both as a normal incrementing sequence and as a resettable counter controlled by the caller.
Question 6
6. When do we get type error?
Answer 6
TypeError occurs when an operation or function is used with a value of incompatible data type.
That means the value is present, but Python cannot process it with the given operation.
Arithmetic between incompatible types (for example string and integer).
Passing wrong type argument to a function.
Applying an unsupported operation on an object.
# Example
print "10" - 5   # TypeError
TypeError: unsupported operand type(s) for -: 'str' and 'int'
Question 7
7. List the situation(s) in which the code may result in IOError?
Answer 7
IOError may occur in situations like:
Trying to open a non-existing file in read mode.
Insufficient permission to read/write a file.
Disk full while writing to a file.
Invalid file path/device issue.
Question 8
8. What is the purpose of yield statement?
Answer 8
yield turns a function into a generator and returns values one-by-one while preserving function state between calls.
Key purposes of yield:
Lazy evaluation: Values are computed on-demand, not all at once.
Memory efficient: Only one value is held in memory at a time.
Maintains state: The function remembers its position and local variables between calls.
Iterable creation: Makes it easy to define custom iteration protocols.
# Example: Generator using yield
def countdown(n):
    while n > 0:
        yield n
        n -= 1

# Using the generator
for value in countdown(3):
    print value
3
2
1
Question 9
9. How is yield different from return?
Answer 9
The key difference: yieldpauses a function and returns control, while returnterminates the function entirely.
Basis
yield
return
Effect
Pauses function and gives one value.
Ends function immediately.
Re-entry
Function resumes from same point on next call.
No resume; function must be called again.
Use
For generators and lazy sequence creation.
For normal function result.
Memory
Memory efficient (one value at a time).
Less efficient (entire list in memory).
Example: Function with return
def get_numbers_return():
    return [1, 2, 3]

# All values returned at once
result = get_numbers_return()
print result
[1, 2, 3]
Example: Function with yield
def get_numbers_yield():
    yield 1
    yield 2
    yield 3

# Values returned one at a time
for num in get_numbers_yield():
    print num
1
2
3
Question 10
10. Write syntax of raise statement.
Answer 10
The raise statement is used to explicitly throw an exception during program execution. It allows you to signal error conditions and interrupt normal program flow.
Syntax variations:
# Raise without message
raise ExceptionType

# Raise with message/description
raise ExceptionType("error message")

# Re-raise current exception
raise

# Raise from another exception (exception chaining)
raise NewException("message") from original_exception
Example 1: Raising ValueError without arguments
def validate_age(age):
    if age < 0:
        raise ValueError

validate_age(-5)
ValueError
Example 2: Raising with descriptive message
def validate_age(age):
    if age < 0:
        raise ValueError("Age cannot be negative!")

validate_age(-5)
ValueError: Age cannot be negative!
Example 3: Custom exception type
def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("Cannot divide by zero")
    return a / b

divide(10, 0)
ZeroDivisionError: Cannot divide by zero
Question 11
11. Write a function called oops that explicitly raises an IndexError exception when called. Then write another function that calls oops inside a try/except statement to catch the error. What happens if you change oops to raise KeyError instead of IndexError?
Answer 11
# Raise IndexError explicitly
def oops():
    raise IndexError("Index problem")

def test_oops():
    try:
        oops()
    except IndexError as e:
        print "Caught:", e

test_oops()
Sample Output:
Caught: Index problem
If oops() is changed to raise KeyError and except IndexError is unchanged, the exception will not be caught and program will terminate with unhandled KeyError.
# Changed version: oops raises KeyError, except still catches IndexError
def oops():
    raise KeyError("Missing key")

def test_oops():
    try:
        oops()
    except IndexError as e:
        print "Caught:", e

test_oops()
Sample Output:
Traceback (most recent call last):
  File "program.py", line 11, in <module>
    test_oops()
  File "program.py", line 8, in test_oops
    oops()
  File "program.py", line 4, in oops
    raise KeyError("Missing key")
KeyError: 'Missing key'
Question 12
12. range() function in python does not include the stop value. Write a generator function equivalent to range() function that includes the stop value also. The function will take three arguments start, stop and step and will generate the desired list.
Answer 12
Python Program:
# Inclusive range generator
def range_inclusive(start, stop, step):
    if step == 0:
        raise ValueError("step cannot be zero")

    if step > 0:
        while start <= stop:
            yield start
            start += step
    else:
        while start >= stop:
            yield start
            start += step
Sample Usage:
# Sample usage
print list(range_inclusive(1, 5, 1))
Sample Output:
[1, 2, 3, 4, 5]
Question 13
13. Write a function to find average of a list of numbers. Your function should be able to handle an empty list and also list containing string.
Answer 13
def avg_list(values):
    try:
        if len(values) == 0:
            raise ValueError("Empty list")

        total = 0.0
        for x in values:
            total += float(x)   # Handles numeric strings also

        return total / len(values)

    except ValueError as e:
        print "ValueError:", e
    except TypeError:
        print "TypeError: list contains invalid element(s)"
Sample Usage:
# Sample outputs
print avg_list([1, 2, 3])
print avg_list([])
Sample Output:
2.0
ValueError: Empty list
Question 14
14. Write a function to generate cubes of numbers over time.
Answer 14
# Generator for cubes from 1 to n
def cube_gen(n):
    i = 1
    while i <= n:
        yield i ** 3
        i += 1
Sample Usage:
# Sample usage
print list(cube_gen(4))
Sample Output:
[1, 8, 27, 64]
Question 15
15. Write a program to accept a date as day, month & year from user and raise appropriate error(s), if legal value(s) is not supplied. Display appropriate message till user inputs correct value(s).
Answer 15
Python Program:
import datetime

while True:
    try:
        d = int(raw_input("Day: "))
        m = int(raw_input("Month: "))
        y = int(raw_input("Year: "))

        # datetime validates legal date
        dt = datetime.date(y, m, d)
        print "Valid date:", dt
        break

    except ValueError as e:
        print "Invalid date input:", e
        print "Please enter correct date again."
    except Exception:
        print "Unexpected error. Try again."
Sample Output:
Day: 31
Month: 2
Year: 2026
Invalid date input: day is out of range for month
Please enter correct date again.
Day: 19
Month: 2
Year: 2026
Valid date: 2026-02-19
Question 16
16. Create a class Person to store personal information (of your choice) for a person. Ensure that while accepting the data incorrect entry is properly handled.
Answer 16
class Person(object):
    def __init__(self):
        self.name = ""
        self.age = 0
        self.email = ""

    def accept(self):
        while True:
            try:
                self.name = raw_input("Name: ").strip()
                if self.name == "":
                    raise ValueError("Name cannot be empty")

                self.age = int(raw_input("Age: "))
                if self.age <= 0 or self.age > 120:
                    raise ValueError("Age out of valid range")

                self.email = raw_input("Email: ").strip()
                if "@" not in self.email or "." not in self.email:
                    raise ValueError("Invalid email format")

                break
            except ValueError as e:
                print "Input Error:", e
                print "Please re-enter details."

    def show(self):
        print "Name:", self.name
        print "Age:", self.age
        print "Email:", self.email

# Example usage (non-interactive sample)
p = Person()
p.name = "Alice"
p.age = 28
p.email = "alice@example.com"
p.show()
Name: Alice
Age: 28
Email: alice@example.com