TheAlgorithms/Python · error · TypeError

Useful years must be an integer

Error message

Useful years must be an integer

What it means

Raised by straight_line_depreciation() in financial/straight_line_depreciation.py when useful_years is not an int (TypeError, not ValueError). The function loops range(useful_years), which requires an int, so a string or float is rejected up front. Note: True/False are ints in Python and pass this check — a latent quirk.

Source

Thrown at financial/straight_line_depreciation.py:56

    Calculate the depreciation expenses over the given period
    :param useful_years: Number of years the asset will be used
    :param purchase_value: Purchase expenditure for the asset
    :param residual_value: Residual value of the asset at the end of its useful life
    :return: A list of annual depreciation expenses over the asset's useful life
    >>> straight_line_depreciation(10, 1100.0, 100.0)
    [100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]
    >>> straight_line_depreciation(6, 1250.0, 50.0)
    [200.0, 200.0, 200.0, 200.0, 200.0, 200.0]
    >>> straight_line_depreciation(4, 1001.0)
    [250.25, 250.25, 250.25, 250.25]
    >>> straight_line_depreciation(11, 380.0, 50.0)
    [30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0]
    >>> straight_line_depreciation(1, 4985, 100)
    [4885.0]
    """

    if not isinstance(useful_years, int):
        raise TypeError("Useful years must be an integer")

    if useful_years < 1:
        raise ValueError("Useful years cannot be less than 1")

    if not isinstance(purchase_value, (float, int)):
        raise TypeError("Purchase value must be numeric")

    if not isinstance(residual_value, (float, int)):
        raise TypeError("Residual value must be numeric")

    if purchase_value < 0.0:
        raise ValueError("Purchase value cannot be less than zero")

    if purchase_value < residual_value:
        raise ValueError("Purchase value cannot be less than residual value")

    # Calculate annual depreciation expense
    depreciable_cost = purchase_value - residual_value

View on GitHub (pinned to f5988cc097)

Solutions

  1. Coerce to int before calling: int(useful_years) after confirming no precision is lost.
  2. Fix the source: parse CLI args with int(sys.argv[1]); tighten JSON schemas to integer type.
  3. If fractional years are a real requirement, this function cannot model them — scale periods yourself.

Example fix

# before
straight_line_depreciation(float(sys.argv[1]), 1250.0, 50.0)

# after
straight_line_depreciation(int(sys.argv[1]), 1250.0, 50.0)
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(useful_years, int) or isinstance(useful_years, bool):
    raise TypeError('useful_years must be int')
straight_line_depreciation(useful_years, purchase, residual)

Type guard

def is_int_years(v: object) -> bool:
    return isinstance(v, int) and not isinstance(v, bool)

Try / catch

try:
    sched = straight_line_depreciation(y, p, r)
except TypeError as exc:
    if 'Useful years' in str(exc):
        sched = straight_line_depreciation(int(y), p, r)
    else:
        raise

Prevention

When it happens

Trigger: Calling straight_line_depreciation(5.0, 1250.0, 50.0) (float years), straight_line_depreciation('5', ...) (string from CLI/JSON), or passing a Decimal. Booleans pass because bool subclasses int.

Common situations: Unparsed CLI arguments (always strings), JSON/YAML config where 5 is written as 5.0, or ORM/API fields typed as float. This is the first of six ordered checks, so it fires before any value checks.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/b85a5050965f09e6. Report an issue: GitHub.