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

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

快速链接到答案:

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


当前回答

Monkeypatching对象

Python中的每个对象都有__dict__成员,用于存储对象的属性。所以,你可以这样做:

class Foo(object):
    def __init__(self, arg1, arg2, **kwargs):
        #do stuff with arg1 and arg2
        self.__dict__.update(kwargs)

f = Foo('arg1', 'arg2', bar=20, baz=10)
#now f is a Foo object with two extra attributes

可以利用这一点向对象任意添加属性和函数。这也可以用来创建一个快速和肮脏的结构类型。

class struct(object):
    def __init__(**kwargs):
       self.__dict__.update(kwargs)

s = struct(foo=10, bar=11, baz="i'm a string!')

其他回答

私有方法和数据隐藏(封装)

在Python中有一个常见的习惯用法,即通过以下划线开头的名称来表示不打算成为类外部API一部分的方法和其他类成员。这很方便,在实践中效果很好,但它给人一种错误的印象,即Python不支持私有代码和/或数据的真正封装。事实上,Python会自动为您提供词法闭包,这使得在真正需要的情况下以更加防弹的方式封装数据变得非常容易。下面是一个使用这种技术的类的例子:

class MyClass(object):
  def __init__(self):

    privateData = {}

    self.publicData = 123

    def privateMethod(k):
      print privateData[k] + self.publicData

    def privilegedMethod():
      privateData['foo'] = "hello "
      privateMethod('foo')

    self.privilegedMethod = privilegedMethod

  def publicMethod(self):
    print self.publicData

这里有一个使用它的人为的例子:

>>> obj = MyClass()
>>> obj.publicMethod()
123
>>> obj.publicData = 'World'
>>> obj.publicMethod()
World
>>> obj.privilegedMethod()
hello World
>>> obj.privateMethod()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'privateMethod'
>>> obj.privateData
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'privateData'

关键是privateMethod和privateData根本不是obj的属性,所以它们不能从外部访问,也不会出现在dir()或类似的文件中。它们是构造函数中的局部变量,在__init__之外完全不可访问。然而,由于闭包的魔力,它们实际上是与它们关联的对象具有相同生命周期的每个实例变量,尽管除了(在本例中)调用privilegedMethod之外没有办法从外部访问它们。通常这种非常严格的封装是多余的,但有时它确实可以非常方便地保持API或名称空间的干净。

在Python 2中。在X中,拥有可变私有状态的唯一方法是使用可变对象(例如本例中的dict)。很多人都说这有多烦人。Python 3。x将通过引入PEP 3104中描述的nonlocal关键字来消除此限制。

列举

用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

我不确定这在Python文档中的位置(或是否),但对于Python 2。x(至少2.5和2.6,我刚刚尝试过),打印语句可以用括号调用。如果您希望能够轻松地移植一些Python 2,这可能很有用。Python 3.x代码。

例子: 我们想要Moshiach Now在python 2.5, 2.6和3.x中工作。

此外,在Python 2和3中,not操作符可以用括号调用: 不是假的 而且 (假) 都应该返回True。

括号也可以用于其他语句和操作符。

编辑:把括号放在非操作符(可能是任何其他操作符)周围不是一个好主意,因为它会导致令人惊讶的情况,就像这样(发生这种情况是因为括号实际上只是在1周围):

>>> (not 1) == 9
False

>>> not(1) == 9
True

这也可以工作,对于某些值(我认为它不是一个有效的标识符名称),像这样: not'val'将返回False, print'We want Moshiach Now'将返回We want Moshiach Now。(但是not552会引发NameError,因为它是一个有效的标识符名称)。

关于Nick Johnson的Property类的实现(只是描述符的演示,当然,不是内置的替换),我将包括一个引发AttributeError的setter:

class Property(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, type):
        if obj is None:
            return self
        return self.fget(obj)

    def __set__(self, obj, value):
       raise AttributeError, 'Read-only attribute'

包含setter使其成为数据描述符,而不是方法/非数据描述符。数据描述符优先于实例字典。现在,实例不能将不同的对象赋值给属性名,并且尝试将其赋值给属性将引发属性错误。

可以从一组长度为2的序列构建字典。当你有一个值列表和数组列表时,这非常方便。

>>> dict([ ('foo','bar'),('a',1),('b',2) ])
{'a': 1, 'b': 2, 'foo': 'bar'}

>>> names = ['Bob', 'Marie', 'Alice']
>>> ages = [23, 27, 36]
>>> dict(zip(names, ages))
{'Alice': 36, 'Bob': 23, 'Marie': 27}