Python技巧:停止使用“or”检查多个条件

我们都熟悉使用这两行来检查变量是否满足一个或多个等式。

if number == 1 or number == 2 or number == 3 or number == 4:
  do_smt()

这种方式编码显得非常的自然,大家也经常使用。

但我们今天说另外一个好的解决方案,接下来我将给出几种方法,我们将分析它们的优缺点。

Python中的”in”运算符

in 关键字在 Python 中基本上有两种用法:

1:遍历一个序列:

例子:

seasons = ["winter", "spring", "summer", "autumn"]

for season in seasons:
    print(season)

winter
spring
summer
autumn

2:检查一个值是否存在于一个序列(字符串、元组、列表等)中。根据值的存在,返回 True 或 False 。

示例 1:

seasons = ["winter", "spring", "summer", "autumn"]

print("summer" in seasons)
print("july" in seasons)

True
False

示例 2:

现在让我们看一下这个示例:

print("in" in "in operator in Python")

让我们把到目前为止学到的所有东西放在一起,看下优雅的解决方案。

我们用”in”代替”or”

这是我们的第一个例子:

if number == 1 or number == 2 or number == 3 or number == 4:
  do_smt()

改用in

if number in [1, 2, 3, 4]:
  do_smt()

这意味着如果列表中存在number,则满足条件并执行do_smt()。换句话说,如果 number 等于列表中的任何值,do_smt() 将运行。请注意,最后一句中的”任何”与”or”具有确切的含义和功能。这就是为什么可以替换或使用 in 的原因——两者具有相同的目的。

为什么以及何时我们应该更喜欢”in”而不是”or”

我们可以很容易地遵循条件。在多个条件的情况下,使用 in 关键字大大提高了可读性。

例如,在 Django REST Framework (DRF) 中,如果我们要测试请求是否为只读操作,我们只需检查请求的 HTTP 方法 (request.method) 是否存在于 SAFE_METHODS 中,它只是一个元组 包含 “GET” 、 “HEAD” 和 “OPTIONS” 。

if request.method in permissions.SAFE_METHODS:

让我们明确地编写 permissions.SAFE_METHODS 以更好地理解:

if request.method in ("GET", "HEAD", "OPTIONS"):

阅读和遵循条件的目的非常简单。我们可以很容易地看到有多少条件以及它们是什么。如果我问你,这里会检查哪些条件,你可以很容易地回答这个问题。

在使用or的情况下,我们需要这样写:

if request.method == "GET" or request.method == "HEAD" or request.method == "OPTIONS":

就可读性而言,最后一个似乎不太友好,因为它有重复,而且是一条长线!

使用in方案是最好的吗?

这取决于你如何定义”最佳”。如果你正在寻找可读性,很明显 in 是最好的。

在使用 in 时,我们不应该只使用一种数据类型来限制自己。我们将看看 list 、 tuple 和 set 。

比较执行时间

我将使用 timeit 模块来测量执行时间。我们将比较 4 种不同的用法。所以这将是 1(或)vs 3(在 list 、 tuple 和 set 中)。

文章其余部分的顺序相同:

in [] - list
in () - tuple
in {} - set
or

我将执行每一个 100000 次。此外,我决定重命名请求的 HTTP 方法方法。

import timeit

method = "GET"

print(timeit.timeit('method in ["GET", "HEAD", "OPTIONS"]', globals=globals(), number=100000))
print(timeit.timeit('method in ("GET", "HEAD", "OPTIONS")', globals=globals(), number=100000))
print(timeit.timeit('method in {"GET", "HEAD", "OPTIONS"}', globals=globals(), number=100000))
print(timeit.timeit('method == "GET" or method == "HEAD" or method == "OPTIONS"', globals=globals(), number=100000))

0.0018657920008990914
0.0018152919947169721
0.00212829202064313
0.0020830420253332704

虽然我执行了 100000 次语句,仍然很难确定哪个更好,但我们可以说元组稍微好一点。

注意:timeit.timeit 中的 globals 参数用于访问全局命名空间中定义的变量。这样,我们就不会计算将”GET”值分配给方法变量所需的时间。否则,我们需要修改它:

print(timeit.timeit('method = "GET"; method in ["GET", "HEAD", "OPTIONS"]', globals=globals(), number=100000))

如果我们想评估最坏的情况怎么办。此时,将满足最后一个条件,而不是第一个条件。

import timeit

method = "OPTIONS"

print(timeit.timeit('method in ["GET", "HEAD", "OPTIONS"]', globals=globals(), number=100000))
print(timeit.timeit('method in ("GET", "HEAD", "OPTIONS")', globals=globals(), number=100000))
print(timeit.timeit('method in {"GET", "HEAD", "OPTIONS"}', globals=globals(), number=100000))
print(timeit.timeit('method == "GET" or method == "HEAD" or method == "OPTIONS"', globals=globals(), number=100000))

0.0035216250689700246
0.0032744579948484898
0.002372542046941817
0.007088540936820209

现在,集合是有利的或表现出最差的表现。实际上,与之前的结果相比,集合并没有太大的变化,因为这个过程的集合具有 O(1) 的时间复杂度:

x in list   ---> O(n)
x in tuple  ---> O(n)
x in set    ---> O(1)

比较内存使用情况

我们可以使用 sys.getsizeof() 来计算对象的内存消耗。

mport sys

print(sys.getsizeof(["GET", "HEAD", "OPTIONS"]))
print(sys.getsizeof(("GET", "HEAD", "OPTIONS")))
print(sys.getsizeof({"GET", "HEAD", "OPTIONS"}))

120
64
216

就内存而言,元组比其他数据容器更好。但是,当我们使用or我们不创建任何序列时,or是内存竞争的赢家!

写在最后:

使用 in 是检查多个条件的时尚方式。它使代码更具可读性和可维护性。我更喜欢使用 in with sets,因为在考虑性能时 in 关键字是有利的。它还向其他程序员会考虑运行时间问题,可以使用具有 O(1) 时间复杂度的数据类型。如果你的项目(如嵌入式系统)的内存有限,那么在这种情况下使用元组是有意义的。

Original: https://blog.csdn.net/qq_42627619/article/details/124104894
Author: 键盘舞蹈者
Title: Python技巧:停止使用“or”检查多个条件

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/735795/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球