博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python的隐藏功能
阅读量:2289 次
发布时间:2019-05-09

本文共 11381 字,大约阅读时间需要 37 分钟。

编程语言鲜为人知但有用的功能是什么?

  • 尝试将答案限于Python核心。
  • 每个答案一个功能。
  • 给出该功能的示例和简短描述,而不仅仅是指向文档的链接。
  • 使用标题作为第一行标记功能。

答案的快速链接:


#1楼

主要信息:)

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

提姆·彼得斯(Tim Peters)撰写的《 Python之禅》

美丽胜于丑陋。

显式胜于隐式。
简单胜于复杂。
复杂胜于复杂。
扁平比嵌套更好。
稀疏胜于密集。
可读性很重要。
特殊情况还不足以打破规则。
尽管实用性胜过纯度。
错误绝不能默默传递。
除非明确地保持沉默。
面对模棱两可的想法,拒绝猜测的诱惑。 应该有一种-最好只有一种-显而易见的方法。
尽管除非您是荷兰人,否则一开始这种方式可能并不明显。
现在总比没有好。
虽然从未往往比现在更好。
如果实现难以解释,那是个坏主意。
如果实现易于解释,则可能是个好主意。
命名空间是一个很棒的主意-让我们做更多这些吧!


#2楼

创建生成器对象

如果你写

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)

#3楼

装饰工

允许将一个函数或方法包装在另一个函数中,该函数或方法可以添加功能,修改参数或结果等。您可以在函数定义上方一行以“ 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

#4楼

可读的正则表达式

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

命名匹配示例(来自 )

>>> p = re.compile(r'(?P
\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})$"

#5楼

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

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

这些可以替换大量的嵌套循环代码。


#6楼

。 例如,具有以下功能:

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 generator7>>> g.next() #now it will yield 7 until we send something else7

#7楼

切片运算符中的step参数。 例如:

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

x[::-1]的特殊情况是“ x反转”的有用用法。

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

#8楼

链接比较运算符:

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

如果您认为它正在做1 < x ,它表示为True ,然后比较True < 10 ,它也是True ,那么不,那实际上不是什么事情(请参阅最后一个示例。)它实际上是在转化为1 < x and x < 10以及x < 10 and 10 < x * 10 and x*10 < 100 ,但键入次数较少,每个术语仅计算一次。


#9楼

重新引发异常

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

错误处理程序中不带任何参数的'raise'语句告诉Python重新引发具有完整原始追溯的异常,允许您说“哦,对不起,对不起,我不是要抓住这个,对不起,对不起。 ”

如果您希望打印,存储或摆弄原始回溯,可以使用sys.exc_info()来获取,并像Python一样使用“回溯”模块完成打印。


#10楼

就地价值交换

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

分配的右侧是创建新元组的表达式。 赋值的左侧立即将(未引用的)元组解压缩为名称ab

分配后,将不引用新元组并将其标记为垃圾回收,并且已交换绑定到ab的值。

如 ,

注意,多重分配实际上只是元组打包和序列拆包的组合。


#11楼

描述符

它们是一大堆Python核心功能背后的魔力。

当您使用点分访问来查找成员(例如xy)时,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)

您将像内置的property()一样使用它:

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

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

Raymond Hettinger ,比我做得更好。


#12楼

:同时进行文档编制和单元测试。

摘自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 resultdef _test():    import doctest    doctest.testmod()    if __name__ == "__main__":    _test()

#13楼

iter()可以接受可调用参数

例如:

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

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


#14楼

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

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

#15楼

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

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

完全一样

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

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

编辑 :新类型的固定名称,应为NewTypeclass声明完全相同。

编辑 :调整标题以更准确地描述功能。


#16楼

上下文管理器和“ with ”语句

在引入的是一个对象,它充当一组语句的运行时上下文。

由于该功能使用了新关键字,因此逐步引入了该功能:在Python 2.5中,可以通过指令使用该 。 Python 2.6及更高版本(包括Python 3)默认情况下可用。

我经常使用因为我认为这是一个非常有用的构造,下面是一个快速演示:

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

幕后发生的事情是, 调用文件对象上的特殊__enter____exit__方法。 如果在with语句主体中引发了任何异常,则异常详细信息也将传递给__exit__ ,从而允许在那里进行异常处理。

在这种特殊情况下,这为您执行的操作是保证当执行超出with套件的范围时,无论该文件是正常发生还是引发异常,该文件都将关闭。 从根本上讲,它是一种抽象通用异常处理代码的方法。

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


#17楼

函数参数解压缩

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

例如:

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

由于列表,元组和字典广泛用作容器,因此非常有用的快捷方式。


#18楼

字典具有get()方法

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

这非常适合诸如加号之类的事情:

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


#19楼

从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]}

collections还有一个名为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]并捕获d[a_key]来检查是否存在将向dict添加新项目的项目。


#20楼

如果您不喜欢使用空格来表示作用域,则可以通过发出以下命令来使用C样式的{}:

from __future__ import braces

#21楼

命名格式

%-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()也是一个字典,因此您可以简单地将其作为字典传递,并从本地变量中获取%替换。 我认为这是不满意的,但可以简化。

新样式格式

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

#22楼

注意可变的默认参数

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

相反,您应该使用表示“未给定”的前哨值,并默认替换为您想要的可变变量:

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

#23楼

要添加更多的python模块(尤其是第三方模块),大多数人似乎使用PYTHONPATH环境变量,或者在其站点包目录中添加符号链接或目录。 另一种方法是使用* .pth文件。 这是python官方文档的解释:

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


#24楼

例外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语句保护的代码未引发的异常。

参见


#25楼

for ... else语法(请参阅 )

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

除非调用break,否则“ else”块通常会在for循环的末尾执行。

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

found = Falsefor i in foo:    if i == 0:        found = True        breakif not found:     print("i was never 0")

#26楼

条件分配

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

它确实听起来像:“如果y为1,则将3分配给x,否则将2分配给x”。 请注意,不需要括号,但是出于可读性考虑,我喜欢它们。 如果您有更复杂的东西,也可以将其链接起来:

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是两个类。


#27楼

枚举

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

例如:

>>> a = ['a', 'b', 'c', 'd', 'e']>>> for index, item in enumerate(a): print index, item...0 a1 b2 c3 d4 e>>>

参考文献:


#28楼

获取python regex解析树以调试您的regex。

正则表达式是python的一个很棒的功能,但是调试它们可能会很麻烦,而且很容易弄错正则表达式。

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

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

一旦了解了语法,就可以发现错误。 在那里,我们可以看到,我忘了逃脱[][/font]

当然,您可以将其与所需的任何标志(例如带注释的正则表达式)结合使用:

>>> re.compile(""" ^              # start of a line \[font         # the font tag (?:=(?P
# 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)

#29楼

交互式口译员选项卡完成

try:    import readlineexcept 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.
class_instance.__class__ class_instance.__module__class_instance.__doc__ class_instance.function>>> class_instance.f
unction()

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


#30楼

操作符重载的set内置:

>>> 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 # SubsetFalse>>> a - b # Difference{1, 2}>>> a ^ b # Symmetric Difference{1, 2, 5, 6}

标准库参考中的更多详细信息:

转载地址:http://gbdnb.baihongyu.com/

你可能感兴趣的文章
输出最长子串 Java实现
查看>>
Hibernate事务与并发问题处理(乐观锁与悲观锁)
查看>>
使用svn进行版本控制
查看>>
mysql错误提示Illegal mix of collations (gbk_chinese_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE)的一个解决办法
查看>>
Struts2看书笔记
查看>>
杭电oj 1009
查看>>
辗转法求最小公约数和最大公倍数
查看>>
01背包问题
查看>>
蓝桥杯 剪格子
查看>>
蓝桥杯 连号区间数
查看>>
去哪儿网个2014校招笔试题 技术岗实习生
查看>>
Android 监听返回键,弹出一个退出对话框
查看>>
Android开发如何调试Service
查看>>
Android插件式开发学习笔记
查看>>
Android免root提权手机已安装apk的方法
查看>>
C/C++控制台输出时设置字体及背景颜色
查看>>
wchar_t 的输出问题
查看>>
c#笔记
查看>>
SQL学习笔记
查看>>
JAVA连接MySQL
查看>>