Considerar:
def my_max(*a): n = len(a) max_v = a[0] for i in range (1,n): if a[i] > max_v: max_v = a[i] return max_v def my_min(*a): n = len(a) min_v = a[0] for i in range (1,n): if a[i] < min_v: min_v = a[i] return min_v test = [7, 4, 2, 6, 8] assert max(test) == my_max(test) and min(test) == my_min(test) assert max(7, 4, 2, 5) == my_max(7, 4, 2, 5) and min(7, 4, 2, 5) == my_min(7, 4, 2, 5) print("pass")Estoy tratando de escribir la función max() de Python en código. Si agrego el asterisco delante de la entrada, no pasará la primera afirmación. Si no lo hago, no pasaría la segunda afirmación.
¿Qué debo escribir en la entrada para que pase ambas afirmaciones, como lo hace en la función max() de Python?
Respuesta corta: use una estrella para recopilar los argumentos en una tupla y luego agregue un caso especial para una tupla de longitud uno para manejar un solo argumento iterable.
Material de origen: el código C que maneja la lógica se puede encontrar en: https://github.com/python/cpython/blob/da20d7401de97b425897d3069f71f77b039eb16f/Python/bltinmodule.c#L1708
Código python puro simplificado : si ignora los argumentos de palabra clave predeterminados y clave , lo que queda se simplifica a:
def mymax(*args): if len(args) == 0: raise TypeError('max expected at least 1 argument, got 0') if len(args) == 1: args = tuple(args[0]) largest = args[0] for x in args[1:]: if x > largest: largest = x return largestHay otros matices, pero esto debería ayudarlo a comenzar.
Documentación: El manejo especial para la longitud de un caso frente a otros casos se documenta aquí :
Devuelve el elemento más grande en un iterable o el más grande de dos o más argumentos.
Si se proporciona un argumento posicional, debe ser iterable. Se devuelve el elemento más grande del iterable. Si se proporcionan dos o más argumentos posicionales, se devuelve el mayor de los argumentos posicionales.
Versión más completa: incluye algunos de los matices antes mencionados, como los argumentos de palabras clave clave y predeterminados , y el uso de iteradores en lugar de segmentos:
sentinel = object() def mymax(*args, default=sentinel, key=None): """max(iterable, *[, default=obj, key=func]) -> value max(arg1, arg2, *args, *[, key=func]) -> value With a single iterable argument, return its biggest item. The default keyword-only argument specifies an object to return if the provided iterable is empty. With two or more arguments, return the largest argument. """ if not args: raise TypeError('max expected at least 1 argument, got 0') if len(args) == 1: it = iter(args[0]) else: if default is not sentinel: raise TypeError('Cannot specify a default for max() with multiple positional arguments') it = iter(args) largest = next(it, sentinel) if largest is sentinel: if default is not sentinel: return default raise ValueError('max() arg is an empty sequence') if key is None: for x in it: if x > largest: largest = x return largest largest_key = key(largest) for x in it: kx = key(x) if kx > largest_key: largest = x largest_key = kx return largest # This makes the tooltips nicer # but isn't how the C code actually works # and it is only half correct. mymax.__text_signature__ = '($iterable, /, *, default=obj, key=func)'