4

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

 2 months ago
source link: https://www.techug.com/post/python-a-loved-but-eternally-flawed-language/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK