有没有一种方法可以键入可以以二进制方式搜索元组的提示?

Is there a way to type hint that a tuple can be searched in a binary way?

你能告诉Python一个字符串列表是排序的并且可以用二进制方式搜索吗?

假设你有一个这样的字符串元组:

from typing import Tuple
words: Tuple[str] = ("alphabet", "bike", "car", "house", "word")

首先,我输入的提示是否正确? 其次,有没有办法告诉python这个元组可以用二进制方式搜索(因为它是排序的)还是不需要的?

类型注释应为 Tuple[t1, t2, ...],其中 t1, t2... 是相应元组值的类型。您键入的方式暗示了您的元组,这意味着它是一个包含单个字符串项的元组。

创建类型提示系统是为了将类似静态的声明带入 python,所以有两点需要注意

    如果您有 2-3 个项目的元组,
  • 注释元组就有意义(例如,Tuple[number, number] 表示一个 2D 点)。您拥有的是一个集合,最好将其注释为 Iterable[str].
  • 无法表示集合已排序,因为 type 注释仅注释 type,这与集合是否排序无关已排序。

你不能说元组是可以使用类型提示进行二进制搜索的。但是,您可以编写一个装饰器来包装您的函数,强制对所有输入元组进行排序。如果您有许多需要排序的元组作为输入的函数,这可能是个好主意。它不会修改元组(它不能——元组是不可变的)


def is_sorted(t):
    """ Returns true if the tuple, t, is sorted """
    return sorted(list(t)) == list(t)

def enforce_sort(func):
    def inner(*args, **kwargs):
        new_args = [None]*len(args) # Since args is a tuple, we can't modify it
        for n, arg in enumerate(args):
            new_args[n] = arg 
            if isinstance(arg, tuple):
                ## Do you want to sort it?
                new_args[n] = tuple(sorted(arg))
                ## Or do you wait to raise an exception if its not sorted?
                # if not is_sorted(arg):
                #     raise ValueError("Input tuple must be sorted")
        for k, v in kwargs.items():
            if isinstance(v, tuple):
                ## Do you want to sort it?
                kwargs[k] = tuple(sorted(v))
                ## Or do you want to raise an exception if its not sorted?
                # if not is_sorted(v):
                #    raise ValueError("Input tuple must be sorted")
        return func(*new_args, **kwargs)
    return inner

@enforce_sort
def show_twoples(t1, t2):
    """ prints two tuples, t1 and t2 """
    print(f"t1: {t1}")
    print(f"t2: {t2}")

a = (1,2,3,4,5) # Sorted
b = (9,8,6,4,2) # Not sorted
c = [1,2,6,2,3] # Not sorted, but not a tuple so it won't be affected
print(f"\nOriginal: t1 = {a}, t2 = {b}")
show_twoples(a, b)
print(f"\nOriginal: t1 = {b}, t2 = {a}")
show_twoples(b, a)
print(f"\nOriginal: t1 = {a} t2 = {c}")
show_twoples(a, c)
print(f"\nOriginal: t1 = {c}, t2 = {b}")
show_twoples(t1 = c, t2 = b)

输出:

Original: t1 = (1, 2, 3, 4, 5), t2 = (9, 8, 6, 4, 2)
t1: (1, 2, 3, 4, 5)
t2: (2, 4, 6, 8, 9)

Original: t1 = (9, 8, 6, 4, 2), t2 = (1, 2, 3, 4, 5)
t1: (2, 4, 6, 8, 9)
t2: (1, 2, 3, 4, 5)

Original: t1 = (1, 2, 3, 4, 5) t2 = [1, 2, 6, 2, 3]
t1: (1, 2, 3, 4, 5)
t2: [1, 2, 6, 2, 3]

Original: t1 = [1, 2, 6, 2, 3], t2 = (9, 8, 6, 4, 2)
t1: [1, 2, 6, 2, 3]
t2: (2, 4, 6, 8, 9)

根据您的需要,您可以在装饰器中自动对元组进行排序(这就是它现在所做的),或者如果元组未排序则可以引发异常(通过切换注释掉的部分) .