奇怪的Python特性有哪些?

好吧,是一个 feature 还是 bug 已经搞不清了

Ubuntu 16.04.03 Python3.5.2

>>> a = ''
>>> a[1:-1]
''
>>> a[2:-1]
''
>>> a[3:-1]
''


奇怪的Python特性有哪些?
14 回复

你觉得应该返回什么?


Python里确实有些特性初看挺反直觉的。我说几个自己踩过坑的:

  1. 可变默认参数:这估计是最经典的“坑”了。函数定义里的默认参数(比如def foo(a=[]))只会在函数定义时被求值一次,而不是每次调用都创建新的。如果你在函数里修改了这个可变默认参数(比如a.append(1)),这个修改会一直累积,影响后续所有调用。所以,默认参数最好用不可变对象(如None),在函数体内部再初始化可变对象。

  2. 闭包变量绑定:在循环里创建闭包(或lambda)时,它们捕获的是变量i本身,而不是循环每一步i当前值。等循环结束,所有闭包看到的都是同一个i的最终值。得用默认参数把当前值“冻结”住:lambda x=i: x

  3. is==的区别is比较的是对象标识(内存地址),==比较的是。对于小整数(-5到256)和短字符串,Python会缓存,所以a is b可能为True,但别依赖这个。比较值永远用==

  4. 链式比较的求值顺序:像a < b < c这样的表达式,Python会按数学直觉处理为a < b and b < c,并且中间的b只被计算一次。这很直观,但要知道它和(a < b) < c这种C语言风格的写法完全不同。

  5. +=对不可变对象的作用:对列表,+=是原地修改(list.__iadd__);对元组或字符串,+=会创建一个新对象(tuple.__add__)。这可能导致a_tuple += (1,)看起来能修改元组,其实是变量a_tuple被重新赋值指向了新元组。

总结:理解这些“怪”特性,关键在明白Python的对象模型和名字绑定机制。


raise IndexError

是 feature。
https://docs.python.org/3.6/library/stdtypes.html#common-sequence-operations

s[i:j:k]
“ The slice of s from i to j is defined as the sequence of items with index k such that i <= k < j. If i or j is greater than len(s), use len(s). If i is omitted or None, use 0. If j is omitted or None, use len(s). If i is greater than or equal to j, the slice is empty.”

In [457]: a='a’

In [458]: a[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]
Out[458]: ‘a’

> However, out of range slice indexes are handled gracefully when used for slicing:

<br>&gt;&gt;&gt; word[4:42]<br>'on'<br>&gt;&gt;&gt; word[42:]<br>''<br>
[document]( https://docs.python.org/3.5/tutorial/introduction.html#strings)

动态语言一般倾向于默认一种行为以方便使用,而不是抛出异常,抛出异常还要处理异常多麻烦啊。动不动就抛出异常那是静态语言的习惯。

说实话,要是避免抛异常你是不是还要多写几个判断边界的语句,但是写完判断边界后你觉得是这种特性好用,还是你自己再写一堆代码好用。。


这个死循环反而很好理解啊



可以理解的,写代码起来方便
但是不抛异常可能会导致错误被隐藏起来啊

判断返回值是否空不就行了?

这大概是语言背后的哲学不同,我习惯 java 就很难理解这种 feature

一直都是这样啊

异常不一定带表错误,是否检查以及如何处理异常是程序逻辑,程序员需要根据需要使用相应的语法功能。

这就好比什么时候用 if a 什么时候用 if a is not None 是程序员的责任而不是语言的责任一样。

回到顶部