首页 文章

Python的隐藏功能[关闭]

提问于
浏览

30 回答

  • 741

    Interactive Interpreter Tab Completion

    try:
        import readline
    except ImportError:
        print "Unable to load readline module."
    else:
        import rlcompleter
        readline.parse_and_bind("tab: complete")
    
    
    >>> class myclass:
    ...    def function(self):
    ...       print "my function"
    ... 
    >>> class_instance = myclass()
    >>> class_instance.<TAB>
    class_instance.__class__   class_instance.__module__
    class_instance.__doc__     class_instance.function
    >>> class_instance.f<TAB>unction()
    

    您还必须设置PYTHONSTARTUP环境变量 .

  • 106

    Function argument unpacking

    您可以使用 *** 将列表或字典解压缩为函数参数 .

    例如:

    def draw_point(x, y):
        # do some magic
    
    point_foo = (3, 4)
    point_bar = {'y': 3, 'x': 2}
    
    draw_point(*point_foo)
    draw_point(**point_bar)
    

    非常有用的快捷方式,因为列表,元组和dicts被广泛用作容器 .

  • 419

    链接比较运算符:

    >>> x = 5
    >>> 1 < x < 10
    True
    >>> 10 < x < 20 
    False
    >>> x < 10 < x*10 < 100
    True
    >>> 10 > x <= 9
    True
    >>> 5 == x > 4
    True
    

    如果're thinking it'执行 1 < x ,它出现 True ,然后比较 True < 10 ,这也是 True ,那么不,'s really not what happens (see the last example.) It'实际上转换为 1 < x and x < 10x < 10 and 10 < x * 10 and x*10 < 100 ,但键入较少,每个术语只评估一次 .

  • 289

    enumerate

    用枚举包装一个iterable,它将产生项目及其索引 .

    例如:

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

    参考文献:

  • 235

    Be careful with mutable default arguments

    >>> def foo(x=[]):
    ...     x.append(1)
    ...     print x
    ... 
    >>> foo()
    [1]
    >>> foo()
    [1, 1]
    >>> foo()
    [1, 1, 1]
    

    相反,你应该使用表示“not given”的sentinel值,并将你想要的mutable替换为默认值:

    >>> def foo(x=None):
    ...     if x is None:
    ...         x = []
    ...     x.append(1)
    ...     print x
    >>> foo()
    [1]
    >>> foo()
    [1]
    
  • 91

    Re-raising exceptions

    # Python 2 syntax
    try:
        some_operation()
    except SomeError, e:
        if is_fatal(e):
            raise
        handle_nonfatal(e)
    
    # Python 3 syntax
    try:
        some_operation()
    except SomeError as e:
        if is_fatal(e):
            raise
        handle_nonfatal(e)
    

    错误处理程序中没有参数的'raise'语句告诉Python重新引发原始跟踪的异常,允许你说"oh, sorry, sorry, I didn't mean to catch that, sorry, sorry."

    如果您希望打印,存储或摆弄原始的回溯,可以使用sys.exc_info()获取它,并像Python一样使用'traceback'模块进行打印 .

  • 317

    当您在代码文件的顶部使用正确的编码声明时,ROT13是源代码的有效编码:

    #!/usr/bin/env python
    # -*- coding: rot13 -*-
    
    cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")
    
  • 305

    字典有一个get()方法

    字典有一个'get()'方法 . 如果你执行d ['key']并且键不存在,则会出现异常 . 如果你执行d.get('key'),如果'key'不存在,你就会返回None . 您可以添加第二个参数来获取该项而不是None,例如:d.get('key',0) .

    它非常适合添加数字:

    sum[value] = sum.get(value, 0) + 1

  • 168

    切片运算符中的步骤参数 . 例如:

    a = [1,2,3,4,5]
    >>> a[::2]  # iterate over the whole list in 2-increments
    [1,3,5]
    

    特殊情况 x[::-1] 是'x reversed'的一个有用的习惯用语 .

    >>> a[::-1]
    [5,4,3,2,1]
    
  • 114

    Main messages :)

    import this
    # btw look at this module's source :)
    

    De-cyphered

    蒂姆·彼得斯的“禅之谜”美丽胜过丑陋 . 显式优于隐式 . 简单比复杂更好 . 复杂比复杂更好 . Flat优于嵌套 . 稀疏优于密集 . 可读性很重要 . 特殊情况不足以打破规则 . 虽然实用性胜过纯洁 . 错误不应该默默地传递 . 除非明确沉默 . 面对模棱两可,拒绝猜测的诱惑 . 应该有一个 - 最好只有一个 - 显而易见的方法 . 虽然这种方式起初可能并不明显,除非你是荷兰人 . 现在总比没有好 . 虽然从来没有比现在更好 . 如果实施很难解释,那是个坏主意 . 如果实现很容易解释,那可能是个好主意 . 命名空间是一个很棒的主意 - 让我们做更多的事情吧!

  • 247

    嵌套列表推导和生成器表达式:

    [(i,j) for i in range(3) for j in range(i) ]    
    ((i,j) for i in range(4) for j in range(i) )
    

    这些可以取代大块的嵌套循环代码 .

  • 152

    例外 else 条款:

    try:
      put_4000000000_volts_through_it(parrot)
    except Voom:
      print "'E's pining!"
    else:
      print "This parrot is no more!"
    finally:
      end_sketch()
    

    使用else子句比向try子句添加其他代码更好,因为它避免意外捕获由try ... except语句保护的代码未引发的异常 .

    http://docs.python.org/tut/node10.html

  • 141

    从2.5开始,dicts有一个特殊方法 __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]}
    

    collections 中还有一个名为 defaultdict 的dict子类,它几乎完全相同,但是为不存在的项调用一个没有参数的函数:

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

    我建议将这些dicts转换为常规dicts,然后再将它们传递给不期望这些子类的函数 . 很多代码使用 d[a_key] 并捕获KeyErrors来检查是否存在可以向dict添加新项的项 .

  • 353

    Decorators

    Decorators允许将函数或方法包装在另一个可以添加功能,修改参数或结果等的函数中 . 您可以在函数定义上方一行编写装饰器,以"at"符号(@)开头 .

    示例显示了一个 print_args 装饰器,它在调用它之前打印装饰函数的参数:

    >>> def print_args(function):
    >>>     def wrapper(*args, **kwargs):
    >>>         print 'Arguments:', args, kwargs
    >>>         return function(*args, **kwargs)
    >>>     return wrapper
    
    >>> @print_args
    >>> def write(text):
    >>>     print text
    
    >>> write('foo')
    Arguments: ('foo',) {}
    foo
    
  • 205

    以完全动态的方式创建新类型

    >>> NewType = type("NewType", (object,), {"x": "hello"})
    >>> n = NewType()
    >>> n.x
    "hello"
    

    这完全一样

    >>> class NewType(object):
    >>>     x = "hello"
    >>> n = NewType()
    >>> n.x
    "hello"
    

    可能不是最有用的东西,但很高兴知道 .

    Edit :修复了新类型的名称,应该 NewTypeclass 语句完全相同 .

    Edit :调整 Headers 以更准确地描述该功能 .

  • 183

    Context managers and the "with" Statement

    PEP 343中引入的context manager是一个对象,它充当一组语句的运行时上下文 .

    由于该功能使用了新的关键字,因此逐渐引入:它通过future指令在Python 2.5中提供 . Python 2.6及更高版本(包括Python 3)默认提供它 .

    我已经使用了很多"with" statement因为我认为它是一个非常有用的结构,这是一个快速演示:

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

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

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

    其他常见用例包括使用线程和数据库事务进行锁定 .

  • 179

    Operator overloading for the set builtin:

    >>> a = set([1,2,3,4])
    >>> b = set([3,4,5,6])
    >>> a | b # Union
    {1, 2, 3, 4, 5, 6}
    >>> a & b # Intersection
    {3, 4}
    >>> a < b # Subset
    False
    >>> a - b # Difference
    {1, 2}
    >>> a ^ b # Symmetric Difference
    {1, 2, 5, 6}
    

    标准库参考的更多细节:Set Types

  • 222

    for ... else语法(参见http://docs.python.org/ref/for.html

    for i in foo:
        if i == 0:
            break
    else:
        print("i was never 0")
    

    除非调用中断,否则“else”块通常在for循环结束时执行 .

    上面的代码可以模拟如下:

    found = False
    for i in foo:
        if i == 0:
            found = True
            break
    if not found: 
        print("i was never 0")
    
  • 258

    Get the python regex parse tree to debug your regex.

    正则表达式是python的一个很好的特性,但是调试它们可能很麻烦,并且很容易让正则表达式出错 .

    幸运的是,python可以通过将未记录的实验性隐藏标志 re.DEBUG (实际上是128)传递给 re.compile 来打印正则表达式解析树 .

    >>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
        re.DEBUG)
    at at_beginning
    literal 91
    literal 102
    literal 111
    literal 110
    literal 116
    max_repeat 0 1
      subpattern None
        literal 61
        subpattern 1
          in
            literal 45
            literal 43
          max_repeat 1 2
            in
              range (48, 57)
    literal 93
    subpattern 2
      min_repeat 0 65535
        any None
    in
      literal 47
      literal 102
      literal 111
      literal 110
      literal 116
    

    一旦理解了语法,就可以发现错误 . 在那里我们可以看到我忘了逃避 [/font] 中的 [] .

    当然,你可以将它与你想要的任何标志结合起来,比如评论的正则表达式:

    >>> re.compile("""
     ^              # start of a line
     \[font         # the font tag
     (?:=(?P<size>  # optional [font=+size]
     [-+][0-9]{1,2} # size specification
     ))?
     \]             # end of tag
     (.*?)          # text between the tags
     \[/font\]      # end of the tag
     """, re.DEBUG|re.VERBOSE|re.DOTALL)
    
  • 314

    Readable regular expressions

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

    示例详细语法(来自Dive into 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)
    

    命名匹配的示例(来自Regular Expression 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})$"
    
  • 138

    Doctest:同时进行文档和单元测试 .

    从Python文档中提取的示例:

    def factorial(n):
        """Return the factorial of n, an exact integer >= 0.
    
        If the result is small enough to fit in an int, return an int.
        Else return a long.
    
        >>> [factorial(n) for n in range(6)]
        [1, 1, 2, 6, 24, 120]
        >>> factorial(-1)
        Traceback (most recent call last):
            ...
        ValueError: n must be >= 0
    
        Factorials of floats are OK, but the float must be an exact integer:
        """
    
        import math
        if not n >= 0:
            raise ValueError("n must be >= 0")
        if math.floor(n) != n:
            raise ValueError("n must be exact integer")
        if n+1 == n:  # catch a value like 1e300
            raise OverflowError("n too large")
        result = 1
        factor = 2
        while factor <= n:
            result *= factor
            factor += 1
        return result
    
    def _test():
        import doctest
        doctest.testmod()    
    
    if __name__ == "__main__":
        _test()
    
  • 339

    描述符

    它们是一大堆核心Python功能背后的神奇之处 .

    当您使用点线访问来查找成员(例如,x.y)时,Python首先在实例字典中查找成员 . 如果找不到,它会在类字典中查找它 . 如果它在类字典中找到它,并且该对象实现了描述符协议,而不是只返回它,Python就会执行它 . 描述符是实现 __get____set____delete__ 方法的任何类 .

    以下是使用描述符实现自己的(只读)版本的属性的方法:

    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)
    

    你就像内置属性()一样使用它:

    class MyClass(object):
        @Property
        def foo(self):
            return "Foo!"
    

    Python中使用描述符来实现属性,绑定方法,静态方法,类方法和插槽等 . 理解它们可以很容易地理解为什么许多以前看起来像Python'怪癖'的东西都是它们的样子 .

    Raymond Hettinger的an excellent tutorial比我更好地描述了他们 .

  • 132

    Creating generators objects

    如果你写

    x=(n for n in foo if bar(n))
    

    你可以拿出发电机并将其分配给x . 现在它意味着你可以做到

    for n in x:
    

    这样做的好处是您不需要中间存储,如果您需要,则需要中间存储

    x = [n for n in foo if bar(n)]
    

    在某些情况下,这可以导致显着的加速 .

    您可以将许多if语句附加到生成器的末尾,基本上复制嵌套的for循环:

    >>> n = ((a,b) for a in range(0,2) for b in range(4,6))
    >>> for i in n:
    ...   print i 
    
    (0, 4)
    (0, 5)
    (1, 4)
    (1, 5)
    
  • 122

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

    “修改python的搜索路径最方便的方法”是将路径配置文件添加到已经在Python路径上的目录中,通常添加到... / site-packages /目录 . 路径配置文件的扩展名为 . pth,每行必须包含一个将附加到sys.path的路径 . (因为新路径附加到sys.path,添加目录中的模块不会覆盖标准模块 . 这意味着您无法使用此机制来安装固定版本的标准模块 . )“

  • 288

    Sending values into generator functions . 例如,具有此功能:

    def mygen():
        """Yield 5 until something else is passed back via send()"""
        a = 5
        while True:
            f = (yield a) #yield a and possibly get f in return
            if f is not None: 
                a = f  #store the new value
    

    您可以:

    >>> g = mygen()
    >>> g.next()
    5
    >>> g.next()
    5
    >>> g.send(7)  #we send this back to the generator
    7
    >>> g.next() #now it will yield 7 until we send something else
    7
    
  • 142

    命名格式

    %-formatting需要一个字典(也适用于%i /%s等验证) .

    >>> print "The %(foo)s is %(bar)i." % {'foo': 'answer', 'bar':42}
    The answer is 42.
    
    >>> foo, bar = 'question', 123
    
    >>> print "The %(foo)s is %(bar)i." % locals()
    The question is 123.
    

    由于locals()也是一个字典,你可以简单地将它作为一个字典传递,并从你的局部变量中获得%-substitions . 我认为这是不赞成的,但简化了事情..

    New Style Formatting

    >>> print("The {foo} is {bar}".format(foo='answer', bar=42))
    
  • 460

    iter() can take a callable argument

    例如:

    def seek_next_line(f):
        for c in iter(lambda: f.read(1),'\n'):
            pass
    

    iter(callable, until_value) 函数重复调用 callable 并产生其结果,直到返回 until_value .

  • 512

    In-place value swapping

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

    赋值的右侧是一个创建新元组的表达式 . 赋值的左侧立即将该(未引用的)元组解包为名称 ab .

    在赋值之后,新元组未被引用并标记为垃圾收集,并且已交换绑定到 ab 的值 .

    正如Python tutorial section on data structures所述,

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

  • 105

    Conditional Assignment

    x = 3 if (y == 1) else 2
    

    它完全听起来像:“如果y为1,则将3分配给x,否则将2分配给x” . 请注意,parens不是必需的,但我喜欢它们以便于阅读 . 如果你有更复杂的东西,你也可以链接它:

    x = 3 if (y == 1) else 2 if (y == -1) else 1
    

    虽然在某个时刻,它有点太过分了 .

    请注意,您可以在任何表达式中使用if ... else . 例如:

    (func1 if y == 1 else func2)(arg1, arg2)
    

    如果y为1,则调用func1,否则调用func2 . 在这两种情况下,将使用参数arg1和arg2调用相应的函数 .

    类似地,以下内容也是有效的:

    x = (class1 if y == 1 else class2)(arg1, arg2)
    

    其中class1和class2是两个类 .

  • 91

    如果您不喜欢使用空格来表示范围,可以通过发出以下命令来使用C风格的{}:

    from __future__ import braces
    

相关问题