【译文】Python–一种深受喜爱但永远存在缺陷的语言

Python 这门语言已经渗透到科技行业的各个角落,它的简洁性和易用性常常受到称赞。人工智能和数据科学等领域似乎都离不开它。

然而,当我们褪去便捷的外衣时,留给我们的却是一门挑战重重的语言,尤其是在长期开发和大型项目中。

写这篇文章的原因是什么?我一直在使用严格的语言,现在我加入了一个由 Python 开发团队牵头的项目。Python 与更严格的、以 JVM 为核心的语言 Go 或 C# 在开发流程上的差异可能会让人大吃一惊。请注意本文的偏见!

提要:随着项目规模的扩大,Python 最初的魅力往往会让人感到沮丧。它的简单性可能会导致复杂问题的出现,这使它成为长期开发的一个值得商榷的选择。

动态类型 = 无声错误的来源

Python 的动态类型是福也是祸。一方面,它允许灵活和快速的开发。另一方面,它可能导致难以察觉的细微错误。想象一下,在一个大型项目中,一个未键入的变量会在代码库中传播,导致一系列错误的连锁反应。

这些错误一直处于休眠状态,直到它们在运行时突然爆发,让开发人员束手无策。缺乏强制类型安全意味着 Python 在发现这些问题时为时已晚。虽然动态类型可以提高工作效率,但它也要求我们保持警惕并进行全面测试。

虽然动态类型赋予了灵活性,但也隐藏着潜在的危险。请看下面这个例子:

def calculate_total(items):
    total = 0
    for item in items:
        total += item
    return total

# Usage
shopping_cart = [10, 20, "30", 40]
print(calculate_total(shopping_cart))  # Oops! Concatenation instead of addition

在这种情况下,动态类型允许字符串 “30 “悄悄地溜进我们的数字计算中,导致了意想不到的行为。

简单?

Python 的简单语法经常被称赞为其标志。它鼓励可读性和简洁性,使其成为初学者的绝佳选择。然而,这种简单也可能具有欺骗性。

新手开发者被 Python 的优雅所吸引,可能会陷入编写 “能用 “但缺乏结构完整性的代码的陷阱。他们可能会优先考虑快速的解决方案,而不是长期的可维护性。

代码通过了初始测试,但当部署到生产环境中时,就会暴露出缺陷。简单的假象可能会导致代价高昂的错误,尤其是在项目发展和需求变化的情况下。

新手开发人员经常会陷入这样的陷阱:编写的代码 “能用”,但缺乏结构完整性。就拿这个代码段来说吧:

def divide(a, b):
    return a / b

result = divide(10, 0)  # Division by zero – a runtime disaster

代码通过了初始测试,但在生产中却会崩溃。简单的假象可能导致代价高昂的错误。

可扩展性问题

随着应用程序的增长,Python 的健壮性问题也变得显而易见。内存管理、并发性和性能都会受到严格审查。Python 的内存占用可能会意外膨胀,影响服务器资源。它的全局解释器锁(GIL)限制了真正的并行性,阻碍了多线程应用。

对于高流量系统来说,Python 的局限性变得非常明显。虽然 Python 在脚本编写和原型开发方面表现出色,但它却难以满足大规模生产级系统的需求。

Go 和 Java 等语言在设计时就考虑到了可扩展性,能为此类场景提供更好的解决方案。

随着项目的增长,Python 的健壮性问题也逐渐显现出来。内存管理和并发性成为瓶颈。例如

# Inefficient memory usage
def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)

# Try factorial(1000) – stack overflow!

Python 的递归方法会消耗过多内存,因此不适合高流量系统。

GIL 的遗产

全局解释器锁(GIL)是 Python 过去的遗留物,现在仍在困扰着它。GIL 最初是为了线程安全而引入的,它确保每次只有一个线程执行 Python 字节码。

这虽然简化了内存管理,却严重限制了多核利用率。在多核处理器无处不在的今天,Python 的 GIL 成了瓶颈。

开发人员不得不采用多进程等变通方法,这就带来了复杂性和开销。GIL 作为一个遗留问题一直存在,让那些追求真正并行性的人感到沮丧。

import threading

def perform_task():
    # Intensive task here

threads = [threading.Thread(target=perform_task) for _ in range(10)]
for thread in threads:
    thread.start()
for thread in threads:
    thread.join()
# Despite creating threads, the GIL limits true parallelism

 

不一致的语言设计

Python 的设计理念是一把双刃剑。虽然它鼓励创造力和实现目标的多种方法,但也会导致不一致。

不同的库可能会采用不同的约定,让开发者感到困惑。例如字符串格式化:f-strings.format() 和连接都是有效的方法。缺乏统一性会影响代码的可读性和可维护性。

相比之下,Kotlin 和 Java 等语言遵守更严格的准则,因此代码库更简洁、更可预测。

例如,实现相同结果的多种方法会导致混乱:

# String formatting options
name = "Alice"
greeting = f"Hello, {name}!"
# Or: greeting = "Hello, {}!".format(name)
# Or: greeting = "Hello, " + name + "!"

这种缺乏统一性的情况妨碍了代码的可读性和可维护性。与 Kotlin 相比,它甚至不是可读的语法。

地狱依赖

Python 的软件包管理可能是一个迷宫。安装第三方软件包的便利是有代价的:依赖冲突。随着项目依赖关系的积累,保持兼容性变得非常具有挑战性。不同的软件包可能需要相同库的冲突版本。

解决这些冲突需要侦查工作、反复试验,有时还需要妥协。即使是经验丰富的开发人员也会陷入臭名昭著的 “依赖地狱”,从而导致挫败感和时间的浪费。它几乎和 JavaScript 一样糟糕。

相互冲突的依赖关系就像一张纠缠不清的网:

# Two packages requiring different versions of the same dependency
import package_a  # Requires library X v1.0
import package_b  # Requires library X v2.0
# Result: Unpredictable behavior or runtime errors

缺乏现代功能

尽管 Python 广受欢迎,但它在采用现代编程功能方面却常常落后于其他语言。虽然最近的版本引入了类型提示和模式匹配,但其他语言很早就拥有了这些功能。

例如,Scala 的模式匹配多年来一直是主要功能。Python 的缓慢采用率会阻碍创新和生产率,尤其是当开发人员渴望用表现力强的工具来解决复杂问题时。

# Python 3.10 introduced pattern matching
match value:
    case 0:
        print("Zero")
    case _:
        print("Non-zero")
# But languages like Scala had this years ago

 

糟糕的重构支持

重构 Python 代码就像解开一张意大利面条网。它的动态特性使得自动重构工具变得非常谨慎。如果没有严格的类型,这些工具很难准确预测变更的影响。

# Refactoring this function is risky
def process_data(data):
    # Process data here

# Manual review and testing become essential

因此,开发人员在重构过程中往往依赖人工审核和大量测试。缺乏强大的重构支持会影响可维护性,并增加引入新错误的风险。

总结

很明显,Python 虽然在某些应用中很容易使用,也很受欢迎,但它充满了挑战,可能会阻碍开发,尤其是当项目的复杂性和规模不断扩大时。

总之,虽然 Python 可以提供一些便利功能,如 Django 管理和人工智能中的易用性,但这些并不能弥补其根本缺陷。对于强大的后端开发而言,开发人员最好使用能提供严格类型、更好性能和更一致设计理念的语言。对于严肃的开发工作来说,设计混乱、缺乏效率的 Python 往往不是最明智的选择。

对于那些寻求更可靠、更可扩展的解决方案的人来说,Kotlin、Java 或 Go 等语言提供了一种更有条理、更注重性能的方法,使它们成为严肃的后端开发的首选。

本文文字及图片出自 Python - a loved, but eternally flawed language

你也许感兴趣的:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注