您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

关于 Python,一些不得不吐槽的“迷惑行为”

时间:2022-09-12 10:56:21  来源:CSDN  作者:

摘要:随着大数据与人工智能时代的到来,Python/ target=_blank class=infotextkey>Python 近年来颇受程序员喜爱,在 TIOBE 编程语言排行榜中也稳居第一。但这并不说明 Python 毫无缺点,本文作者就将盘点一些 Python 的“迷惑性为”。

原文链接:https://medium.com/geekculture/why-python-still-is-a-mess-1f7bf5bca281

作 者 |Ari Joury

译者| 弯月

出品 | CSDN(ID:CSDNnews)

长期以来,Python一直自诩是最适合新手程序员的语言之一。话虽没错,但这并不意味着编程新手不会对Python的一些行为感到困惑。

举个例子,动态类型。你无需单独编写一行代码来定义变量的类型,Python能够自行分辨,乍一看之下,这似乎很神奇。感觉这样编程速度更快。

然而,就因为少了一行变量定义,整个项目在运行结束之前就有可能崩溃。

说句公道话,许多其他编程语言也使用动态类型。但对于Python而言,这只是一系列噩梦的开始。

隐式的变量声明会影响阅读代码

几年前,我想在同事编写的一个软件的基础之上,进行二次开发。我知道该软件的基本思想,我的同事甚至写了一篇论文作为该软件的文档。

但是,我仍然需要阅读数千行 Python 代码,才能搞清楚各个部分在干什么,以及我可以将新功能放到哪里。然而,就在这个过程中,我遇到了很大的问题……

纵观整个代码库,变量声明到处都是。为了搞清楚每个变量的用途,我不得不搜索整个文件,甚至是整个项目。

此外,还有各种各样的复杂情况,比如函数的某个参数的名字和调用该函数时使用的变量完全不同,或者一个变量与某个类紧密结合,而该类又和另一个类中的某个变量交织在一起……诸如此类的事情层出不穷。

很多人都有类似的感觉,有人就曾表示显式变量声明优于隐式(参考链接:https://peps.python.org/pep-0020/)。但是,在Python中隐式变量声明比比皆是,尤其是在大型项目中。

无处不在的可变类型,甚至在函数中

在 Python 中,定义函数的时候可以指定可选参数,即不需要明确指定的参数。如下所示:

defadd_five(a, b= 0) : returna + b + 5

通过这个简单的示例可以看出,在调用函数时,无论指定一个参数还是两个参数都可以:

add_five(3) # returns 8 add_five(3,4) # returns 12

之所以会出现这种现象,是因为表达式b=0定义了b是一个整数,而整数是不可变的。再看看下面这个例子:

def add_element( list=[]): list.Append( "foo") returnlist add_element # returns ["foo"], as expected

发现问题了吗?再执行一次会怎么样?

  • add_element # returns [ "foo", "foo"]! wtf!

因为这里的list已经存在,即["foo"],而Python会继续向这个列表添加新东西。这是因为列表与整数不同,是可变类型。

我不禁想起一句话:“疯子就是不断重复同一件事,却期待不同的结果。”(经考证,这句话不是爱因斯坦说的)。我想说,Python + 可选参数 + 可变对象 = 疯子。

类变量并不安全

如果你认为上述问题仅限于可变对象作为可选参数的时候,那你就大错特错了。

相信你也使用Python编写面向对象的代码,在Python代码中类无处不在。而类最实用的特性之一便是:继承。

简单来说,如果父类具有某些属性,子类就可以继承这些属性。如下所示:

classparent(object): x = 1 classfirstchild(parent): pass classsecondchild(parent): pass print(parent.x, firstchild.x, secondchild.x) # returns 1 1 1

注意,这段代码写得并不好,不要复制到实际的项目中。关键在于,子类继承了 x = 1,因此我们可以获取子类的这个属性,得到的结果与父类相同。

如果我们修改某个子类的x属性,那么理应说变化的只有这个子类。就好像孩子染发不可能改变父母亲或兄弟姐妹的发色。代码如下:

firstchild.x = 2 print( parent.x, firstchild.x, secondchild.x) # returns 1 2 1

如果这时父母染发,孩子的发色会变吗?不会变,对不对?

parent.x = 3 print( parent.x, firstchild.x, secondchild.x) # returns 3 2 3

出现这个结果是因为Python的方法解析顺序(http://python-history.blogspot.com/2010/06/method-resolution-order.html)。简单来说,只要没有另行说明,子类就会继承父类拥有的一切。也就是说,在Python的世界里,如果你不提前抗议,那么你妈妈在染头发的时候,会顺带连你的头发一起染了。

反方向的作用域

我个人已经因为这个问题多次栽跟头。

在Python中,函数内部定义的变量无法在函数外部使用,这是因为超出了作用域:

def myfunction(number): basenumber = 2 return basenumber*number basenumber ## Oh no! This is the error: #Traceback (most recent call last): #File "<stdin>", line 1, in<module> #NameError: name 'basenumber'is not defined

这部分完全符合直觉,我栽跟头也不是因为这部分代码。

但是反过来呢?我的意思是,如果我在函数外部定义一个变量,然后在函数内部引用它呢?

x = 2 def add_5: x = x + 5 print(x) add_5 ## Oh dear... #Traceback (most recent call last): #File "<stdin>", line 1, in<module> #File "<stdin>", line 2, inadd_y #UnboundLocalError: localvariable 'x'referenced before assignment

这就很奇怪了,不是吗?我们生活在一个有树的世界里,虽然平时我们住在房子里,但肯定也知道树长什么样子,对不对?(树是 x,房子是 add_5,我们是 5……)

有好多次,我在某个类中调用另一个类中定义的函数,就遇到了错误。我花了很长一段时间才找到问题的根源。

其背后的基本思想是,函数内部的 x 与外部的 x 是不同的,所以你不能在外部调用它。

幸运的是,这个问题有一个简单的解决方案,即在 x 之前加一个global,让x变成全局变量!

x = 2 defadd_5: globalx x = x + 5 print(x) add_5 # works!

所以说,如果你认为作用域的目的仅仅是保护函数内部的变量不被外部干扰,那就大错特错了。在Python中,局部作用域也无法访问外部。

在迭代的过程中修改列表

请看如下代码:

mynumbers = [ x forx inrange( 10)] # thisis[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] forx inrange( len(mynumbers)): ifmynumbers[x]%3 == 0: mynumbers. remove(mynumbers[x]) ## Ew! # Traceback (most recent call last): # File "<stdin>", line2, in <module> # IndexError: list index out of range

这个循环出错,是因为循环在迭代的过程中不断删除列表中的元素。因此,列表不断缩短,循环不可能到达第10个元素,因为它不存在了!

有一种解决方法是,为你想删除的所有元素统一分配一个值,然后在循环结束后删除它们。

此外,似乎还有一种更好的解决方式:

mynumbers = [ x forx inrange( 10) ifx%3 ! = 0] # that's what we wanted! [1, 2, 4, 5, 7, 8]

只需要一行代码!

请注意,在上面的示例中,我们使用了 Python 的列表推导式来调用列表。

列表推导式指的是方括号([])中的表达式,一般都是循环的缩写形式。列表推导式通常比常规循环更快,因此非常适合处理大型数据集。

在这个示例中,我们添加了一个 if 子句来告诉列表推导式:不应包含可被 3 整除的数字。

这个问题与前面的几个不同,我不认为这是Python的迷惑行为,相反我认为这种处理很聪明,尽管初学者理解起来会有些困难。

总结

实际上,我们对Python的不满不止是编写代码的痛苦,别忘了,以前Python的执行速度非常慢,比大多数其他语言慢 2~10 倍。

现在情况已经好很多了。例如,现在Numpy 包能够非常快速地处理列表、矩阵等。

Python的多线程处理也变得更加容易了。你可以使用计算机上的多个内核,我曾在 20 个内核上运行进程,为我节省了数周的计算时间。

此外,在过去几年中,随着机器学习的蓬勃发展,Python 也表现出了进一步的发展空间。Pytorch 和 Tensorflow 等包的出现推动了Python的采用,而其他语言也正在努力中。

虽然,多年来Python在不断进步,但这并不能保证Python未来的发展会一帆风顺。Python语言的学习并没有那么简单,请多加小心。



Tags:Python   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
一篇文章教会你使用Python中三种简单的函数
所谓函数,就是指:把某些特定功能的代码组成为一个整体,这个整体就叫做函数。一、函数简介所谓函数,就是指:把某些特定功能的代码组成为一个整体,这个整体就叫做函数。二、函数定义...【详细内容】
2024-04-11  Search: Python  点击:(3)  评论:(0)  加入收藏
一篇文章带你了解Python的分布式进程接口
在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上。一、前言在Thread和Process中,应当优...【详细内容】
2024-04-11  Search: Python  点击:(2)  评论:(0)  加入收藏
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Search: Python  点击:(8)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Search: Python  点击:(18)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Search: Python  点击:(34)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  Search: Python  点击:(35)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  Search: Python  点击:(36)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Search: Python  点击:(89)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  Search: Python  点击:(88)  评论:(0)  加入收藏
大语言模型插件功能在携程的Python实践
作者简介成学,携程高级安全研发工程师,关注Python/Golang后端开发、大语言模型等领域。一、背景2023年初,科技圈最火爆的话题莫过于大语言模型了,它是一种全新的聊天机器人模型,...【详细内容】
2024-01-26  Search: Python  点击:(76)  评论:(0)  加入收藏
▌简易百科推荐
一篇文章教会你使用Python中三种简单的函数
所谓函数,就是指:把某些特定功能的代码组成为一个整体,这个整体就叫做函数。一、函数简介所谓函数,就是指:把某些特定功能的代码组成为一个整体,这个整体就叫做函数。二、函数定义...【详细内容】
2024-04-11  Go语言进阶学习  微信公众号  Tags:Python   点击:(3)  评论:(0)  加入收藏
一篇文章带你了解Python的分布式进程接口
在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上。一、前言在Thread和Process中,应当优...【详细内容】
2024-04-11  Go语言进阶学习    Tags:Python   点击:(2)  评论:(0)  加入收藏
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Python技术    Tags:Python   点击:(8)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Python技术  微信公众号  Tags:Python   点击:(18)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Python都知道  微信公众号  Tags:Python   点击:(34)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  子午Python  微信公众号  Tags:Python技巧   点击:(35)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  编程技术汇    Tags:Python代码   点击:(36)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Python学研大本营  微信公众号  Tags:PyCharm插件   点击:(89)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  科学随想录  微信公众号  Tags:Graphlib库   点击:(88)  评论:(0)  加入收藏
Python分布式爬虫打造搜索引擎
简单分布式爬虫结构主从模式是指由一台主机作为控制节点负责所有运行网络爬虫的主机进行管理,爬虫只需要从控制节点那里接收任务,并把新生成任务提交给控制节点就可以了,在这个...【详细内容】
2024-01-25  大雷家吃饭    Tags:Python   点击:(59)  评论:(0)  加入收藏
站内最新
站内热门
站内头条