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

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

快速链接到答案:

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


当前回答

getattr内置函数:

>>> class C():
    def getMontys(self):
        self.montys = ['Cleese','Palin','Idle','Gilliam','Jones','Chapman']
        return self.montys


>>> c = C()
>>> getattr(c,'getMontys')()
['Cleese', 'Palin', 'Idle', 'Gilliam', 'Jones', 'Chapman']
>>> 

如果你想根据上下文分派函数,这很有用。参见深入了解Python中的示例(此处)

其他回答

上下文管理器和“with”语句

在PEP 343中引入的上下文管理器是作为一组语句的运行时上下文的对象。

由于该特性使用了新的关键字,它是逐渐引入的:在Python 2.5中通过__future__指令可用。Python 2.6及以上版本(包括Python 3)默认情况下可用。

我经常使用“with”语句,因为我认为这是一个非常有用的结构,下面是一个快速演示:

from __future__ import with_statement

with open('foo.txt', 'w') as f:
    f.write('hello!')

这里在幕后发生的事情是,“with”语句在文件对象上调用特殊的__enter__和__exit__方法。如果with语句体引发任何异常,异常细节也会传递给__exit__,允许在那里进行异常处理。

在这种特殊情况下,这为您做的是,当执行超出with套件的范围时,它保证关闭文件,无论这是正常发生还是抛出异常。它基本上是一种抽象出常见异常处理代码的方法。

其他常见的用例包括线程锁定和数据库事务。

可读正则表达式

在Python中,您可以将正则表达式拆分为多行,命名匹配并插入注释。

示例详细语法(来自Python):

>>> pattern = """
... ^                   # beginning of string
... M{0,4}              # thousands - 0 to 4 M's
... (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                     #            or 500-800 (D, followed by 0 to 3 C's)
... (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                     #        or 50-80 (L, followed by 0 to 3 X's)
... (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                     #        or 5-8 (V, followed by 0 to 3 I's)
... $                   # end of string
... """
>>> re.search(pattern, 'M', re.VERBOSE)

命名匹配示例(摘自正则表达式HOWTO)

>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'

由于字符串字面值的串联,你也可以在不使用re.VERBOSE的情况下详细地编写一个正则表达式。

>>> pattern = (
...     "^"                 # beginning of string
...     "M{0,4}"            # thousands - 0 to 4 M's
...     "(CM|CD|D?C{0,3})"  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                         #            or 500-800 (D, followed by 0 to 3 C's)
...     "(XC|XL|L?X{0,3})"  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                         #        or 50-80 (L, followed by 0 to 3 X's)
...     "(IX|IV|V?I{0,3})"  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                         #        or 5-8 (V, followed by 0 to 3 I's)
...     "$"                 # end of string
... )
>>> print pattern
"^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"

对迭代器的多个引用

你可以使用列表乘法创建对同一个迭代器的多个引用:

>>> i = (1,2,3,4,5,6,7,8,9,10) # or any iterable object
>>> iterators = [iter(i)] * 2
>>> iterators[0].next()
1
>>> iterators[1].next()
2
>>> iterators[0].next()
3

这可以用来将一个可迭代对象分组成块,例如,就像这个来自itertools文档的例子

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

为了添加更多的python模块(特别是第三方模块),大多数人似乎使用PYTHONPATH环境变量,或者在他们的site-packages目录中添加符号链接或目录。另一种方法是使用*.pth文件。以下是python官方文档的解释:

“这是最方便的修改方式 Python的搜索路径]是添加一个路径 配置文件到一个目录 已经在Python的路径上了, 通常到…/site-packages/ 目录中。路径配置文件 扩展名为。pth,每个 行必须包含一个单独的路径 将被追加到sys.path。(因为 新路径被附加到 sys。路径,模块在添加 目录将不会覆盖标准 模块。这意味着你不能使用这个 安装固定机构 标准模块的版本。)

元组拆包:

>>> (a, (b, c), d) = [(1, 2), (3, 4), (5, 6)]
>>> a
(1, 2)
>>> b
3
>>> c, d
(4, (5, 6))

更模糊的是,你可以在函数参数中做到这一点(在Python 2.x中;Python 3。X将不再允许这样):

>>> def addpoints((x1, y1), (x2, y2)):
...     return (x1+x2, y1+y2)
>>> addpoints((5, 0), (3, 5))
(8, 5)