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

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

快速链接到答案:

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


当前回答

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

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

其他回答

应许多人的要求,这个答案已经被移到了问题本身。

列举

用enumerate包装一个可迭代对象,它将生成项目及其索引。

例如:


>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 e
>>>

引用:

Python教程循环技术 Python文档-内置函数-枚举 PEP 279

就地值交换

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

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

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

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

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

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

可以使用属性使类接口更加严格。

class C(object):
    def __init__(self, foo, bar):
        self.foo = foo # read-write property
        self.bar = bar # simple attribute

    def _set_foo(self, value):
        self._foo = value

    def _get_foo(self):
        return self._foo

    def _del_foo(self):
        del self._foo

    # any of fget, fset, fdel and doc are optional,
    # so you can make a write-only and/or delete-only property.
    foo = property(fget = _get_foo, fset = _set_foo,
                   fdel = _del_foo, doc = 'Hello, I am foo!')

class D(C):
    def _get_foo(self):
        return self._foo * 2

    def _set_foo(self, value):
        self._foo = value / 2

    foo = property(fget = _get_foo, fset = _set_foo,
                   fdel = C.foo.fdel, doc = C.foo.__doc__)

在Python 2.6和3.0中:

class C(object):
    def __init__(self, foo, bar):
        self.foo = foo # read-write property
        self.bar = bar # simple attribute

    @property
    def foo(self):
        '''Hello, I am foo!'''

        return self._foo

    @foo.setter
    def foo(self, value):
        self._foo = value

    @foo.deleter
    def foo(self):
        del self._foo

class D(C):
    @C.foo.getter
    def foo(self):
        return self._foo * 2

    @foo.setter
    def foo(self, value):
        self._foo = value / 2

要了解属性如何工作的更多信息,请参阅描述符。

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

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