八个重构技巧使得Python代码更Pythonic

开发 前端
如果你已经熟悉生成器,那么这是一个高级技巧。一个经常被忽略的小技巧是 Python 的 yield​ 关键字对于可迭代对象有一个对应的yield from。

1.合并追加到列表声明

我们从一个简单的开始。不是声明一个空列表然后附加到它,而是直接用所有元素初始化列表。这缩短了代码并使意图更加明确。它的性能也稍微好一些,因为它避免了对 append() 的函数调用。

players = []
players.append("Patrick")
players.append("Max")
players.append("Jessi")

# -> refactor
players = ["Patrick", "Max", "Jessi"]

这同样适用于填充其他集合类型,如集合和字典。

2 使用items()直接解包字典值

当遍历字典时,你需要键和值,那么不要手动访问值。而是迭代dictionary.items(),它同时为你提供键和值。

这节省了我们过去分配给 players 的行,代码现在读起来更自然,重复更少。

teams_by_color = {"blue": ["Patrick", "Jessi"]}

for team_color in teams_by_color:
players = teams_by_color[team_color]
if is_winning(team_color):
advance_level(players)

# -> refactor
for team_color, players in teams_by_color.items():
if is_winning(team_color):
advance_level(players)

3. 将 range(len) 替换为枚举

如果我们需要遍历列表并且需要同时跟踪索引和当前项,请使用内置enumerate()​函数而不是range(len)。这会将当前索引和当前项目作为元组返回。所以我们可以直接在这里查看值,也可以访问带有索引的项目。

for i in range(len(players)):
print(i, players[i])

# -> refactor
for i, player in enumerate(players):
print(i, player)

Enumerate​ 还带有一个可选的start参数。如果你使用它,计数器将从该值开始。但请注意,这些项目仍然从第一个开始。

for i, player in enumerate(players, start=1):
print(i, player)

4. 用枚举调用替换手动循环计数器

这与之前非常相似。有时我会看到直接对项目执行迭代的代码——这本身并不坏——但随后需要一个计数器,它会在循环内手动递增。同样在这里你可以简单地使用 enumerate 函数。这更简单,也更快。

i = 0
for player in players:
print(i, player)
i += 1

# -> refactor
for i, player in enumerate(players):
print(i, player)

4.1 不要手动更新计数器

如果你只需要计算项目的数量,也不要遍历循环并手动计算所有项目。相反,只需使用len()函数来获取列表中的元素数。

num_players = 0
for player in players:
num_players += 1

# -> refactor
num_players = len(players)

5.将条件简化为return语句

当我们到达一个方法的末尾并想要返回 True​ 或 False​ 时,一种常见的做法是这样的。如果条件为 True​,我们返回 True​。否则我们最后返回 False。然而,直接返回结果更简洁:

def function():
if isinstance(a, b) or issubclass(b, a):
return True
return False

# -> refactor
def function():
return isinstance(a, b) or issubclass(b, a)

我们在这里应该注意的一件事是,只有当表达式的计算结果为布尔值时才能这样做。isinstance()和issubclass()都是返回布尔值的函数,所以这很好。但在下一个示例中,第一个表达式pythonistas是一个列表而不是布尔值。

如果pythonistas​是一个有效的非空列表,这将返回列表而不是预期的布尔值,然后可能是你的应用程序中的错误。因此,为了确保我们在这里返回一个布尔值,我们可以将返回包装在对 bool()函数的调用中。

def any_pythonistas():
pythonistas = [coder for coder in coders if is_good_in_python(coder)]
if pythonistas or self.is_pythonista():
return True
return False

# -> refactor
def any_hats():
pythonistas = [coder for coder in coders if is_good_in_python(coder)]
return bool(pythonistas or self.is_pythonista())

6.合并条件中的重复块

我们应该始终寻找机会删除重复的代码。这样做的好地方是if …elif链中有多个相同的块。

在此示例中,if​ 和 elif​ 都导致相同的执行功能。所以我们可以使用or​组合前两个块来删除对函数的重复调用。现在,如果我们需要更改process_standard_payment()行,我们可以在一处而不是两处进行。

def process_payment(payment, currency):
if currency == "USD":
process_standard_payment(payment)
elif currency == "EUR":
process_standard_payment(payment)
else:
process_international_payment(payment)

# -> refactor
def process_payment(payment, currency):
if currency == "USD" or currency == "EUR":
process_standard_payment(payment)
else:
process_international_payment(payment)

7.用in运算符替换同一个变量的多次比较

我们甚至可以进一步重构以前的代码。由于我们针对多个值重复检查同一个变量,我们可以使用 in 运算符来缩短它。如果货币值在定义的列表中,我们将执行专用操作。

def process_payment(payment, currency):
if currency == "USD" or currency == "EUR":
process_standard_payment(payment)
else:
process_international_payment(payment)

# -> refactor
def process_payment(payment, currency):
if currency in ["USD", "EUR"]:
process_standard_payment(payment)
else:
process_international_payment(payment)

为了再次改进这一点,我们应该在这里使用一个集合。在集合中查找值更快,而且无论如何我们都想要这里的唯一元素,所以集合是更好的选择。

# -> refactor
def process_payment(payment, currency):
if currency in {"USD", "EUR"}:
process_standard_payment(payment)
else:
process_international_payment(payment)

8. 将 for 循环中的 yield 替换为 yield from

如果你已经熟悉生成器,那么这是一个高级技巧。一个经常被忽略的小技巧是 Python 的 yield​ 关键字对于可迭代对象有一个对应的yield from。

如果你有一个像列表这样的可迭代对象,而不是说for item in iterable: yield item​,你可以简单地说yield from iterable。这更短,并且消除了对可迭代对象的手动循环,这也可以提高性能。

def get_content(entry):
for block in entry.get_blocks():
yield block

# -> refactor
def get_content(entry):
yield from entry.get_blocks()
责任编辑:武晓燕 来源: 数据STUDIO
相关推荐

2023-02-06 12:00:00

重构PythonPythonic

2023-09-26 12:04:15

重构技巧Pythonic

2024-03-27 14:06:58

Python代码开发

2012-10-29 11:01:17

2024-03-21 09:58:27

ExtractTypeScript工具类型

2022-12-15 16:38:17

2021-12-10 13:06:37

低代码无代码开发人员

2024-04-01 07:51:49

Exclude​工具类型TypeScript

2022-03-18 21:27:36

Python无代码

2024-03-06 13:56:00

项目awaitpromise

2022-08-19 14:24:30

forPythonpythonic

2010-08-11 16:43:05

职场

2011-09-25 10:46:18

云计算安全

2010-08-25 11:14:05

云安全数据安全网络安全

2010-09-09 13:44:06

DIVCSS

2023-10-24 09:25:23

IT技巧文化

2022-05-30 00:04:16

开源Github技巧

2022-07-25 15:21:50

Java编程语言开发

2024-03-08 08:00:00

Python开发装饰器

2023-01-03 11:47:47

点赞
收藏

51CTO技术栈公众号