位置: 编程技术 - 正文

十个Python程序员易犯的错误(python程序员必读书籍)

编辑:rootadmin

推荐整理分享十个Python程序员易犯的错误(python程序员必读书籍),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:python程序员找工作,python程序员工作内容,python程序员工资一般多少,python程序员找工作,python程序员工资一般多少,python程序员工作累吗,python程序员烂大街了吗,python 程序员,内容如对您有帮助,希望把文章链接给更多的朋友!

常见错误1:错误地将表达式作为函数的默认参数

在Python中,我们可以为函数的某个参数设置默认值,使该参数成为可选参数。虽然这是一个很好的语言特性,但是当默认值是可变类型时,也会导致一些令人困惑的情况。我们来看看下面这个Python函数定义:

Python程序员常犯的一个错误,就是想当然地认为:在每次调用函数时,如果没有为可选参数传入值,那么这个可选参数就会被设置为指定的默认值。在上面的代码中,你们可能觉得重复调用foo()函数应该会一直返回'baz',因为你们默认每次foo()函数执行时(没有指定bar变量的值),bar变量都被设置为[](也就是,一个新的空列表)。

但是,实际运行结果却是这样的:

很奇怪吧?为什么每次调用foo()函数时,都会把"baz"这个默认值添加到已有的列表中,而不是重新创建一个新的空列表呢?

答案就是,可选参数默认值的设置在Python中只会被执行一次,也就是定义该函数的时候。因此,只有当foo()函数被定义时,bar参数才会被初始化为默认值(也就是,一个空列表),但是之后每次foo()函数被调用时,都会继续使用bar参数原先初始化生成的那个列表。

当然,一个常见的解决办法就是:

常见问题2:错误地使用类变量

我们来看下面这个例子:

这个结果很正常。

嗯,结果和预计的一样。

在Python语言中,类变量是以字典的形式进行处理的,并且遵循方法解析顺序(Method Resolution Order,MRO)。因此,在上面的代码中,由于类C中并没有x这个属性,解释器将会查找它的基类(base class,尽管Python支持多重继承,但是在这个例子中,C的基类只有A)。换句话说,C并不没有独立于A、真正属于自己的x属性。所以,引用C.x实际上就是引用了A.x。如果没有处理好这里的关系,就会导致示例中出现的这个问题。

常见错误3:错误地指定异常代码块(exception block)的参数

请看下面这段代码:

这段代码的问题在于,except语句并不支持以这种方式指定异常。在Python 2.x中,需要使用变量e将异常绑定至可选的第二个参数中,才能进一步查看异常的情况。因此,在上述代码中,except语句并没有捕获IndexError异常;而是将出现的异常绑定到了一个名为IndexError的参数中。

要想在except语句中正确地捕获多个异常,则应将第一个参数指定为元组,然后在元组中写下希望捕获的异常类型。另外,为了提高可移植性,请使用as关键词,Python 2和Python 3均支持这种用法。

常见错误4:错误理解Python中的变量名解析

Python中的变量名解析遵循所谓的LEGB原则,也就是“L:本地作用域;E:上一层结构中def或lambda的本地作用域;G:全局作用域;B:内置作用域”(Local,Enclosing,Global,Builtin),按顺序查找。看上去是不是很简单?不过,事实上这个原则的生效方式还是有着一些特殊之处。说到这点,我们就不得不提下面这个常见的Python编程错误。请看下面的代码:

出了什么问题?

上述错误的出现,是因为当你在某个作用域内为变量赋值时,该变量被Python解释器自动视作该作用域的本地变量,并会取代任何上一层作用域中相同名称的变量。

正是因为这样,才会出现一开始好好的代码,在某个函数内部添加了一个赋值语句之后却出现了UnboundLocalError,难怪会让许多人吃惊。

在使用列表时,Python程序员尤其容易陷入这个圈套。

请看下面这个代码示例:

呃?为什么函数foo1运行正常,foo2却出现了错误?

答案与上一个示例相同,但是却更难捉摸清楚。foo1函数并没有为lst变量进行赋值,但是foo2却有赋值。我们知道,lst += [5]只是lst = lst + [5]的简写,从中我们就可以看出,foo2函数在尝试为lst赋值(因此,被Python解释器认为是函数本地作用域的变量)。但是,我们希望为lst赋的值却又是基于lst变量本身(这时,也被认为是函数本地作用域内的变量),也就是说该变量还没有被定义。这才出现了错误。

常见错误5:在遍历列表时更改列表

下面这段代码的问题应该算是十分明显:

在遍历列表或数组的同时从中删除元素,是任何经验丰富的Python开发人员都会注意的问题。但是尽管上面的示例十分明显,资深开发人员在编写更为复杂代码的时候,也很可能会无意之下犯同样的错误。

幸运的是,Python语言融合了许多优雅的编程范式,如果使用得当,可以极大地简化代码。简化代码还有一个好处,就是不容易出现在遍历列表时删除元素这个错误。能够做到这点的一个编程范式就是列表解析式。而且,列表解析式在避免这个问题方面尤其有用,下面用列表解析式重新实现上面代码的功能:

常见错误6:不理解Python在闭包中如何绑定变量

请看下面这段代码:

你可能觉得输出结果应该是这样的:

但是,实际的输出结果却是:

吓了一跳吧!

十个Python程序员易犯的错误(python程序员必读书籍)

这个结果的出现,主要是因为Python中的迟绑定(late binding )机制,即闭包中变量的值只有在内部函数被调用时才会进行查询。因此,在上面的代码中,每次create_multipliers()所返回的函数被调用时,都会在附近的作用域中查询变量i的值(而到那时,循环已经结束,所以变量i最后被赋予的值为4)。

要解决这个常见Python问题的方法中,需要使用一些hack技巧:

请注意!我们在这里利用了默认参数来实现这个lambda匿名函数。有人可能认为这样做很优雅,有人会觉得很巧妙,还有人会嗤之以鼻。但是,如果你是一名Python程序员,不管怎样你都应该要了解这种解决方法。

常见错误7:模块之间出现循环依赖(circular dependencies)

假设你有两个文件,分别是a.py和b.py,二者相互引用,如下所示:

a.py文件中的代码:

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

代码运行正常。也许这出乎了你的意料。毕竟,我们这里存在循环引用这个问题,想必应该是会出现问题的,难道不是吗?

答案是,仅仅存在循环引用的情况本身并不会导致问题。如果一个模块已经被引用了,Python可以做到不再次进行引用。但是如果每个模块试图访问其他模块定义的函数或变量的时机不对,那么你就很可能陷入困境。

那么回到我们的示例,当我们导入a.py模块时,它在引用b.py模块时是不会出现问题的,因为b.py模块在被引用时,并不需要访问在a.py模块中定义的任何变量或函数。b.py模块中对a模块唯一的引用,就是调用了a模块的foo()函数。但是那个函数调用发生在g()函数当中,而a.py或b.py模块中都没有调用g()函数。所以,不会出现问题。

但是,如果我们试着导入b.py模块呢(即之前没有引用a.py模块的前提下):

糟糕。情况不太妙!这里的问题是,在导入b.py的过程中,它试图引用a.py模块,而a.py模块接着又要调用foo()函数,这个foo()函数接着又试图去访问b.x变量。但是这个时候,b.x变量还没有被定义,所以才出现了AttributeError异常。

解决这个问题有一种非常简单的方法,就是简单地修改下b.py模块,在g()函数内部才引用a.py:

现在我们再导入b.py模块的话,就不会出现任何问题了:

常见错误8:模块命名与Python标准库模块名冲突

Python语言的一大优势,就是其本身自带的强大标准库。但是,正因为如此,如果你不去刻意注意的话,你也是有可能为自己的模块取一个和Python自带标准库模块相同的名字(例如,如果你的代码中有一个模块叫email.py,那么这就会与Python标准库中同名的模块相冲突。)

这很可能会给你带来难缠的问题。举个例子,在导入模块A的时候,假如该模块A试图引用Python标准库中的模块B,但却因为你已经有了一个同名模块B,模块A会错误地引用你自己代码中的模块B,而不是Python标准库中的模块B。这也是导致一些严重错误的原因。

因此,Python程序员要格外注意,避免使用与Python标准库模块相同的名称。毕竟,修改自己模块的名称比提出PEP提议修改上游模块名称且让提议通过,要来得容易的多。

常见错误9:未能解决Python 2与Python 3之间的差异

假设有下面这段代码:

如果是Python 2,那么代码运行正常:

但是现在,我们换成Python 3再运行一遍:

这到底是怎么回事?这里的“问题”是,在Python 3中,异常对象在except代码块作用域之外是无法访问的。(这么设计的原因在于,如果不这样的话,堆栈帧中就会一直保留它的引用循环,直到垃圾回收器运行,将引用从内存中清除。)

避免这个问题的一种方法,就是在except代码块的作用域之外,维持一个对异常对象的引用(reference),这样异常对象就可以访问了。下面这段代码就使用了这种方法,因此在Python 2和Python 3中的输出结果是一致的:

在Python 3下运行代码:

太棒了!

常见错误:错误使用del方法

假设你在mod.py的文件中编写了下面的代码:

如果你运行another_mod.py模块的话,将会出现AttributeError异常。

为什么?因为当解释器结束运行的时候,该模块的全局变量都会被设置为None。因此,在上述示例中,当__del__方法被调用之前,foo已经被设置成了None。

要想解决这个有点棘手的Python编程问题,其中一个办法就是使用atexit.register()方法。这样的话,当你的程序执行完成之后(即正常退出程序的情况下),你所指定的处理程序就会在解释器关闭之前运行。

应用了上面这种方法,修改后的mod.py文件可能会是这样子的:

这种实现支持在程序正常终止时干净利落地调用任何必要的清理功能。很明显,上述示例中将会由foo.cleanup函数来决定如何处理self.myhandle所绑定的对象。

综述

Python是一门强大而又灵活的编程语言,提供的许多编程机制和范式可以极大地提高工作效率。但是与任何软件工具或语言一样,如果对该语言的能力理解有限或无法欣赏,那么有时候自己反而会被阻碍,而不是受益了。正如一句谚语所说,“自以为知道够多,但实则会给自己或别人带来危险。

不断地熟悉Python语言的一些细微之处,尤其是本文中提到的大常见错误,将会帮助你有效地使用这门语言,同时也能避免犯一些比较常见的错误。

使用Python编写简单的端口扫描器的实例分享 单线程实现单线程实现道理比较简单,这里尝试Soket连接,连接成功说明端口开放,否则说明没有开远程服务。随便修改了一下就ok了,代码如下,最

用ReactJS和Python的Flask框架编写留言板的代码示例 近期要在生产环境上使用react,所以,自己学习了一下,写了一个简单的留言板小程序。完整的代码可以到这里下载:message-boardUse前端使用React,然后还

在DigitalOcean的服务器上部署flaskblog应用 在DigitalOcean上部署了flaskblog,项目虽小,部署中也学到了很多东西。操作系统选择的是Ubuntu.,原因就是平时自己主要使用这个版本,顺手而已,所以

标签: python程序员必读书籍

本文链接地址:https://www.jiuchutong.com/biancheng/379943.html 转载请保留说明!

上一篇:Python学习笔记整理3之输入输出、python eval函数(整型python)

下一篇:使用Python编写简单的端口扫描器的实例分享(python简明)

  • 间接税和直接税哪个容易转嫁
  • 价外费用是含税价还是不含税价
  • 金税四期对建筑的影响
  • 应交税费减免科目金额的计算
  • 预估收入增值税申报
  • 资产处置损益属于收入吗
  • 建筑劳务适用税率
  • 本年利润包含增值税吗
  • 运输过程中货物丢失
  • 一般纳税人农业增值税如何申报
  • 暂估出库是什么意思
  • 耕地占用税如何做账
  • 用土地出资需要交税吗
  • 月末在产品直接人工成本怎么算
  • 提高并购成本
  • 小规模收到增值税专用发票咋处理
  • 固定资产计提折旧的会计科目
  • 返还经费
  • 筹建期的收入要交企业所得税吗
  • 税控盘登不上怎么回事
  • 以土地入股需要开发票吗
  • 高新加计扣除怎么做账
  • 无偿捐赠增值税计算公式
  • bios咋进入
  • 种植业土地租赁计入哪个科目
  • 基本户是否可以冻结
  • 公司账户收款退回怎么退
  • 什么叫存量房转移登记
  • 境外佣金支付所需要征收的税
  • vue3+vite在main.ts或者main.js文件中引入/App.vue报错(/App.vue不是模块)
  • 结转已销产品实收成本
  • PHP:image2wbmp()的用法_GD库图像处理函数
  • 金融企业财务规则(征求意见稿)
  • 如何开启framework 3.5
  • 金碟软件如何查看明细账
  • 财税2016年12号文件解读
  • es6解构赋值对象
  • 删除ont命令
  • js中this指向有几种情况
  • 微擎框架可以干什么
  • 差旅费报销有哪些
  • springbootredis密码加密
  • 企业所得税放入什么科目
  • 留存收益的个别资本成本计算公式
  • 固定资产原值增加折旧怎么算
  • 收到个税手续费返还怎么做分录
  • 个体定期定额怎么征税
  • 购买防伪税控设备
  • 企业暂估成本如何确定
  • 公共电话亭的话费怎么算
  • 预付账款和应付账款减少
  • 滴滴打车开具的普通发票可以抵扣吗
  • 增加固定资产原值
  • 财务收入支出明细表
  • 进项税额减免部分在重点税源表中怎么填
  • 一般纳税人购买汽车会计分录
  • 税控抵税怎么做分录
  • 收到车辆购置税发票怎么做账
  • 企业实收资本怎么计算
  • 货物发出退货
  • 驾驶员行车补贴
  • 每月发票认证时间
  • 材料的运费计入哪个科目
  • centos rpm命令
  • windowsxp注册表在哪
  • 意大利的福利政策
  • 关于windows的开始菜单,叙述错误的是
  • 免费升级windows10
  • linux如何使用vim编写程序
  • js中cookie
  • javascript如何学
  • react-router react-router-dom
  • jquery cookie使用
  • nodejs项目实例
  • python生成随机数据
  • javascript的dom
  • 国家税务局上的电子发票如何作废
  • 176是哪的号码
  • 除了增值税还要什么税种
  • 进项税计提和上交会计分录
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设