docs: def iterate(obj):
  	"""Loop over an iterable and track progress, including first and last state.
  	
  	On each iteration yield an Iteration named tuple with the first and last flags, current element index, total
  	iterable length (if possible to acquire), and value, in that order.
  	
  		for iteration in iterate(something):
  			iteration.value  # Do something.
  	
  	You can unpack these safely:
  	
  		for first, last, index, total, value in iterate(something):
  			pass
  	
  	If you want to unpack the values you are iterating across, you can by wrapping the nested unpacking in parenthesis:
  	
  		for first, last, index, total, (foo, bar, baz) in iterate(something):
  			pass
  	
  	Even if the length of the iterable can't be reliably determined this function will still capture the "last" state
  	of the final loop iteration.  (Basically: this works with generators.)
  	
  	This process is about 10x slower than simple enumeration on CPython 3.4, so only use it where you actually need to
  	track state.  Use `enumerate()` elsewhere.
  	"""
  	
  	global next, Iteration
  	next = next
  	Iteration = Iteration
  	
  	total = len(obj) if isinstance(obj, Sized) else None
  	iterator = iter(obj)
  	first = True
  	last = False
  	i = 0
  	
  	try:
  		value = next(iterator)
  	except StopIteration:
  		return
  	
  	while True:
  		try:
  			next_value = next(iterator)
  		except StopIteration:
  			last = True
  		
  		yield Iteration(first, last, i, total, value)
  		if last: return
  		
  		value = next_value
  		i += 1
  		first = False