returns the maximum product that can be obtained by multiplying a contiguous subarray of the given integer list nums example maxproductsubarray2 3 2 4 6 maxproductsubarray2 0 1 0 maxproductsubarray2 3 2 4 1 48 maxproductsubarray1 1 maxproductsubarray0 0 maxproductsubarray 0 maxproductsubarray 0 maxproductsubarraynone 0 maxproductsubarray2 3 2 4 5 1 traceback most recent call last valueerror numbers must be an iterable of integers maxproductsubarrayabc traceback most recent call last valueerror numbers must be an iterable of integers update the maximum and minimum subarray products update the maximum product found till now returns the maximum product that can be obtained by multiplying a contiguous subarray of the given integer list nums example max_product_subarray 2 3 2 4 6 max_product_subarray 2 0 1 0 max_product_subarray 2 3 2 4 1 48 max_product_subarray 1 1 max_product_subarray 0 0 max_product_subarray 0 max_product_subarray 0 max_product_subarray none 0 max_product_subarray 2 3 2 4 5 1 traceback most recent call last valueerror numbers must be an iterable of integers max_product_subarray abc traceback most recent call last valueerror numbers must be an iterable of integers update the maximum and minimum subarray products update the maximum product found till now
def max_product_subarray(numbers: list[int]) -> int:
    
    if not numbers:
        return 0

    if not isinstance(numbers, (list, tuple)) or not all(
        isinstance(number, int) for number in numbers
    ):
        raise ValueError("numbers must be an iterable of integers")

    max_till_now = min_till_now = max_prod = numbers[0]

    for i in range(1, len(numbers)):
        
        number = numbers[i]
        if number < 0:
            max_till_now, min_till_now = min_till_now, max_till_now
        max_till_now = max(number, max_till_now * number)
        min_till_now = min(number, min_till_now * number)

        
        max_prod = max(max_prod, max_till_now)

    return max_prod