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

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

快速链接到答案:

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


当前回答

主要信息:)

import this
# btw look at this module's source :)

De-cyphered:

蒂姆·彼得斯的《Python之禅》 美总比丑好。 显性比隐性好。 简单比复杂好。 复杂胜过复杂。 扁平比嵌套好。 稀疏比密集好。 可读性。 特殊情况并不特别到可以打破规则。 尽管实用性胜过纯洁性。 错误绝不能悄无声息地过去。 除非明确保持沉默。 面对模棱两可,拒绝猜测的诱惑。 应该有一种——最好只有一种——明显的方法来做到这一点。 除非你是荷兰人,否则这种方式一开始可能并不明显。 现在总比没有好。 虽然永远不比现在更好。 如果实现很难解释,那就是一个坏主意。 如果实现很容易解释,这可能是一个好主意。 名称空间是一个非常棒的想法——让我们多做一些吧!

其他回答

使用负step反转可迭代对象

>>> s = "Hello World"
>>> s[::-1]
'dlroW olleH'
>>> a = (1,2,3,4,5,6)
>>> a[::-1]
(6, 5, 4, 3, 2, 1)
>>> a = [5,4,3,2,1]
>>> a[::-1]
[1, 2, 3, 4, 5]

就地值交换

>>> a = 10
>>> b = 5
>>> a, b
(10, 5)

>>> a, b = b, a
>>> a, b
(5, 10)

赋值语句的右边是一个表达式,用于创建一个新的元组。赋值的左边立即将(未引用的)元组解包为名称a和b。

赋值之后,新的元组不被引用,并标记为垃圾收集,绑定到a和b的值已经交换。

正如Python教程中关于数据结构的部分所述,

注意,多重赋值实际上只是元组打包和序列解包的组合。

使用不同的起始索引进行枚举

enumerate在这个答案中已经部分涉及了,但最近我发现了enumerate一个更隐藏的特性,我认为值得单独发表,而不仅仅是评论。

从Python 2.6开始,你可以在第二个参数中指定要枚举的起始索引:

>>> l = ["spam", "ham", "eggs"]
>>> list(enumerate(l))
>>> [(0, "spam"), (1, "ham"), (2, "eggs")]
>>> list(enumerate(l, 1))
>>> [(1, "spam"), (2, "ham"), (3, "eggs")]

我发现它非常有用的一个地方是当我枚举对称矩阵的元素时。由于矩阵是对称的,我可以通过只在上三角形上迭代来节省时间,但在这种情况下,我必须在内部for循环中使用不同的起始索引来正确跟踪行和列的索引:

for ri, row in enumerate(matrix):
    for ci, column in enumerate(matrix[ri:], ri):
        # ci now refers to the proper column index

奇怪的是,enumerate的这种行为在help(enumerate)中没有记录,只有在线文档中有记录。

...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,你应该会看到彩蛋。