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

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

快速链接到答案:

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


当前回答

这不是一个隐藏的功能,但仍然很好:

import os.path as op

root_dir = op.abspath(op.join(op.dirname(__file__), ".."))

保存大量字符时,操作路径!

其他回答

...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

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

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

Getattr接受第三个参数

Getattr (obj, attribute_name, default)是这样的:

try:
    return obj.attribute
except AttributeError:
    return default

只不过attribute_name可以是任何字符串。

这对于鸭子输入非常有用。也许你有这样的东西:

class MyThing:
    pass
class MyOtherThing:
    pass
if isinstance(obj, (MyThing, MyOtherThing)):
    process(obj)

(顺便说一下,isinstance(obj, (a,b))表示isinstance(obj, a)或isinstance(obj, b)。)

当你创建一种新的东西时,你需要把它添加到它出现的任何地方。(这种结构在重新加载模块或以两个名称导入同一个文件时也会导致问题。这种事情发生的次数比人们愿意承认的要多。)但是你可以说:

class MyThing:
    processable = True
class MyOtherThing:
    processable = True
if getattr(obj, 'processable', False):
    process(obj)

添加继承就更好了:所有可处理对象的示例都可以继承

class Processable:
    processable = True

但你不需要说服每个人都继承你的基类,只需要设置一个属性。

EVERYTHING是一个对象,因此是可扩展的。我可以将成员变量作为元数据添加到我定义的函数中:

>>> def addInts(x,y): 
...    return x + y
>>> addInts.params = ['integer','integer']
>>> addInts.returnType = 'integer'

这对于编写动态单元测试非常有用,例如。

内置方法或函数不实现描述符协议,这使得不可能做这样的事情:

>>> class C(object):
...  id = id
... 
>>> C().id()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: id() takes exactly one argument (0 given)

然而,你可以创建一个小的绑定描述符来实现这一点:

>>> from types import MethodType
>>> class bind(object):
...  def __init__(self, callable):
...   self.callable = callable
...  def __get__(self, obj, type=None):
...   if obj is None:
...    return self
...   return MethodType(self.callable, obj, type)
... 
>>> class C(object):
...  id = bind(id)
... 
>>> C().id()
7414064