# person_step02.py
#
# ICS 33 Spring 2026
# Code Example
#
# This version of Person modifies the namedtuple version by adding an age()
# method to it.

from collections import namedtuple


Person = namedtuple('Person', ['name', 'birthdate'])


# That we wrote this function using a "def" statement was partly stylistic
# (it's the naturally Pythonic way to write a function whose body consists
# of multiple statements) and partly out of necessity.  If we want to add a
# method to a class, we need it to be a function (i.e., an instance of
# Python's function class, rather than an object of an arbitrary class
# that has a __call__ method), because we need it also to be a descriptor,
# so that it can be called on a Person object and have its self parameter
# bound automatically.
def _calculate_age(self, as_of_date):
    if self.birthdate > as_of_date:
        raise ValueError(f'Person was not born yet on {as_of_date}')

    years_old = as_of_date.year - self.birthdate.year

    if (self.birthdate.month, self.birthdate.day) >= (as_of_date.month, as_of_date.day):
        years_old -= 1

    return years_old


# Once we have a function, we can simply assign it to an attribute of
# the Person class, and we've got ourselves a method.
Person.age = _calculate_age
