Python 中 max() 函数的实现

Lew*_*wis 21 python

考虑:

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")
Run Code Online (Sandbox Code Playgroud)

我正在尝试用代码编写Python的max()函数。如果我在输入前面添加星号,它将不会通过第一个断言。如果我不这样做,就不会通过第二个断言。

我应该在输入中写什么才能传递两个断言,就像在 Python 的 max() 函数中那样?

Ray*_*ger 45

简短回答: 使用星号收集元组中的参数,然后为长度为 1 的元组添加特殊情况以处理单个可迭代参数。

源材料:处理逻辑的C代码可以在以下位置找到: https://github.com/python/cpython/blob/da20d7401de97b425897d3069f71f77b039eb16f/Python/bltinmodule.c#L1708

简化的纯 python 代码:如果忽略defaultkey关键字参数,剩下的内容将简化为:

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
Run Code Online (Sandbox Code Playgroud)

还有其他细微差别,但这应该可以帮助您入门。

文档:此处记录了一种情况与其他情况的长度的特殊处理:

返回可迭代中最大的项或两个或多个参数中最大的项。

如果提供了一个位置参数,它应该是一个可迭代的。返回可迭代对象中最大的项。如果提供了两个或多个位置参数,则返回位置参数中最大的一个。

更完整的版本: 这包括前面提到的一些细微差别,例如keydefault关键字参数以及使用迭代器而不是切片:

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)'
Run Code Online (Sandbox Code Playgroud)