Python 使用非严格字典规则,Python 3.6之前没有定义字典键的顺序。如果试图创建一个包含多个项的字典,且这些项共享同一个键值,那么最终生成的dict
对象只会保留其中一项。我们无法定义被保留的是这些重复键值中的哪一个,但只要设计的算法是正确的,这一点便无关紧要。
典型结果如下所示。最后一个值会替换任何先前的值。但在Python 3.6之前,无法保证这种情况一定会发生。
>>> {'a': 1, 'a': 2}
{'a': 2}
在这种情况下,无须在意需要保留哪一个重复键。下面是max()
函数的一个简化版本,它简单地选取了两个值中较大的那个。
def non_strict_max(a, b):
f = {a >= b: lambda: a,
b >= a: lambda: b}[True]
return f()
对于a == b
的情况,字典中的两项都会得到条件为True
的键,但其中只有一个会保留下来。由于这两个结果一样,因此保留哪个或将哪个视为重复并进行覆盖并不重要。
请注意,该函数的正规类型提示非常复杂。进行比较的项必须是可排序的,即它们必须将运算符排序。下面定义一个适用于可排序对象概念的类型。
from abc import ABCMeta, abstractmethod
from typing import TypeVar, Any
class Rankable(metaclass=ABCMeta):
@abstractmethod
def __lt__(self, other: Any) -> bool: ...
@abstractmethod
def __gt__(self, other: Any) -> bool: ...
@abstractmethod
def __le__(self, other: Any) -> bool: ...
@abstractmethod
def __ge__(self, other: Any) -> bool: ...
RT = TypeVar('RT', bound=Rankable)
类Rankable
的定义是一个抽象类。针对某些有用的函数定义,这个类借助abc
模块来将类定义中的抽象特性具象化。装饰器@abstractmethod
用于确定任何具体且实用的子类必须定义的方法函数。
之后可以将non_strict_max()
函数的参数类型和返回值类型绑定为类型变量RT
。包含类型提示的定义如下所示(此处省略了函数主体,上文已经给出了):
def non_strict_max(a: RT, b: RT) -> RT:
这里阐明了接收的两个参数a
和b
应是可排序的类型,并被指定为了RT
类型。返回值的可排序类型相同。这样就厘清了max()
的基本语义,即参数的类型必须一致,返回值的类型也和参数的类型相同。