Python开发人员最常见的8个错误

大多数python开发人员具有不同的核心编程语言背景,例如java,C#或c ++。 因此,他们习惯于用艰苦的方式做事,而当它们以简单易学的Python语言被引入时,它们会误解Python的多样性和功能,并常常最终导致自己误导其失去某些细微之处。

在本文中,我将尝试解决Python程序员遇到的错误。 这些错误甚至是本文中的大多数错误都是针对中级甚至专家级的开发人员的。 想知道? 如果您是初学者或中级开发人员,请继续阅读文章Python开发人员最常犯的10个错误,因为当前文章适合更高级的读者。

1.遍历列表时修改列表

这是每个Python开发人员一生中至少面对一次的问题。在下面的代码片段中查看问题:

>>> odd = lambdax : bool(x %2) >>> numbers = [nfor n inrange(10)] >>>for i inrange(len(numbers)): ...if odd(numbers[i]): ...         del numbers[i]  # 在列表上进行迭代时删除列表中的项目...Traceback (most recentcalllast):      File"",line2, in IndexError:listindex out ofrange 

这个问题非常明显,但即使是高级开发人员,在复杂的工作流程中添加代码时也会犯类似的错误。

有几种解决方案。我想在这里讨论一个最佳解决方案,但据我说这是最简单的解决方案,因此我不太可能产生错误。我建议列表理解在这种情况下非常有用。看看上面的代码具有列表理解的实现:

>>> odd = lambda x : bool(x %2)>>> numbers = [n for n in range(10)]>>> numbers[:] = [n for n in numbers if not odd(n)]>>> numbers [0,2,4,6,8] 

2.创建循环模块依赖项

假设您有两个文件a.py和b.py,每个文件都导入另一个文件,如下所示:

在a.py中:

import bdeff():return b.xprint f() 

在b.py中:

import a x =1defg():print a.f() 

首先,让我们尝试导入a.py:

>>> import a1 

一切正常,没有错误。它应该给您一个错误,但是这里的问题是,如果存在循环依赖关系,您有时可以摆脱它,因为python足够聪明,可以跟踪导入的软件包。当每个模块尝试访问另一个模块的功能时会发生问题,因为不会声明另一个模块,这将导致AttributeError,如下所示:

>>> import b Traceback (most recent call last):        File"", line1,in        File"b.py", line1,in      import a       File"a.py", line6,in      print f()       File"a.py", line4,in freturn b.xAttributeError:'module' object has no attribute'x' 

要解决此问题,我们需要在函数内部导入其他依赖模块:

x =1defg():import a# 仅在调用g()时才会计算print a.f() 

现在一切都应该运行良好:

>>> import b>>> b.g()1#自模块'a'在最后调用'print f()'以来首次打印1#第二次打印,这是我们对“ g”的调用 

3.错误使用表达式作为函数参数的默认值

这是很难调试的错误之一,因为它不会给您带来错误,而且在大多数情况下它可以正常工作,并且开发人员可以摆脱它。当我们可以指定一个可变的可选函数参数时,就会发生这种情况。例如:

>>>deffoo(bar=[]): ...    bar.append("baz") ...return bar 

看起来我们已经创建了一个函数,该函数会将baz附加在指定给它的列表的末尾,否则每次在不使用bar参数的情况下调用它都将返回[“ baz”],因为bar将被初始化为[]。但是,当我们执行它时,我们得到以下结果:

>>> foo() ["baz"]>>> foo() ["baz","baz"]>>> foo() ["baz","baz","baz"] 

输出结果并非预期的那样,现在您将看到,如果没有人注意到此问题,那么如果调用它,大多数开发人员将如何摆脱它。通过查看代码,很难找到尚未遇到此问题或不知道Python如何评估函数的人,因为每次它将bar的值初始化为[]时,都很难。但是在Python中,默认参数仅被评估一次,因此在第一次调用时它会按预期工作,但是在第二次和第三次调用中,它使用现有的条形列表而不是对其进行初始化。她是我们如何解决这个问题的方法:

>>>deffoo(bar=None): ...if barisNone:#或者 if not bar: ...        bar = [] ...    bar.append("baz") ...return bar ...>>> foo()["baz"] >>> foo()["baz"] >>> foo()["baz"] 

4.错误使用类变量

考虑以下示例:

>>>classA(object): ...     x =1 ...>>>classB(A): ...     pass ...>>>classC(A): ...     pass ...>>> print A.x, B.x, C.x111 

这个说得通。

>>> B.x =2>>> print A.x, B.x, C.x121 

再次如预期

>>> A.x =3>>> print A.x, B.x, C.x323 

什么?通过更改A类的值,C类不会受到影响是很奇怪的。这是因为在Python中,类变量在内部作为字典处理,并且遵循称为“方法解析顺序”的顺序。发生这种情况是因为在类C中找不到属性x,所以在基类A中对其进行了查找。

5.为异常块指定不正确的参数

对于给定的代码:

>>>try: ...l = ["a","b"] ...int(l[2]) ... except ValueError, IndexError:  # Tocatch both exceptions,right? ...     pass...Traceback (most recentcalllast):  File"",line3, in IndexError:listindex out ofrange 追溯(最近一次通话):  <模块>中第3行的文件“<stdin>” 

IndexError:列表索引超出范围 

看来您正在尝试捕获这两个异常,但这是行不通的。此错误通常是由来自python 2.x背景的开发人员犯的,因为在Python 2中,此语法用于将异常绑定到可选参数。我们的代码应该捕获了IndexError异常。正确的方法是使用元组,方法是指定要在元组中捕获并使用as绑定到参数的所有异常。 python 2&3也支持此语法:

>>>try:...     l = ["a","b"]...     int(l[2])... except (ValueError, IndexError) as e:...     pass...>>> 

6.对Python作用域规则的误解

Python范围解析基于所谓的LEGB规则,它是Local,Enclosing,Global,Built-in的简写。但这会使开发人员遇到麻烦,例如:

>>> x =10 >>>deffoo(): ...     x +=1 ...print x...>>> foo()Traceback (most recent call last):  File"", line1,in    File"", line2,in foo UnboundLocalError: local variable'x' referenced before assignment 追溯(最近一次通话):   <模块>中第1行的文件“ ”   文件“ ”,第2行,在foo中 

UnboundLocalError:分配前已引用局部变量“ x” 

没道理我们已经声明x应该可以正常运行。调用该函数会在这里寻找变量x,但找不到变量x,它将把它带到外部作用域。直到我们对其进行分配之前,它都可以正常工作。我们得到UnboundLocalError以避免函数意外更改变量的值。有关更多信息,请参见此处。

为了进一步说明,下面是一些其他示例:

>>> lst = [1,2,3] >>>deffoo1(): ...     lst.append(5) ...>>> foo1()>>> lst[1,2,3,5] >>> lst = [1,2,3] >>>deffoo2(): ...     lst += [5] ...>>> foo2()Traceback (most recent call last):  File"", line1,in    File"", line2,in foo UnboundLocalError: local variable'lst' referenced before assignment 追溯(最近一次通话):   <模块>中第1行的文件“ ”   文件“ ”,行2,在foo中 

UnboundLocalError:分配前已引用局部变量“ lst” 

在这两种情况下,我们都尝试从外部范围更新列表。在第一个示例中它起作用了,但是在第二个示例中却没有起作用,因为我们在函数主体中的该列表上使用了赋值运算符。这将尝试将计算/评估的值存储到foo2中不存在的局部变量lst中。

7.混淆Python如何在闭包中绑定变量

考虑以下示例:、

>>>defcreate_multipliers(): ...return [lambda x : i * xfor iin range(5)] >>>for multiplierin create_multipliers(): ...print multiplier(2) 

... 

您可能期望以下输出:

但是您实际上得到:

由于Python的后期绑定行为,即在调用内部函数时会搜索闭包中使用的变量的值。因此,在上面的代码中,无论何时调用任何返回的函数,i的值都会在调用时在周围的范围内进行搜索,但是到发生这种情况时,循环就完成了,因此我已经为其分配了i最终值为4。一种解决方法是:

>>>defcreate_multipliers(): ...return [lambda x, i=i : i * xfor iin range(5)] ...>>>for multiplierin create_multipliers(): ...print multiplier(2) ...02468 

8.重新发明轮子

这是在来自低级语言背景(例如c ++,c#等)的开发人员中最常见的。由于庞大的社区和大量的开放源代码内容以及对python社区的帮助,如果没有现有的解决方案,很难发现问题。但是在这里,我谈论的是重新创建python提供的基础。其中一些可能包括使用装饰器,生成器,内置函数。我最好的例子是排序功能。当我为开发人员编写满足其独特需求的自定义排序函数时,我已经看到了好几次。在所有情况下,整个功能都可以用更简单,更优雅和更强大的代码代替:

list.sort(key=…,reverse=…) 

很难找到无法解决我们问题的实际方案。我们甚至可以使用此方法对元组,字典或任何Python对象进行排序。

看下面的例子:

>>> vowels = ['e','a','u','o','i']>>> vowels.sort(reverse=True)>>> print('Sorted list (in Descending):', vowels) Sorted list (in Descending): ['u','o','i','e','a'] 

这是元组列表的示例

# take second element for sort#将第二个元素进行排序deftakeSecond(elem):return elem[1]# random list#随机列表 random = [(2,2), (3,4), (4,1), (1,3)]# sort list with key#用键排序列表 random.sort(key=takeSecond)# print list#打印清单 print('Sorted list:', random) Output: Sorted list: [(4,1), (2,2), (1,3), (3,4)] 

总结:

即使python很容易上手,但对所使用的工具或范例缺乏深入的了解也会使您陷入麻烦。我希望你们中的一些人会发现

最后,小编想说:我是一名python开发工程师, 整理了一套最新的python系统学习教程, 想要这些资料的可以关注私信小编“01”即可(免费分享哦)希望能 对你有所帮助.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355