什么样的函数才叫 Pythonic

1. Pythonic是什么?

Pythonic一词是源自于Python编程语言的一个词汇,它强调了Python代码要有易读性和简洁性的特点。Pythonic的定义可以归纳为“使用Python语言特性、风格和习惯的代码”。

2. Pythonic函数是什么样的?

Pythonic函数是指那些呈现Python语言特性和最佳实践的函数。这些函数通常容易理解,风格简洁,易读和易维护。Pythonic函数通常包括以下特点:

2.1. 易读性

Pythonic函数要尽可能地使代码容易阅读。它们应该使用简单且易于理解的变量名称,并通过加注释来解释关键部分的操作。

def calculate_area_of_circle(radius: float) -> float:

"""Calculate the area of a circle."""

area = 3.14 * (radius ** 2)

return area

在上面的代码示例中,函数名和文档字符串描述了函数计算圆面积的操作,而参数和返回值的类型则告诉了使用者需要提供什么类型的参数和函数将返回什么类型的值。

2.2. 简化代码

Pythonic函数通过优化代码结构和语法来简化代码。这通常包括利用语言特性(如列表解析)和标准库功能来简化重复或冗余的操作。

def get_only_active_users(users: List[Dict[str, Any]]) -> List[Dict[str, Any]]:

"""Get a list of active users."""

active_users = [user for user in users if user.get('is_active')]

return active_users

上述代码示例使用列表解析来筛选出字典列表中的所有活跃用户。它略微缩短了代码并增强了代码的可读性。

2.3. 函数默认参数

Pythonic函数使用默认参数来减少冗余的代码。它们利用了Python的可选参数功能和可迭代数据类型。

def get_name_initials(name: str, middle_name: str = '', last_name: str = '') -> str:

"""Get the initials of the given name."""

initials = [n[0].upper() for n in [name, middle_name, last_name] if n]

return '. '.join(initials) + '.'

上述代码示例演示了如何使用函数默认参数缩短代码。当用户提供姓、名和中间名时,可以创建一个包含所有名称首字母的列表。通过使用列表推导来删除空字符串,您可以仅返回提供的初始化列表。

2.4. 返回多种数据类型

Pythonic函数通常比较灵活,不仅应该能够返回多种不同的数据类型,还可以处理各种Python数据类型。

def get_average(numbers: Union[int, List[int], Tuple[int]]) -> Union[float, List[float]]:

"""Get the average of a single number, a list of numbers or a tuple of numbers."""

if isinstance(numbers, int):

return numbers

elif isinstance(numbers, (list, tuple)):

return sum(numbers) / len(numbers)

上述代码实现了一个Pythonic函数,它可以接受非常不同的输入类型(单个数字,数字列表或数字元组),并根据输入返回不同类型的结果。

2.5. 遵循PEP8规范

Pythonic函数必须符合PEP8编码规范,这使得Pythonic代码易于阅读和维护。遵循编码规范可以让代码更具有可读性,并有助于减少后期维护的时间和精力。

def get_upper_case_count(word: str) -> int:

"""Return the number of uppercase characters in a given string."""

return len([char for char in word if char.isupper()])

上述代码示例符合PEP8规范,包括使用四个空格的缩进,适当的注释和括号内的空格等。

3. 非Pythonic函数是什么样的?

非Pythonic函数是不符合Python编程规范的函数。它们可能更难理解和维护的代码,并且可能包含不必要的重复代码或长的过程。以下是一些非Pythonic函数的例子:

3.1. 过度使用if语句

这是一个典型的非Pythonic函数,主要是用于过度使用if语句。使用太多的if语句会使代码更加复杂和难以维护。

def check_passing_score(score: int) -> bool:

"""Check if a given score is passing or not."""

if score >= 70:

return True

else:

if score >= 60:

return True

else:

return False

上述代码示例看起来冗长、笨重且难以阅读。在此示例中,可以重构代码以使用单个if语句和Python三元运算符来使其更Pythonic。

def check_passing_score(score: int) -> bool:

"""Check if a given score is passing or not."""

return True if score >= 70 else False

3.2. 过多重复代码

以下是一个非Pythonic函数的示例,其中包含重复的代码,没有利用Pythonic的for循环结构及列表解析特性,这使代码显得混乱且难以维护。

def remove_duplicates_from_list(alist: List[str]) -> List[str]:

"""Remove duplicates from a given list of strings."""

unique = []

for x in alist:

if x not in unique:

unique.append(x)

new_list = []

for x in unique:

new_list.append(x)

return new_list

上述代码示例可以重构为如下Pythonic代码:

def remove_duplicates_from_list(alist: List[str]) -> List[str]:

"""Remove duplicates from a given list of strings."""

return list(set(alist))

如你所见,这个Pythonic的函数更短,更容易理解和维护,因为我们使用了列表解析和集合来减少长代码行。

3.3. 函数过长

这是另一个非Pythonic函数的示例。这个函数太长了,没有被模块化,导致难以维护和重用。

def calculate_distance_of_points(point1: Tuple[int], point2: Tuple[int]) -> float:

"""Calculate the distance between two points."""

x1, y1 = point1

x2, y2 = point2

dx = x2 - x1

dy = y2 - y1

return sqrt(dx ** 2 + dy ** 2)

上述代码示例可以重构为使用较小和更可读的Pythonic函数,以便提高代码可维护性和可重用性。

def get_dx(x1: int, x2: int) -> int:

"""Get the delta x between two points."""

return x2 - x1

def get_dy(y1: int, y2: int) -> int:

"""Get the delta y between two points."""

return y2 - y1

def calculate_distance_of_points(point1: Tuple[int], point2: Tuple[int]) -> float:

"""Calculate the distance between two points."""

x1, y1 = point1

x2, y2 = point2

dx = get_dx(x1, x2)

dy = get_dy(y1, y2)

return sqrt(dx ** 2 + dy ** 2)

4. 结论

Pythonic的函数可以清晰明了地传达代码的含义,减少了代码的冗余和歧义,并遵循编码规范,使得代码更易于检查和维护。Pythonic的函数应该遵循各种最佳实践和Python语言特有的规则,例如:遵循PEP8编码规范,使用列表解析来替换冗余的for循环,使用默认参数等。Pythonic函数也通常与函数式编程的一些概念和惯用法结合使用,例如匿名函数和map reduce。因此,尽可能写出Pythonic的代码可以使我们的代码更有可读性和可维护性,并且可以减少开发时间和重构代码的工作量。

后端开发标签