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

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

快速链接到答案:

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


当前回答

不是很隐藏,但是函数有属性:

def doNothing():
    pass

doNothing.monkeys = 4
print doNothing.monkeys
4

其他回答

is_ok() and "Yes" or "No"

不是很隐藏,但是函数有属性:

def doNothing():
    pass

doNothing.monkeys = 4
print doNothing.monkeys
4

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

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

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!')

从2.5开始字典有一个特殊的方法__missing__,用于调用缺少的项:

>>> class MyDict(dict):
...  def __missing__(self, key):
...   self[key] = rv = []
...   return rv
... 
>>> m = MyDict()
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

在集合中还有一个名为defaultdict的dict子类,它做了几乎相同的事情,但对于不存在的项调用了一个不带参数的函数:

>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

我建议将这些字典转换为常规字典,然后再将它们传递给不需要此类子类的函数。许多代码使用d[a_key]并捕获KeyErrors来检查是否存在一个项,这将向dict添加一个新项。