python 开发中的常见编程错误 绝地灬酷狼 2022-05-28 02:44 225阅读 0赞 转载至:[http://www.cnblogs.com/rrxc/p/4664462.html][http_www.cnblogs.com_rrxc_p_4664462.html] ## 滥用表达式作为函数参数默认值 ## > Python允许开发者指定一个默认值给函数参数,虽然这是该语言的一个特征,但当参数可变时,很容易导致混乱,例如,下面这段函数定义: def foo(bar=[]): # bar is optional and defaults to [] if not specified ... .append("baz") # but this could be problematic, as we'll see... ... return bar *在上面这段代码里,一旦重复调用foo()(没有指定一个bar参数),那么将一直返回’bar’,因为没有指定参数,那么foo()每次被调用的时候,都会赋予\[\]。下面来看看,这样做的结果:* >>> foo() ["baz"] >>> foo() ["baz", "baz"] >>> foo() ["baz", "baz", "baz"] # 解决方案: >>> def foo(=None): ... if bar is None: # or if not bar: ... bar = [] ... bar.append("baz") ... return bar ... >>> foo() ["baz"] >>> foo() ["baz"] >>> foo() ["baz"] ## 错误地使用类变量 ## > 先看下面这个例子: >>> class A(object): ... x = 1 ... >>> class B(A): ... pass ... >>> class C(A): ... pass ... >>> print A.x, B.x, C.x 1 1 1 # 这样是有意义的: >>> B.x = 2 >>> print A.x, B.x, C.x 1 2 1 # 再来一遍: >>> A.x = 3 >>> print A.x, B.x, C.x 3 2 3 # 仅仅是改变了A.x,为什么C.x也跟着改变了。 *在Python中,类变量都是作为字典进行内部处理的,并且遵循方法解析顺序(MRO)。在上面这段代码中,因为属性x没有在类C中发现,它会查找它的基类(在上面例子中只有A,尽管Python支持多继承)。换句话说,就是C自己没有x属性,独立于A,因此,引用 C.x其实就是引用A.x。* ## 为异常指定不正确的参数 ## > 假设代码中有如下代码: >>> try: ... l = ["a", "b"] ... int(l[2]) ... except ValueError, IndexError: # To catch both exceptions, right? ... pass ... Traceback (most recent last): File "<stdin>", 3, in <module> IndexError: list index out of range 问题在这里,except语句并不需要这种方式来指定异常列表。然而,在Python 2.x中,except Exception,e通常是用来绑定异常里的 第二参数,好让其进行更进一步的检查。因此,在上面这段代码里,IndexError异常并没有被except语句捕获,异常最后被绑定 到了一个名叫IndexError的参数上。 在一个异常语句里捕获多个异常的正确方法是指定第一个参数作为一个元组,该元组包含所有被捕获的异常。与此同时,使用as关键字来保证最大的可移植性,Python 2和Python 3都支持该语法。 >>> try: ... l = ["a", "b"] ... int(l[2]) ... except (ValueError, IndexError) as e: ... pass ... >>> ## 误解Python规则范围 ## > Python的作用域解析是基于LEGB规则,分别是Local、Enclosing、Global、Built-in。实际上,这种解析方法也有一些玄机,看下面这个例子: >>> x = 10 >>> def foo(): ... x += 1 ... print x ... >>> foo() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in foo UnboundLocalError: local variable 'x' referenced before assignment 许多人会感动惊讶,当他们在工作的体里添加一个参数语句,会在先前工作的代码里报UnboundLocalError错误( 点击这里查看更详细描述)。 在使用列表时,开发者是很容易犯这种错误的,看看下面这个例子: >>> lst = [1, 2, 3] >>> def foo1(): ... lst.append(5) # This works ok... ... >>> foo1() >>> lst [1, 2, 3, 5] >>> lst = [1, 2, 3] >>> def foo2(): ... lst += [5] # ... but this bombs! ... >>> foo2() Traceback (most recent last): File "<stdin>", 1, in <module> File "<stdin>", line 2, in foo UnboundLocalError: local variable 'lst' referenced before assignment 为什么foo2失败而foo1运行正常? 答案与前面那个例子是一样的,但又有一些微妙之处。foo1没有赋值给lst,而foo2赋值了。lst += \[5\]实际上就是lst = lst + \[5\],试图给lst赋值(因此,假设Python是在局部作用域里)。然而,我们正在寻找指定给lst的值是基于lst本身,其实尚未确定。 ## 修改遍历列表 ## > 下面这段代码很明显是错误的: >>> odd = lambda x : bool(x % 2) >>> numbers = [n for n in range(10)] >>> for i in range(len(numbers)): ... if odd(numbers[i]): ... del numbers[i] # BAD: Deleting item from a list while iterating over it ... Traceback (most recent last): File "<stdin>", 2, in <module> IndexError: list index out of range 在的时候,对列表进行删除操作,这是很低级的错误。稍微有点经验的人都不会犯。 对上面的代码进行修改,正确地执行: >>> odd = x : bool(x % 2) >>> numbers = [n for n in range(10)] >>> numbers[:] = [n for n in numbers if not odd(n)] # ahh, the beauty of it all >>> numbers [0, 2, 4, 6, 8] ## 如何在闭包中绑定变量 ## > 看下面这个例子: >>> def create_multipliers(): ... return [lambda x : i * x for i in range(5)] >>> for multiplier in create_multipliers(): ... print multiplier(2) 你期望的结果是: `0 2 4 6 8` 实际上: `8 8 8 8 8` 是不是非常吃惊!出现这种情况主要是因为Python的后期绑定行为,该变量在闭包中使用的同时,内部又在调用它。 解决方案: >>> def create_multipliers(): ... return [ x, i=i : i * x for i in range(5)] ... >>> for multiplier in create_multipliers(): ... print multiplier(2) ... 0 2 4 6 8 ## 创建循环模块依赖关系 ## > 假设有两个文件,a.py和b.py,然后各自导入,如下: 在a.py中: import b def f(): return b.x print f() 在b.py中: import a x = 1 def g(): print a.f() 首先,让我们试着导入a.py: `>>> import a 1` 可以很好地工作,也许你会感到惊讶。毕竟,我们确实在这里做了一个循环导入,难道不应该有点问题吗? 仅仅存在一个循环导入并不是Python本身问题,如果一个模块被导入,Python就不会试图重新导入。根据这一点,每个模块在试图访问或变量时,可能会在运行时遇到些问题。 当我们试图导入b.py会发生什么(先前没有导入a.py): >>> import b Traceback (most recent call last): File "<stdin>", 1, in <module> File "b.py", line 1, in <module> import a File "a.py", line 6, in <module> print f() File "a.py", line 4, in f return b.x AttributeError: 'module' object has no attribute 'x' 出错了,这里的问题是,在导入b.py的过程中还要试图导入a.py,这样就要调用f(),并且试图访问b.x。但是b.x并未被定义。 可以这样解决,仅仅修改b.py导入到a.py中的g(): x = 1 def g(): import a # This will be evaluated only when g() is called print a.f() 无论何时导入,一切都可以正常运行: >>> import b >>> b.g() 1 # Printed a first time since module 'a' s 'print f()' at the end 1 # Printed a second time, this one is our call to 'g' 与Python标准库模块名称冲突 Python拥有非常丰富的模块库,并且支持“开箱即用”。因此,如果不刻意避免,很容易发生命名冲突事件。例如,在你的代码中可能有一个email.py的模块,由于名称一致,它很有可能与Python自带的标准库模块发生冲突。 ## 未按规定处理Python2.x和Python3.x之间的区别 ## 看一下foo.py: import sys def (i): if i == 1: raise KeyError(1) if i == 2: raise ValueError(2) def bad(): e = None try: bar(int(sys.argv[1])) except KeyError as e: print('key error') except ValueError as e: print('value error') print(e) bad() 在Python 2里面可以很好地运行: $ python foo.py 1 key error 1 $ python foo.py 2 value error 2 但是在Python 3里: $ 3 foo.py 1 key error Traceback (most recent last): File "foo.py", 19, in <module> bad() File "foo.py", line 17, in bad print(e) UnboundLocalError: local variable 'e' referenced before assignment 解决方案: import sys def bar(i): if i == 1: raise KeyError(1) if i == 2: raise ValueError(2) def good(): exception = None try: (int(sys.argv[1])) except KeyError as e: exception = e print('key error') except ValueError as e: exception = e print('value error') print(exception) good() 在Py3k中运行结果: `$ 3 foo.py 1 key error 1 $ python3 foo.py 2 value error 2` 在 Python招聘指南里有许多关于Python 2与Python 3在移植代码时需要关注的注意事项与讨论,大家可以前往看看。 ## 滥用**del**方法 ## 比如这里有一个叫mod.py的文件: import foo class Bar(object): ... def __del__(self): foo.cleanup(self.myhandle) 下面,你在another_mod.py文件里执行如下操作: import mod my = mod.Bar() 你会获得一个AttributeError异常。 至于为什么会出现该异常,点击这里查看详情。当解释器关闭时,该模块的全局变量全部设置为None。因此,在上面这个例子里,当**del**被调用时,foo已经全部被设置为None。 一个很好的解决办法是使用atexit.register()代替。顺便说一句,当程序执行完成后,您注册的处理程序会在解释器关闭之前停止 工作。 修复上面问题的代码: import foo import atexit def cleanup(handle): foo.cleanup(handle) class Bar(object): def __init__(self): ... atexit.register(cleanup, self.myhandle) 在程序的正常终止的前提下,这个实现提供了一个整洁可靠的方式调用任何需要清理的功能。 [http_www.cnblogs.com_rrxc_p_4664462.html]: http://www.cnblogs.com/rrxc/p/4664462.html
相关 避免Java开发中常见的类型转换错误 在Java开发中,避免类型转换错误通常遵循以下几个步骤: 1. **明确类型**:在进行变量声明时,确保你知道你要存储的是什么类型的对象。例如,而不是`int i = "He 逃离我推掉我的手/ 2024年09月10日 23:03/ 0 赞/ 21 阅读
相关 Python编程语言常见错误盘点 ![7a9f9afd862c29685ff828dcdd9aba35.jpeg][] 转自:[微点阅读][Link 1] [https://www.weidianyuedu. 小鱼儿/ 2024年03月25日 23:29/ 0 赞/ 10 阅读
相关 Python 中常见的 SyntaxError 错误 文章目录 拼写错误: 变量名或函数名拼写错误。 缺少冒号: 在代码块、条件语句或循环中缺少冒号。 缩进错误: 在缩进代码块时混用了 谁借莪1个温暖的怀抱¢/ 2023年10月13日 21:48/ 0 赞/ 9 阅读
相关 python编写错误怎么改_Python每天一分钟:python编程中常见的错误一览与修复方法... 接触过编程的读者一定对程序运行中出现的错误再熟悉不过了,这些错误有的是因为开发人员疏忽引入的语法错误,有的是缺乏必要检验引起的逻辑或者数据错误,还有的是程序运行中与平台规则冲突 Myth丶恋晨/ 2023年01月09日 01:29/ 0 赞/ 73 阅读
相关 Python常见错误 Python常见错误 在刚学习 Python 编程时,经常会看到一些报错信息,下面是一些常见易犯的错误 1.语法错误 Python 的语法错误或者称之为解析错,是 末蓝、/ 2022年12月30日 07:45/ 0 赞/ 177 阅读
相关 Python常见编程错误和陷阱 http://[blog.csdn.net/pipisorry/article/details/45175457][blog.csdn.net_pipisorry_articl 我就是我/ 2022年08月07日 17:43/ 0 赞/ 169 阅读
相关 python 开发中的常见编程错误 转载至:[http://www.cnblogs.com/rrxc/p/4664462.html][http_www.cnblogs.com_rrxc_p_4664462.htm 绝地灬酷狼/ 2022年05月28日 02:44/ 0 赞/ 226 阅读
相关 React native开发中常见的错误 [React Native][]环境搭建请移步:[react native环境搭建][react native] 这里说说[React][] native创建完成之后,运行中 本是古典 何须时尚/ 2022年03月09日 14:14/ 0 赞/ 198 阅读
还没有评论,来说两句吧...