Python编程语言中有哪些鲜为人知但很有用的特性?

尽量将答案限制在Python核心。 每个回答一个特征。 给出一个例子和功能的简短描述,而不仅仅是文档链接。 使用标题作为第一行标记该特性。

快速链接到答案:

参数解包 牙套 链接比较运算符 修饰符 可变默认参数的陷阱/危险 描述符 字典默认的.get值 所以测试 省略切片语法 枚举 其他/ 函数作为iter()参数 生成器表达式 导入该 就地值交换 步进列表 __missing__物品 多行正则表达式 命名字符串格式化 嵌套的列表/生成器推导 运行时的新类型 .pth文件 ROT13编码 正则表达式调试 发送到发电机 交互式解释器中的制表符补全 三元表达式 试着/ / else除外 拆包+打印()函数 与声明


当前回答

脚本的交互式调试(和doctest字符串)

我不认为这是广为人知的,但添加这一行到任何python脚本:

进口pdb;pdb.set_trace ()

将导致PDB调试器在代码的那一点弹出运行游标。我想,更鲜为人知的是,你可以在doctest中使用同样的行:

"""
>>> 1 in (1,2,3)   
Becomes
>>> import pdb; pdb.set_trace(); 1 in (1,2,3)
"""

然后可以使用调试器检出doctest环境。您不能真正逐级执行doctest,因为每一行都是自主运行的,但它是调试doctest glob和环境的好工具。

其他回答

...dict.get()有一个默认值None,从而避免KeyErrors:

In [1]: test = { 1 : 'a' }

In [2]: test[2]
---------------------------------------------------------------------------
<type 'exceptions.KeyError'>              Traceback (most recent call last)

&lt;ipython console&gt; in <module>()

<type 'exceptions.KeyError'>: 2

In [3]: test.get( 2 )

In [4]: test.get( 1 )
Out[4]: 'a'

In [5]: test.get( 2 ) == None
Out[5]: True

甚至在“现场”指定这个:

In [6]: test.get( 2, 'Some' ) == 'Some'
Out[6]: True

你可以使用setdefault()来设置一个值,如果它不存在就返回:

>>> a = {}
>>> b = a.setdefault('foo', 'bar')
>>> a
{'foo': 'bar'}
>>> b
'bar

这里有2个彩蛋:


python本身的一个:

>>> import __hello__
Hello world...

另一个是在Werkzeug模块中,它有点复杂,在这里:

通过查看Werkzeug的源代码,在Werkzeug /__init__.py中,有一行应该引起你的注意:

'werkzeug._internal':   ['_easteregg']

如果你有点好奇,这应该让你看看werkzeug/_internal.py,在那里,你会发现一个_easteregg()函数,它在参数中接受一个wsgi应用程序,它还包含一些base64编码的数据和2个嵌套的函数,如果在查询字符串中找到一个名为macgybarchakku的参数,它似乎做了一些特殊的事情。

因此,为了揭示这个彩蛋,似乎你需要在_easteregg()函数中包装一个应用程序,让我们开始:

from werkzeug import Request, Response, run_simple
from werkzeug import _easteregg

@Request.application
def application(request):
    return Response('Hello World!')

run_simple('localhost', 8080, _easteregg(application))

现在,如果你运行应用程序并访问http://localhost:8080/?macgybarchakku,你应该会看到彩蛋。

小心可变默认参数

>>> def foo(x=[]):
...     x.append(1)
...     print x
... 
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

相反,你应该使用一个表示“not given”的哨兵值,并将其替换为你想要的默认值:

>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]

Re可以调用函数!

事实上,您可以在每次匹配正则表达式时调用函数,这非常方便。 这里我有一个例子,把每个“Hello”替换为“Hi”,把“there”替换为“Fred”,等等。

import re

def Main(haystack):
  # List of from replacements, can be a regex
  finds = ('Hello', 'there', 'Bob')
  replaces = ('Hi,', 'Fred,', 'how are you?')

  def ReplaceFunction(matchobj):
    for found, rep in zip(matchobj.groups(), replaces):
      if found != None:
        return rep

    # log error
    return matchobj.group(0)

  named_groups = [ '(%s)' % find for find in finds ]
  ret = re.sub('|'.join(named_groups), ReplaceFunction, haystack)
  print ret

if __name__ == '__main__':
  str = 'Hello there Bob'
  Main(str)
  # Prints 'Hi, Fred, how are you?'

一切事物的一等性(“一切事物都是一个物体”),以及这可能造成的混乱。

>>> x = 5
>>> y = 10
>>> 
>>> def sq(x):
...   return x * x
... 
>>> def plus(x):
...   return x + x
... 
>>> (sq,plus)[y>x](y)
20

最后一行创建一个包含这两个函数的元组,然后计算y>x (True)并将其作为元组的索引(通过将其强制转换为int类型,1),然后使用参数y调用该函数并显示结果。

对于进一步的滥用,如果你返回一个带索引的对象(例如一个列表),你可以在末尾添加更多的方括号;如果内容是可调用的,更多的括号,等等。为了更变态,使用这样的代码的结果作为另一个例子中的表达式(即用下面的代码替换y>x):

(sq,plus)[y>x](y)[4](x)

这展示了Python的两个方面——极端的“一切都是一个对象”哲学,以及不恰当或考虑不良的语言语法使用方法,可能导致完全不可读、不可维护的意大利面条代码,适合一个表达式。