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")
I am trying to write the max() function of python in codes. If I add the asterisk in front of the input, it won't pass the first assertion. If I don't it wouldn't pass the second assertion. What should I write in input for it to pass both assertions like it does in max() function of python?
CodePudding user response:
Short answer: Use a star to collect the arguments in a tuple and then add a special case for a tuple of length one to handle a single iterable argument.
Source material: The C code that handles the logic can be found at: https://github.com/python/cpython/blob/da20d7401de97b425897d3069f71f77b039eb16f/Python/bltinmodule.c#L1708
Simplified pure python code: If you ignore the default and key keyword arguments, what's left simplifies to:
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 largest
There are other nuances, but this should get you started.
Documentation: The special handling for the length one case versus other cases is documented here:
Return the largest item in an iterable or the largest of two or more arguments.
If one positional argument is provided, it should be an iterable. The largest item in the iterable is returned. If two or more positional arguments are provided, the largest of the positional arguments is returned.
More complete version: This includes some of aforementioned nuances like the key and default keyword arguments and the use of iterators instead of slices:
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)'