当前位置:  开发笔记 > 编程语言 > 正文

Python的隐藏功能

如何解决《Python的隐藏功能》经验,为你挑选了140个好方法。

Python编程语言有哪些鲜为人知但有用的功能?

尝试限制Python核心的答案.

每个答案一个功能.

举一个示例和该功能的简短描述,而不仅仅是文档的链接.

使用标题作为第一行标记要素.

快速链接到答案:

参数解包

背带

链式比较运算符

装饰

默认参数陷阱/可变默认参数的危险

字典默认.get

文档字符串测试

省略号切片语法

列举

对于/其他

作为iter()参数的函数

生成器表达式

import this

就地价值交换

列出步进

__missing__ 项目

多行正则表达式

命名字符串格式

嵌套列表/生成器理解

运行时的新类型

.pth

ROT13编码

正则表达式调试

发送给生成器

交互式解释器中的选项卡完成

三元表达

try/except/else

拆包+ print()功能

with 声明

Thomas Woute.. 740

链接比较运算符:

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

如果你正在考虑它正在做什么1 < x,True然后进行比较True < 10,然后比较,那么True,那么不,那真的不是发生了什么(参见最后一个例子.)它真正转化为1 < x and x < 10,并且x < 10 and 10 < x * 10 and x*10 < 100,但是打字较少,每个术语仅评估一次.



1> Thomas Woute..:

链接比较运算符:

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

如果你正在考虑它正在做什么1 < x,True然后进行比较True < 10,然后比较,那么True,那么不,那真的不是发生了什么(参见最后一个例子.)它真正转化为1 < x and x < 10,并且x < 10 and 10 < x * 10 and x*10 < 100,但是打字较少,每个术语仅评估一次.


这非常有帮助.它应该是所有语言的标准.可悲的是,事实并非如此.
这也适用于其他比较运算符,这就是为什么人们有时会感到惊讶为什么像(5 [5]中的5是真的)的代码是假的(但是开始时明确地测试这样的布尔值是非单音的).
很好,但要注意同等的优点,比如'in'和'='."A中的A = D中的C"表示"(B中的A)和(B == C)和(C中的D)"可能是意外的.
Azafe:Lisp的比较自然就是这样.这不是一个特例,因为没有其他(合理的)方法来解释`(<1 x 10)`.您甚至可以将它们应用于单个参数,例如`(= 10)`:http://www.cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/fun_eqcm_sleq__lteqcm_gteq.html
你应该添加一些返回false的例子.例如>>> 10 他们真的应该使用所有语言,我完全同意.
_"每个术语仅评估一次"_这是关键.

2> BatchyX..:

获取python正则表达式解析树来调试你的正则表达式.

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

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

>>> re.compile("^\[font(?:=(?P[-+][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  # 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)


除了使用正则表达式解析HTML是缓慢而痛苦的.即使是内置的"html"解析器模块也不使用正则表达式来完成工作.如果html模块不能让你满意,那么有很多XML/HTML解析器模块可以完成这项工作而无需重新发明轮子.

3> Dave..:

枚举

用枚举包装一个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
>>>

参考文献:

Python教程循环技术

Python docs内置函数 - enumerate

PEP 279


我很惊讶在关于python列表的教程中没有经常介绍这个问题.
而且这一次我用这种方式编码:对于范围内的我(len(a)):...然后使用[i]来获取当前项目.
神圣的废话这太棒了.for x in xrange(len(a)):一直是我最不喜欢的python习语.
枚举可以从任意索引开始,而不是必需的0.示例:'for i,枚举项(_list_,start = 1):print i,item'将从1开始枚举,而不是0.
@Berry Tsakala:据我所知,它还没有被弃用.
Py3K中没有弃用http://docs.python.org/py3k/library/functions.html?highlight=enumerate#enumerate

4> freespace..:

创建生成器对象

如果你写

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)


特别值得注意的是节省内存开销.值是按需计算的,因此您永远不会在内存中获得列表推导的整个结果.如果您稍后只迭代部分列表理解,那么这是特别理想的.
这不是特别"隐藏"的imo,但值得注意的是你无法回放生成器对象,而你可以重复列表任意次.
发电机的"无倒带"功能可能会引起一些混乱.具体来说,如果您打印生成器的内容以进行调试,然后稍后使用它来处理数据,则它不起作用.生成的数据由print()消耗,然后不能用于正常处理.这不适用于列表推导,因为它们完全存储在内存中.
类似的(dup?)答案:http://stackoverflow.com/questions/101268/hidden-features-of-python/165138#165138但请注意,我在这里链接的答案提到了一个关于发电机功率的真正好的介绍.你真的应该检查一下.

5> mbac32768..:

iter()可以采用可调用的参数

例如:

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

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



6> Jason Baker..:

小心可变的默认参数

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


当我得知默认参数存在于一个元组的属性中时,我发现这更容易理解,例如`foo.func_defaults`.作为一个元组,它是不可改变的.
这绝对是一个比较讨厌的隐藏功能.我不时遇到它.
一个快速入门使你的初始化更短:x = x或[].您可以使用它而不是2行if语句.
@Robert当然参数元组可能是不可变的,但它指向的对象不一定是不可变的.
@grayger:当执行def语句时,它的参数由解释器计算.这会为代码对象(函数的套件)创建(或重新绑定)名称.但是,默认参数在定义时被实例化为对象.对于默认对象的任何时间都是如此,但是当对象是可变的时,这只是显着的(暴露可见语义).没有办法在函数的闭包中重新绑定该默认参数名称,尽管它显然可以被任何调用覆盖,或者可以重新定义整个函数).

7> Rafał Dowgir..:

将值发送到生成器函数.例如具有此功能:

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


在其他语言中,我相信这个神奇的设备被称为"变量".
@finnw:该示例实现了类似于变量的东西.但是,该功能可以以许多其他方式使用...与变量不同.显而易见的是,可以使用对象(特别是实现Python的__call__方法的类)来实现类似的语义.
协程应该是协同程序,发生器也应该是自己的,没有混合.关于这个的巨大链接和谈话以及示例:http://www.dabeaz.com/coroutines/
这是一个非隐藏的功能
对于那些从未见过(也可能不会理解)共同惯例的人来说,这是一个微不足道的例子.实现运行平均值而没有sum变量溢出风险的示例是一个很好的例子.

8> eduffy..:

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

from __future__ import braces


我认为我们这里可能有一个语法错误,不应该是"来自**\_\__ _过去\ _\_**导入大括号"?
那是邪恶的.:)
来自**\_\__ _ _ _ _ _ _ _ _ _ _ _ _ _ _**_**进口大括号
这是亵渎神明!
>>> from\_\_ future\_\_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
我承认这很有趣,但与盲人相反呢?我记得有一段时间读过一个盲人和沮丧的人,由于缺乏语句括号,他/她无法使用Python.
jmucchiello:是的,你需要特定于python的东西.屏幕阅读器应该说出python解释器使用的标记,"意图进入","缩进".
@ David,@ jmucchiello:有一个脚本可以为注释中的每个块添加大括号(`#}`),实际上我已经读过使用它来让他们编写Python的盲人:)
@Alex:文本阅读器如何说缩进级别?您需要一个特定于Python的文本阅读器来告诉您"for 冒号换行符缩进传递换行符".现在添加一些缩进:"缩进缩进缩进冒号换行缩进缩进缩进缩进传递换行缩进缩进缩进<下一个语句>"
动态空白是python的优点的一半.那......扭曲了.
@David:对于盲人来说,大括号怎么样?在最佳情况下(缩进代码,Python强制执行),大括号只会增加极少量的清晰度.在我看来,一个带有空格的文本块比一个小印刷字符的存在更容易注意到.支架的易读性取决于该人所信仰的OTBS版本.我更喜欢的内嵌支架在没有适当视觉的情况下阅读会很糟糕.
非常有趣!:-)

9> Rafał Dowgir..:

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

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]


在我看来,更清楚的是reverse()函数.>>> list(reverse(range(4)))[3,2,1,0]
reverse()的问题是它返回一个迭代器,所以如果你想保留反转序列的类型(元组,字符串,列表,unicode,用户类型......),你需要一个额外的步骤来转换它.
def reverse_string(string):return string [:: - 1]
@pi我认为如果你知道足够多的定义reverse_string,那么你可以在你的代码中保留[:: - 1],并且对它的含义和感觉是合适的.
那么如何以更好的方式写出"this ia string"[:: - 1]?逆转似乎没有帮助
"".join(reverse("this ia string"))

10> DzinX..:

装饰

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


在定义装饰器时,我建议用@decorator装饰装饰器.它创建了一个装饰器,在对其进行内省时保留了函数签名.更多信息:http://www.phyast.pitt.edu/~micheles/python/documentation.html
好吧,它在大多数简单的Python教程中都没有出现,在我开始使用Python之后很长一段时间我偶然发现了它.这就是我所谓的隐藏功能,与此处的其他热门帖子差不多.
这是一个隐藏的功能?
vetler,这些问题要求"Python编程语言鲜为人知但有用的功能".你如何衡量'鲜为人知但有用的功能'?我的意思是这些响应中的任何一个如何隐藏功能?
@vetler这里的大部分东西都不是"隐藏"的.
如果标准是否记录了某个功能,则应关闭此问题.

11> rlerallut..:

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


我认为for/else语法很尴尬.如果永远不执行循环体,它"感觉"好像应该执行else子句.
似乎关键字应该是最终的,否则
除了最终已经被用于总是执行该套件的方式.
啊.从未见过那个!但我必须说这有点用词不当.谁会期望else块只有在中断时才会执行?我同意代号:看起来其他的是为空的foos输入.
应该肯定不是'其他'.也许'then'或者其他东西,然后'else'来表示循环从未被执行过.
任何人都记得FOR var ... NEXT var ... END FOR Sinclair QL的SuperBasic变种?NEXT和END FOR之间的所有内容都将在循环结束时执行,除非发出了EXIT FOR.*那*语法更清晰:)
嘿,人们忘了提这个成语也适用于`while`循环.
我一直以为`for ... then ... else`结构会更好,其中`then`仅在`for`成功时执行,'else`只在for不能输入时执行(例如:` for in in []; pass; else; print"empty list"`.但是我是新手.:)
这非常方便,我使用它,但每次都需要解释注释.
我在课程的编程任务中使用了这个并丢失了分数,因为评分者之前从未见过它......完全得到了这些.
我避开这个功能.每次我想使用它我都要阅读它,然后我仍然觉得很难做对.
我以前也常常对这种行为感到困惑,直到我用`try ..来考虑它除了..还是..其他... .. Python的`for .. else..`行为与try块的执行方式一致.如果尝试或成功的内容,跳转到其他.

12> Armin Ronach..:

从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添加新项的项.


@grayger的意思是这个`m = {}; m.setdefault('foo',[]).append(1)`.
我更喜欢使用setdefault.m = {}; m.setdefault( '富',1)
defaultdict在某些情况下比setdefault更好,因为它不会创建默认对象**,除非**缺少密钥.无论是否丢失,setdefault都会创建它.如果您的默认对象创建起来很昂贵,那么性能就会受到影响 - 只需更改所有setdefault调用,我就能从一个程序中获得不错的加速.
在其他情况下,`defaultdict`也比`setdefault`方法更强大.例如,对于counter-`dd = collections.defaultdict(int)... dd [k] + = 1` vs`d.setdefault(k,0)+ = 1`.

13> Lucas S...:

就地价值交换

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

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

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

转让后,新的元组是未引用和标记为垃圾回收,和值必然ab被交换.

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

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


它不使用更多内存.它使用较少..我只是两种方式编写它,并解编译字节码..编译器优化,你希望它会.dis结果显示它正在设置变量,然后是ROT_TWOing.ROT_TWO意味着'交换两个最顶层的堆栈变量'......实际上非常时髦.
您还无意中指出了Python的另一个不错的功能,即您可以通过用逗号分隔它们来隐式地创建项目元组.
这是我在这里读到的最不隐藏的功能.很好,但在每个Python教程中都有明确描述.
Dana the Sane:Python中的赋值是一个语句,而不是表达式,因此如果=具有更高的优先级(即它被解释为a,(b = b),a),则表达式将无效.

14> MvdD..:

可读的正则表达式

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

示例详细语法(从Dive到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\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})$"


是的,但是因为你不能在grep或大多数编辑中做到这一点,很多人都不知道它在那里.其他语言具有相同功能的事实并不能使它成为python的一个有用且鲜为人知的特性
我不知道我是否真的考虑过Python功能,大多数RE引擎都有一个冗长的选项.
在一个包含大量优化正则表达式的大型项目中(读取:针对机器优化但不针对人类),我咬了一下子弹并将它们全部转换为详细语法.现在,向项目中引入新的开发人员要容易得多.从现在开始,我们在每个项目上强制执行详细的RE.
@Ken:正则表达式可能并不总是直接在源代码中,可以从设置或配置文件中读取.允许评论或只是额外的空格(为了便于阅读)可以提供很大的帮助.

15> e-satis..:

函数参数解包

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

例如:

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被广泛用作容器.


*也称为splat运算符
pylint的建议不是法律.另一方面,apply(callable,arg_seq,arg_map)自2.3以来不推荐使用.
我喜欢这个功能,但是pylint并不遗憾.
我看到它曾在代码中使用过,并想知道它做了什么.不幸的是,很难谷歌为"Python**"

16> André..:

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

#!/usr/bin/env python
# -*- coding: rot13 -*-

cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")


这与编码无关,它只是用威尔士语写的Python.:-P
Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!
不幸的是它从py3k中删除了
大!请注意字面字符串是如何按字面意思获取的,但解码了unicode字符串:try`cevag h"Uryyb fgnpxbiresybj!"
这有利于绕过防病毒.
看到?您可以用任何语言编写难以理解的代码,即使在python中也是如此
@amyassin我也被flumoxxed,直到我记得谷歌,并找到了http://en.wiktionary.org/wiki/ph'nglui_mglw'nafh_Cthulhu_R'lyeh_wgah'nagl_fhtagn

17> Torsten Mare..:

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

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

这完全一样

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

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

编辑:固定新类型的名称,应该NewTypeclass语句完全相同.

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


注意:所有类都是在运行时创建的.因此,您可以在条件内或函数内使用'class'语句(对于创建充当闭包的类或类的族)非常有用."类型"带来的改进是能够巧妙地定义动态生成的一组属性(或基础).
这有很大的用处,例如JIT ORM
我用它来生成基于动态输入的HTML-Form类.非常好!
对代码注入非常有用.

18> Ycros..:

上下文管理器和" with"声明

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

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

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

from __future__ import with_statement

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

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

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

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


在2.7中你可以有多个`withs` :)`open('filea')作为filea而open('fileb')作为fileb:...`
这可能不言而喻,但是使用python v2.6 +,您不再需要从__future__导入.with现在是第一类关键字.
是的,嵌套范围和生成器等"可爱"功能最好留给那些知道自己在做什么的人.任何想要与未来版本的Python兼容的人.对于嵌套的作用域和生成器,Python的"未来版本"分别表示2.2和2.5.对于with语句,Python的"未来版本"意味着2.6.
@Austin我无法在2.7上使用该语法.然而这确实有效:`open('filea')作为filea,open('fileb')作为fileb:...`
我不赞成从__future__导入任何内容的代码审查.这些功能比有用的更可爱,通常它们最终会让Python新手感到困惑.

19> Rory..:

字典有一个get()方法

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

它非常适合添加数字:

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


另外,检查setdefault方法.
另外,checkout collections.defaultdict类.
如果您使用的是Python 2.7或更高版本,或3.1或更高版本,请查看集合模块中的Counter类.http://docs.python.org/library/collections.html#collections.Counter

20> Nick Johnson..:

它们是一大堆核心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)

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

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

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

Raymond Hettinger有一个很好的教程,比我更好地描述它们.


不,装饰器和描述符是完全不同的东西,虽然在示例代码中,我正在创建描述符装饰器.:)

21> tghw..:

有条件的分配

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


作业不是特殊部分.您可以轻松地执行以下操作:返回3 if(y == 1)else 2.
这种替代方式是我第一次看到混淆的Python.
这种向后风格的编码让我感到困惑.类似于`x =((y == 1)?3:2)`对我来说更有意义
我感觉与@Mark完全相反,C风格的三元运算符总是让我感到困惑,是在正确的情况下评估的右侧还是中间的?我更喜欢Python的三元语法.
Kylebrooks:在这种情况下,布尔运算符不会短路.如果bool(3)== False,它只会评估2.
我认为C风格的三元运算符更简单,更像英语:"我喝醉了吗?" '是的,和她一起''''不,甚至不考虑它'

22> Pierre-Jean ..:

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


Doctests被高估并污染文档.在没有任何setUp()的情况下,您多久测试一次独立函数?
如果一个独立的函数需要一个setUp,很可能它应该与一些不相关的东西分离或放入一个类.然后可以在类方法doctests中重用类doctest命名空间,因此它有点像setUp,只有DRY和可读.
Doctests肯定很酷,但我真的不喜欢你必须键入的所有内容来测试某些事情应该引发异常
"你经常测试一个独立的功能" - 很多.我发现在我决定外墙时,设计过程中经常会出现doctests.
谁说你不能在doctest中设置?编写一个生成上下文的函数,然后在doctest中返回`locals()``locals().update(setUp())`= D
这些非常适合确保文档字符串中的示例不会失去同步.

23> Pasi Savolai..:

命名格式

%-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.我认为这是不赞成的,但简化了事情..

新风格格式

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


将逐步淘汰并最终用string的format()方法替换.
%s格式不会被逐步淘汰.str.format()当然更加pythonic,但实际上简单的字符串替换速度要慢10倍.我的信念是%s格式仍然是最佳实践.
a*哈希*,对吧?我知道你来自哪里.
命名格式对于翻译者非常有用,因为他们往往只看到格式字符串而没有上下文的变量名
似乎在python 3.0.1中工作(需要在打印调用周围添加父主题).

24> dgrant..:

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

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



25> Constantin..:

例外其他条款:

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


+1这太棒了.如果try块在没有输入任何异常块的情况下执行,则输入else块.然后,当然,执行finally块

26> Thomas Woute..:

重新提出例外:

# 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重新引发原始回溯的异常,允许你说"哦,对不起,对不起,我不是故意要抓住它,对不起,对不起. "

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


也许更神奇,`exc_info = sys.exc_info(); raise exc_info [0],exc_info [1],exc_info [2]`等同于此,但你可以改变那些值(例如,更改异常类型或消息)
请注意斜体文本.有些人会做"提高e"而不是保留原始的追溯.
@Lucas S.嗯,我不知道,我很高兴它写在这里.

27> cleg..:

主要信息:)

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

解密:

Tim Peters的Python之禅

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


写源的方式与zen相反!
http://svn.python.org/view/python/trunk/Lib/this.py?view=markup
我更新了我的/usr/lib/python2.6/this.py,用这个`print s.translate("".join(chr(64 @MiniQuark:快速历史课:http://www.wefearchange.org/2010/06/import-this-and-zen-of-python.html

28> mjard..:

Interactive Interpreter选项卡完成

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.
class_instance.__class__   class_instance.__module__
class_instance.__doc__     class_instance.function
>>> class_instance.function()

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


IPython为您提供了大量其他整洁的东西
@akaihola读了主要的qn.
这是一个非常有用的功能.所以我有一个简单的脚本来启用它(加上其他一些内省增强功能):http://www.pixelbeat.org/scripts/inpy
@haridsv - `easy_install ipdb` - 那么你可以使用`import ipdb; ipdb.set_trace()`

29> Rafał Dowgir..:

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

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

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


要记住的关键点(这花了我很长时间才意识到)是``for``语句的顺序是按照你期望它们用标准for循环写的顺序写的,从外面的内部.
sorta喜欢微积分中的双重积分,或双重求和.
要添加到sykora的注释中:想象一下你是从一堆`for`s和`if`s with`yield x`开始的.要将其转换为生成器表达式,首先移动`x`,删除所有冒号(和`yield`),然后用括号括起整个东西.要改为列表理解,请用方括号替换外部的parens.

30> Kiv..:

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

标准库参考的更多细节:设置类型



31> Abgan..:

负圆

round()函数将浮点数舍入为十进制数的给定精度,但精度可以为负数:

>>> str(round(1234.5678, -2))
'1200.0'
>>> str(round(1234.5678, 2))
'1234.57'

注意: round()总是返回一个浮点数,str()在上面的例子中使用,因为浮点数学是不精确的,而在2.x下,第二个例子可以打印为1234.5700000000001.另见decimal模块.


或者通常,`roundNearest = lambda n,m:(n +(m/2))/ m*m`.它比我的系统上使用'round(float)`快两倍.
所以我经常需要将数字舍入到倍数.例如,第17轮到5(15)的倍数.但Python的回合不允许我这样做!IMO,它应该被构造为`round(num,precision = 1) - round"num"到最接近的"precision"倍数`
@wallacoloo与(17/5)*5有什么关系?它不简短而富有表现力吗?

32> jpsimons..:

乘以布尔值

我在Web开发中经常做的一件事是可选地打印HTML参数.我们都看到过其他语言的代码:

class='<% isSelected ? "selected" : "" %>'

在Python中,您可以乘以布尔值,它完全符合您的期望:

class='<% "selected" * isSelected %>'

这是因为乘法将布尔值强制转换为整数(0表示False,1表示True),而在python中,字符串乘以int会重复字符串N次.


你也可以使用类似:`('not-selected','selected')[isSelected]`如果你需要一个False值的选项..
在2.5中将适当的[条件表达式](http://stackoverflow.com/questions/4103667/python-ternary-operator)添加到Python中.如果你使用2.5+,你可能不应该出于可读性的原因使用这些技巧.
+1,这是一个很好的.OTOH,因为它有点神秘,出于可读性原因,很容易理解为什么你可能不想这样做.

33> Armin Ronach..:

Python的高级切片操作有一个鲜为人知的语法元素,省略号:

>>> class C(object):
...  def __getitem__(self, item):
...   return item
... 
>>> C()[1:2, ..., 3]
(slice(1, 2, None), Ellipsis, 3)

不幸的是,它几乎没有用,因为只有在涉及元组的情况下才支持省略号.


请参阅http://stackoverflow.com/questions/118370/how-do-you-use-the-ellipsis-slicing-syntax-in-python了解更多信息
实际上,省略号在处理来自`numpy`模块的多维数组时非常有用.
这应该在Python 3中更有用,其中省略号将成为文字.(尝试一下,你可以在Python 3解释器中键入`...`,它将返回`Eillipsis`)

34> Scott Kirkwo..:
可以调用函数!

事实上你可以在每次匹配正则表达式时调用函数都非常方便.在这里,我有一个样本,用"Hi"替换每个"Hello",用"Fred"等替换"there"等.

import re

def Main(haystack):
  # List of from replacements, can be a regex
  finds = ('Hello', 'there', 'Bob')
  replaces = ('Hi,', 'Fred,', 'how are you?')

  def ReplaceFunction(matchobj):
    for found, rep in zip(matchobj.groups(), replaces):
      if found != None:
        return rep

    # log error
    return matchobj.group(0)

  named_groups = [ '(%s)' % find for find in finds ]
  ret = re.sub('|'.join(named_groups), ReplaceFunction, haystack)
  print ret

if __name__ == '__main__':
  str = 'Hello there Bob'
  Main(str)
  # Prints 'Hi, Fred, how are you?'


疯了吧.我不知道这存在.真棒.非常感谢.
从来没有见过这个,但更好的例子可能是`re.sub('[aeiou]',lambda match:match.group().upper()*3,'abcdefghijklmnopqrstuvwxyz')`

35> Adrien Pliss..:

元组在python 3中解压缩

在python 3中,您可以使用与函数定义中的可选参数相同的语法来进行元组解包:

>>> first,second,*rest = (1,2,3,4,5,6,7,8)
>>> first
1
>>> second
2
>>> rest
[3, 4, 5, 6, 7, 8]

但是一个鲜为人知且功能更强大的功能允许您在列表中间包含未知数量的元素:

>>> first,*rest,last = (1,2,3,4,5,6,7,8)
>>> first
1
>>> rest
[2, 3, 4, 5, 6, 7]
>>> last
8


相当haskellish :)很酷的一个:)
我喜欢它,无赖它在2.7 ..

36> sa125..:

多行字符串

一种方法是使用反斜杠:

>>> sql = "select * from some_table \
where id > 10"
>>> print sql
select * from some_table where id > 10

另一种是使用三重报价:

>>> sql = """select * from some_table 
where id > 10"""
>>> print sql
select * from some_table where id > 10

问题在于它们没有缩进(在代码中看起来很差).如果您尝试缩进,它只会打印您放置的空白区域.

我最近发现的第三个解决方案是将你的字符串分成几行并用括号括起来:

>>> sql = ("select * from some_table " # <-- no comma, whitespace at end
           "where id > 10 "
           "order by name") 
>>> print sql
select * from some_table where id > 10 order by name

注意行之间没有逗号(这不是元组),你必须考虑字符串需要的任何尾随/前导空格.顺便说一句,所有这些都与占位符一起工作(例如"my name is %s" % name).



37> Wayne Werner..:

根据许多人的要求,这个答案已经转移到了问题本身.


这个答案可以被接受,还是被移到问题中?将这样的索引放在首位会很好.
+1这里的惊人,时间和奉献精神.

38> Tzury Bar Yo..:

下划线,它包含解释器显示的最新输出值(在交互式会话中):

>>> (a for a in xrange(10000))

>>> b = 'blah'
>>> _

一个方便的Web浏览器控制器:

>>> import webbrowser
>>> webbrowser.open_new_tab('http://www.stackoverflow.com')

内置的http服务器.要提供当前目录中的文件:

python -m SimpleHTTPServer 8000

atexit对

>>> import atexit


值得注意的是,`_`仅在交互模式下可用.从文件运行脚本时,`_`没有特殊含义.
为什么不只是SimpleHTTPServer?
@asmeurer我经常使用`_`作为我不关心的变量的名称(例如`for _,desired_value,_ in my_tuple_with_some_irrelevant_values`).是的,这是一个prologger :)

39> Tamás..:

pow()也可以有效地计算(x**y)%z.

有一个鲜为人知的内置pow()函数的第三个参数,它允许你比简单地做更有效地计算x y modulo z (x ** y) % z:

>>> x, y, z = 1234567890, 2345678901, 17
>>> pow(x, y, z)            # almost instantaneous
6

相比之下,(x ** y) % z在我的机器上一分钟没有给出相同值的结果.


@buzkor:它对密码学也非常有用
记住,这是**内置的**`pow()`函数.这不是**math.pow()函数,它只接受2个参数.
这里很酷的是你可以使用`__pow__`在你自己的对象中覆盖*这种行为.您只需要定义一个可选的第三个参数.有关使用方法的更多信息,请参阅http://en.wikipedia.org/wiki/Modular_exponentiation.

40> 小智..:

您可以轻松地使用zip转置数组.

a = [(1,2), (3,4), (5,6)]
zip(*a)
# [(1, 3, 5), (2, 4, 6)]


基本上,`zip(*a)`_unzips_`a`.所以如果`b = zip(a)`,那么`a == zip(*b)`.
如果你的元组长度不同,map(无,*a)可以派上用场:map(无,*[(1,2),(3,4,5),(5,)])=> [(1 ,3,5),(2,4,无),(无,5,无)]

41> Tamás..:

用不同的起始索引枚举

enumerate已经部分涵盖了这个答案,但最近我发现了一个更隐藏的功能enumerate,我觉得应该发表自己的帖子,而不仅仅是评论.

从Python 2.6开始,您可以enumerate在第二个参数中指定起始索引:

>>> l = ["spam", "ham", "eggs"]
>>> list(enumerate(l))
>>> [(0, "spam"), (1, "ham"), (2, "eggs")]
>>> list(enumerate(l, 1))
>>> [(1, "spam"), (2, "ham"), (3, "eggs")]

我发现它非常有用的一个地方就是我在列举对称矩阵的条目时.由于矩阵是对称的,我可以通过迭代上三角形来节省时间,但在这种情况下,我必须enumerate在内部for循环中使用不同的起始索引来正确跟踪行和列索引:

for ri, row in enumerate(matrix):
    for ci, column in enumerate(matrix[ri:], ri):
        # ci now refers to the proper column index

奇怪的是,这种行为enumerate没有记录在案help(enumerate),仅在在线文档中.



42> jfs..:

您可以使用属性使您的类接口更严格.

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

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


如果您的2.6之前版本和2.6和3.0示例实际上会呈现完全相同的东西会很好:classname不同,2.6版本之前有注释,2.6和3.0版本不包含初始化代码.

43> lacker..:

很多人不了解"dir"功能.这是一个很好的方法来确定一个对象可以从解释器做什么.例如,如果要查看所有字符串方法的列表:

>>> dir("foo")
['__add__', '__class__', '__contains__', (snipped a bunch), 'title',
 'translate', 'upper', 'zfill']

然后,如果您想了解有关特定方法的更多信息,可以在其上调用"帮助".

>>> help("foo".upper)
    Help on built-in function upper:

upper(...)
    S.upper() -> string

    Return a copy of the string S converted to uppercase.


如果您使用IPython,您可以附加问号以获取变量/方法的帮助.
dir()对于发展至关重要.对于大型模块,我已经增强了它以添加过滤功能.见http://www.pixelbeat.org/scripts/inpy
你也可以直接使用help:help('foo')

44> monkut..:

集/ frozenset

可能容易被忽视的python内置是"set/frozenset".

当你有一个像这样的列表[1,2,1,1,2,3,4]并且只想要像这样的[1,2,3,4]这样的独特时,这很有用.

使用set(),这正是你得到的:

>>> x = [1,2,1,1,2,3,4] 
>>> 
>>> set(x) 
set([1, 2, 3, 4]) 
>>>
>>> for i in set(x):
...     print i
...
1
2
3
4

当然,要获取列表中的唯一身份数量:

>>> len(set([1,2,1,1,2,3,4]))
4

您还可以使用set()查找列表是否是另一个列表的子集.issubset():

>>> set([1,2,3,4]).issubset([0,1,2,3,4,5])
True

从Python 2.7和3.0开始,您可以使用花括号来创建一个集合:

myset = {1,2,3,4}

以及设定理解:

{x for x in stuff}

有关更多详细信息,请访问:http: //docs.python.org/library/stdtypes.html#set


在仅使用字典来测试值是否存在的情况下也很有用.

45> spiv..:

内置base64,zlib和rot13编解码器

字符串也有encodedecode方法.通常这用于转换str,unicode反之亦然,例如u = s.encode('utf8').但是还有其他一些方便的内置编解码器.使用zlib(和bz2)进行压缩和解压缩是没有明确导入的:

>>> s = 'a' * 100
>>> s.encode('zlib')
'x\x9cKL\xa4=\x00\x00zG%\xe5'

同样,您可以编码和解码base64:

>>> 'Hello world'.encode('base64')
'SGVsbG8gd29ybGQ=\n'
>>> 'SGVsbG8gd29ybGQ=\n'.decode('base64')
'Hello world'

当然,你可以腐烂13:

>>> 'Secret message'.encode('rot13')
'Frperg zrffntr'


遗憾的是,这将停止在Python 3中工作
令人敬畏的是,base64在处理来自网络的数据的交互式会话中非常有用.

46> James Brady..:

口译员内的口译员

标准库的代码模块允许您在程序中包含自己的read-eval-print循环,或者运行整个嵌套的解释器.例如(从这里复制我的例子)

$ python
Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> shared_var = "Set in main console"
>>> import code
>>> ic = code.InteractiveConsole({ 'shared_var': shared_var })
>>> try:
...     ic.interact("My custom console banner!")
... except SystemExit, e:
...     print "Got SystemExit!"
... 
My custom console banner!
>>> shared_var
'Set in main console'
>>> shared_var = "Set in sub-console"
>>> import sys
>>> sys.exit()
Got SystemExit!
>>> shared_var
'Set in main console'

这对于您希望接受来自用户的脚本输入或实时查询VM状态的情况非常有用.

TurboGears通过使用WebConsole来实现这一效果,您可以从中查询实时Web应用程序的状态.



47> 小智..:
>>> from functools import partial
>>> bound_func = partial(range, 0, 10)
>>> bound_func()
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> bound_func(2)
[0, 2, 4, 6, 8]

不是真正隐藏的功能,但是部分对于对功能的后期评估非常有用.

您可以根据需要在初始调用中绑定尽可能多的参数,并稍后使用任何剩余参数调用它(在此示例中,我将开始/结束参数绑定到范围,但是第二次调用它步骤arg)

请参阅文档.


我希望curryfication在python中添加一个不错的运算符.

48> utku_karatas..:

在调试复杂的数据结构时,pprint模块非常方便.

引用文档..

>>> import pprint    
>>> stuff = sys.path[:]
>>> stuff.insert(0, stuff)
>>> pprint.pprint(stuff)
[,
 '',
 '/usr/local/lib/python1.5',
 '/usr/local/lib/python1.5/test',
 '/usr/local/lib/python1.5/sunos5',
 '/usr/local/lib/python1.5/sharedmodules',
 '/usr/local/lib/python1.5/tkinter']


pprint也适用于在doctests中打印字典,因为它总是按键对输出进行排序

49> Constantin..:

Python有GOTO

...它由外部纯Python模块实现 :)

from goto import goto, label
for i in range(1, 10):
    for j in range(1, 20):
        for k in range(1, 30):
            print i, j, k
            if k == 3:
                goto .end # breaking out from a deeply nested loop
label .end
print "Finished"


也许这个功能最好隐藏起来.
那么,这里的实际隐藏功能是用于实现GOTO的机制.
@shylent:异常应该是例外.出于这个原因,他们针对不抛出的情况进行了优化.如果您希望在正常处理过程中出现这种情况,则应使用其他方法
@shylent,打破嵌套循环的正确方法是将循环放入函数中,并从函数返回
当然,为了打破嵌套循环你只能引发异常,不是吗?

50> 小智..:

dict的构造函数接受关键字参数:

>>> dict(foo=1, bar=2)
{'foo': 1, 'bar': 2}


只要关键字参数是有效的Python标识符(名称).您不能使用:dict(1 ="one",two = 2 ...)因为"1"不是有效的标识符,即使它是完全有效的字典键.

51> Ruslan Spiva..:

序列乘法和反射操作数

>>> 'xyz' * 3
'xyzxyzxyz'

>>> [1, 2] * 3
[1, 2, 1, 2, 1, 2]

>>> (1, 2) * 3
(1, 2, 1, 2, 1, 2)

我们使用反射(交换)操作数获得相同的结果

>>> 3 * 'xyz'
'xyzxyzxyz'

它的工作原理如下:

>>> s = 'xyz'
>>> num = 3

要评估表达式s*num解释器调用s .___ mul ___(num)

>>> s * num
'xyzxyzxyz'

>>> s.__mul__(num)
'xyzxyzxyz'

要评估表达式num*s解释器调用num .___ mul ___(s)

>>> num * s
'xyzxyzxyz'

>>> num.__mul__(s)
NotImplemented

如果调用返回NotImplemented,则解释器调用反射操作s .___ rmul ___(num)如果操作数具有不同类型

>>> s.__rmul__(num)
'xyzxyzxyz'

请参阅http://docs.python.org/reference/datamodel.html#object.RMUL


+1我知道序列乘法,但反射的操作数对我来说是新的.

52> Ber..:

模块运算符中的Getter功能

函数attrgetter()itemgetter()模块operator可用于生成快速访问函数,以用于排序和搜索对象和字典

Python库文档中的第6.7章



53> Torsten Mare..:

交错iffor列表理解

>>> [(x, y) for x in range(4) if x % 2 == 1 for y in range(4)]
[(1, 0), (1, 1), (1, 2), (1, 3), (3, 0), (3, 1), (3, 2), (3, 3)]

在我学习Haskell之前,我从未意识到这一点.


不太酷,你只是有一个列表理解与两个for循环.有什么令人惊讶的?
我想知道,有没有办法用别的方法做到这一点?`[a(a,b)in zip(lista,listb)如果a == b else:' - ']`

54> ianb..:

元组拆包:

>>> (a, (b, c), d) = [(1, 2), (3, 4), (5, 6)]
>>> a
(1, 2)
>>> b
3
>>> c, d
(4, (5, 6))

更晦涩的是,您可以在函数参数中执行此操作(在Python 2.x中; Python 3.x将不再允许此操作):

>>> def addpoints((x1, y1), (x2, y2)):
...     return (x1+x2, y1+y2)
>>> addpoints((5, 0), (3, 5))
(8, 5)


对于它的价值,在函数定义中的元组解包在python 3.0中是有用的
主要是因为据我所知,它使实现真的很糟糕.(例如,标准库中的inspect.getargs - 正常路径(没有元组args)大约是10行,并且还有大约30行用于处理元组args(偶尔会偶尔使用).)让我很难过.
它为什么会消失?

55> tadeusz..:

显然,反重力模块. xkcd#353


哪个确实有效.尝试在最新的Py3K中加入"import antigravity".
可能是我最常用的模块.当然,灵魂模块之后.

56> davidavr..:

Python解释器

>>> 

也许不是鲜为人知,但肯定是我最喜欢的Python功能之一.


你见过的其他一切.
它还有iPython,它比默认的解释器要好得多
Python比其他一切更好的首要原因.

57> 小智..:

Python排序函数正确排序元组(即使用熟悉的词典顺序):

a = [(2, "b"), (1, "a"), (2, "a"), (3, "c")]
print sorted(a)
#[(1, 'a'), (2, 'a'), (2, 'b'), (3, 'c')]

如果您想在年龄之后对人员列表进行排序然后命名,则非常有用.


这对于版本元组很有用:(1,9)<(1,10).
这是元组比较通常正常工作的结果,即(1,2)<(1,3).

58> Jake..:

在构建时引用列表理解...

您可以引用列表推导,因为它是由符号'_ [1]'构建的.例如,以下函数unique-ifies元素列表,而不通过引用其列表推导来更改其顺序.

def unique(my_list):
    return [x for x in my_list if x not in locals()['_[1]']]


这是一个未记录的实现细节,而不是隐藏的功能.依靠这个是一个坏主意.
对算法和实际原因不是一个好主意.从算法上讲,这将使您在每次迭代时对列表进行线性搜索,将O(n)循环更改为O(n**2); 之后将列表放入集合中要好得多.实际上,它没有文档,可能会改变,并且可能在ironpython/jython/pypy中不起作用.
漂亮的把戏.你知道这是否是可接受的行为,还是更糟糕的黑客可能会在未来发生变化?下划线让我想到了后者.

59> Noctis Skyto..:

解压缩语法已在最新版本中升级,如示例中所示.

>>> a, *b = range(5)
>>> a, b
(0, [1, 2, 3, 4])
>>> *a, b = range(5)
>>> a, b
([0, 1, 2, 3], 4)
>>> a, *b, c = range(5)
>>> a, b, c
(0, [1, 2, 3], 4)


从来没有见过这个,非常好!

60> Chmouel Boud..:

简单:

>>> 'str' in 'string'
True
>>> 'no' in 'yes'
False
>>> 

是我喜欢Python的东西,我已经看到很多不那么像这样的pythonic成语:

if 'yes'.find("no") == -1:
    pass



61> Matthias Kes..:

元类

当然:-) 什么是Python中的元类?



62> Tom..:

我个人喜欢3种不同的报价

str = "I'm a string 'but still I can use quotes' inside myself!"
str = """ For some messy multi line strings.
Such as

 ... """

同样很酷:不必逃避正则表达式,使用原始字符串避免可怕的反斜杠沙拉:

str2 = r"\n" 
print str2
>> \n


_Four_不同的引号,如果你包括''''

63> Robert Rossn..:

发电机

我认为很多初学的Python开发人员都没有真正掌握它们的用途或者对它们的能力有所了解.直到我读到David M. Beazley关于发电机的PyCon演示文稿(它可以在这里找到),我才意识到它们是多么有用(必不可少).那个演示文稿阐明了对我来说是一种全新的编程方式,我推荐给那些对发电机没有深刻理解的人.


哇!我的大脑是油炸的,这只是前6个部分.从7开始,我不得不开始绘制图片,看看我是否真的了解多进程/多线程/多机器处理流水线的情况.太棒了!

64> e-satis..:

隐式连接:

>>> print "Hello " "World"
Hello World

想要在脚本中的多行上创建长文本时很有用:

hello = "Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello " \
        "Word"

要么

hello = ("Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello " 
         "Word")


好吧,一个PEP已经准备摆脱它,但Guido决定最终保留它.我想它比仇恨更有用.实际上,缺点是没有那么危险(没有安全问题),对于长串,它有很大帮助.
要使长文本适合多行,您还可以使用三引号.
任何忘记了字符串列表中逗号的人都知道这个"特征"是多么邪恶.
这可能是我最喜欢的Python功能.你可以忘记正确的语法,它仍然是正确的语法.

65> Giampaolo Ro..:

使用交互式shell时,"_"包含最后打印项的值:

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> _
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>



66> Remco Wendt..:

textwrap.dedentpython中的实用程序函数可以非常方便地测试返回的多行字符串是否等于预期输出而不会破坏单元测试的缩进:

import unittest, textwrap

class XMLTests(unittest.TestCase):
    def test_returned_xml_value(self):
        returned_xml = call_to_function_that_returns_xml()
        expected_value = textwrap.dedent("""\
        
        
            my_content
        
        """)

        self.assertEqual(expected_value, returned_xml)



67> David Z..:

零参数和变量参数lambda

Lambda函数通常用于将一个值快速转换为另一个值,但它们也可用于在函数中包装值:

>>> f = lambda: 'foo'
>>> f()
'foo'

他们也可以接受通常*args**kwargs语法:

>>> g = lambda *args, **kwargs: args[0], kwargs['thing']
>>> g(1, 2, 3, thing='stuff')
(1, 'stuff')



68> 小智..:

使用关键字参数作为分配

有时,人们希望根据一个或多个参数构建一系列函数.但是,这可能很容易导致闭包所有引用相同的对象和值:

funcs = [] 
for k in range(10):
     funcs.append( lambda: k)

>>> funcs[0]()
9
>>> funcs[7]()
9

通过将lambda表达式转换为仅依赖于其参数的函数,可以避免此行为.关键字参数存储绑定到它的当前值.函数调用不必更改:

funcs = [] 
for k in range(10):
     funcs.append( lambda k = k: k)

>>> funcs[0]()
0
>>> funcs[7]()
7


一种不那么强硬的方法(imho)只是使用一个单独的函数来制造不关闭循环变量的lambda.像这样:`def make_lambda(k):return lambda:k`.

69> jpsimons..:

Mod可以正数使用负数

-1%5是4,因为它应该是-1,而不是像其他语言一样的JavaScript.这使得"环绕式窗口"在Python中变得更干净,你只需这样做:

index = (index + increment) % WINDOW_SIZE



70> Jeremy Cantr..:

一流的功能

它并不是一个隐藏的功能,但功能是一流的对象这一事实非常棒.你可以像任何其他变量一样传递它们.

>>> def jim(phrase):
...   return 'Jim says, "%s".' % phrase
>>> def say_something(person, phrase):
...   print person(phrase)

>>> say_something(jim, 'hey guys')
'Jim says, "hey guys".'


任何没有第一类函数(或者至少是一些好的替代品,比如C函数指针)的语言都是错误的.没有,完全无法忍受.
这也使得回调和钩子创建(以及因此,为Python脚本创建插件)如此微不足道,以至于您可能甚至不知道自己在做什么.

71> Alexander Ko..:

三元运算符

>>> 'ham' if True else 'spam'
'ham'
>>> 'ham' if False else 'spam'
'spam'

这是在2.5中添加的,在此之前您可以使用:

>>> True and 'ham' or 'spam'
'ham'
>>> False and 'ham' or 'spam'
'spam'

但是,如果您要使用的值将被视为false,则存在差异:

>>> [] if True else 'spam'
[]
>>> True and [] or 'spam'
'spam'



72> Torsten Mare..:

分配和删除切片:

>>> a = range(10)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[:5] = [42]
>>> a
[42, 5, 6, 7, 8, 9]
>>> a[:1] = range(5)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[::2]
>>> a
[1, 3, 5, 7, 9]
>>> a[::2] = a[::-2]
>>> a
[9, 3, 5, 7, 1]

注意:分配给扩展切片(s[start:stop:step])时,指定的可迭代必须与切片具有相同的长度.



73> Markus..:

不是很隐蔽,但功能有属性:

def doNothing():
    pass

doNothing.monkeys = 4
print doNothing.monkeys
4


这是因为函数可以作为定义了__call __()函数的对象.
这是因为函数可以被认为是定义了__call __()函数的描述符.
我敢打赌它的__call __()功能一直向下.

74> evilpie..:

将元组传递给内置函数

很多Python函数都接受元组,它似乎也不像.例如,您想测试您的变量是否为数字,您可以这样做:

if isinstance (number, float) or isinstance (number, int):  
   print "yaay"

但是,如果你通过我们元组,这看起来更清洁:

if isinstance (number, (float, int)):  
   print "yaay"



75> Evgeny..:

在字典中无限递归的好处理:

>>> a = {}
>>> b = {}
>>> a['b'] = b
>>> b['a'] = a
>>> print a
{'b': {'a': {...}}}



76> 小智..:

使用负步骤反转可迭代

>>> s = "Hello World"
>>> s[::-1]
'dlroW olleH'
>>> a = (1,2,3,4,5,6)
>>> a[::-1]
(6, 5, 4, 3, 2, 1)
>>> a = [5,4,3,2,1]
>>> a[::-1]
[1, 2, 3, 4, 5]


该符号实际上将创建该序列的新(反向)实例,在某些情况下这可能是不合需要的.对于这种情况,`reversed()`函数更好,因为它返回一个反向迭代器而不是分配一个新的序列.
很高兴知道,但小点:只适用于序列而不是一般的迭代.即,`(n为(1,2,3,4,5)中的n [] - :: - 1]`不起作用.

77> Noufal Ibrah..:

不是"隐藏"但非常有用且不常用

像这样快速创建字符串连接功能

 comma_join = ",".join
 semi_join  = ";".join

 print comma_join(["foo","bar","baz"])
 'foo,bar,baz

能够比引号,逗号混乱更优雅地创建字符串列表.

l = ["item1", "item2", "item3"]

取而代之

l = "item1 item2 item3".split()



78> Kimvais..:

可以说,这本身并不是一个编程功能,但是非常有用,我会发布它.

$ python -m http.server

......其次是$ wget http://:8000/filename其他地方.

如果您仍在运行较旧的(2.x)版本的Python:

$ python -m SimpleHTTPServer

您也可以指定一个端口python -m http.server 80(例如,如果您在服务器端有根,则可以省略URL中的端口)



79> David Z..:

对迭代器的多个引用

您可以使用列表乘法创建对同一迭代器的多个引用:

>>> i = (1,2,3,4,5,6,7,8,9,10) # or any iterable object
>>> iterators = [iter(i)] * 2
>>> iterators[0].next()
1
>>> iterators[1].next()
2
>>> iterators[0].next()
3

这可以在本实施例中被用来组可迭代成块,例如,作为来自itertools文档

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)


我实际上没有看到做这一点的区别:"a ​​= iter(i)",随后"b = a"我也得到多个对同一个迭代器的引用 - 对我没有任何魔力,没有隐藏功能它只是正常的参考复制语言的东西.做了什么,是创建迭代器,然后(列表乘法)多次复制这个迭代器.多数民众赞成,一切都在语言中.
@Juergen:的确,`a = iter(i); b = a`做同样的事情我也可以把它写进答案而不是`[iter(i)]*n`.无论哪种方式,它都没有"神奇".这与这个问题的任何其他答案都没有什么不同 - 它们都不是"神奇的",它们都在语言中.使这些功能"隐藏"的原因是许多人没有意识到它们是可能的,或者没有意识到它们可以被使用的有趣方式,直到明确指出它们为止.

80> Piotr Duda..:

从python 3.1(2.7)支持字典和集合理解:

{ a:a for a in range(10) }
{ a for a in range(10) }



81> u0b34a0f6ae..:

Python 可以理解任何类型的unicode数字,而不仅仅是ASCII类:

>>> s = u'?????'
>>> s
u'\uff11\uff10\uff15\uff18\uff15'
>>> print s
?????
>>> int(s)
10585
>>> float(s)
10585.0



82> Armin Ronach..:

__slots__是一种节省内存的好方法,但很难得到对象值的字典.想象一下以下对象:

class Point(object):
    __slots__ = ('x', 'y')

现在该对象显然有两个属性.现在我们可以创建它的实例并以这种方式构建它的字典:

>>> p = Point()
>>> p.x = 3
>>> p.y = 5
>>> dict((k, getattr(p, k)) for k in p.__slots__)
{'y': 5, 'x': 3}

但是如果点被子类化并且添加了新的插槽,则这将不起作用.但是Python会自动实现__reduce_ex__以帮助copy模块.这可能会被滥用来获得价值观:

>>> p.__reduce_ex__(2)[2][1]
{'y': 5, 'x': 3}


你仍然可以做`object .__ reduce_ex __(p,2)[2] [1]`.

83> 小智..:

itertools

这个模块经常被忽视.以下示例用于itertools.chain() 展平列表:

>>> from itertools import *
>>> l = [[1, 2], [3, 4]]
>>> list(chain(*l))
[1, 2, 3, 4]

有关更多应用程序,请参阅http://docs.python.org/library/itertools.html#recipes.



84> Thomas Woute..:

操作sys.modules

您可以直接操作模块缓存,使模块可用或不可用:

>>> import sys
>>> import ham
Traceback (most recent call last):
  File "", line 1, in 
ImportError: No module named ham

# Make the 'ham' module available -- as a non-module object even!
>>> sys.modules['ham'] = 'ham, eggs, saussages and spam.'
>>> import ham
>>> ham
'ham, eggs, saussages and spam.'

# Now remove it again.
>>> sys.modules['ham'] = None
>>> import ham
Traceback (most recent call last):
  File "", line 1, in 
ImportError: No module named ham

这适用于可用的模块,某种程度上适用于已导入的模块:

>>> import os
# Stop future imports of 'os'.
>>> sys.modules['os'] = None
>>> import os
Traceback (most recent call last):
  File "", line 1, in 
ImportError: No module named os
# Our old imported module is still available.
>>> os

如最后一行所示,更改sys.modules只影响将来的import语句,而不是过去的语句,所以如果你想影响其他模块,给他们机会尝试导入模块之前进行这些更改是很重要的 - 所以在你之前通常导入它们.None是一个特殊的值sys.modules,用于负缓存(表示第一次找不到模块,所以再看一遍没有意义.)任何其他值都将是import操作的结果- 即使它不是模块对象.您可以使用它来替换具有与您想要的行为完全相同的对象的模块.sys.modules完全删除条目会导致下一个条目import正常搜索模块,即使它之前已经导入过.



85> John D. Cook..:

您可以通过查看其__ module__属性来询问任何对象来自哪个模块.例如,如果您在命令行进行实验并导入了很多东西,这很有用.

同样,您可以通过查看其__ file__属性来询问模块的来源.这在调试路径问题时很有用.



86> daniel..:

一些内置的收藏夹,map(),reduce()和filter().一切都非常快速和强大.


@recursive:我无法生成一个列表理解/生成器表达式,它执行`reduce()`的操作
@sil:map仍然存在于Python 3中,过滤器也是如此,而reduce则以functools.reduce的形式存在.
如果滥用Python代码,它也可能会混淆Python代码

87> Ken Arnold..:

一句话:IPython

标签内省,漂亮印刷,%debug历史管理pylab,......值得花时间学习.



88> 小智..:

猜整数基数

>>> int('10', 0)
10
>>> int('0x10', 0)
16
>>> int('010', 0)  # does not work on Python 3.x
8
>>> int('0o10', 0)  # Python >=2.6 and Python 3.x
8
>>> int('0b10', 0)  # Python >=2.6 and Python 3.x
2



89> Dan Lenski..:

您可以从一组长度为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}



90> Denis Otkida..:

在子类中扩展属性(定义为描述符)

有时,扩展(修改)子类中描述符"返回"的值是有用的.它可以很容易地完成super():

class A(object):
    @property
    def prop(self):
        return {'a': 1}

class B(A):
    @property
    def prop(self):
        return dict(super(B, self).prop, b=2)

将其存储test.py并运行python -i test.py(另一个隐藏功能:-i选项执行脚本并允许您以交互模式继续):

>>> B().prop
{'a': 1, 'b': 2}



91> Martin Becke..:

蟒蛇的轻微错误.将字符串列表连接在一起的正常快速方法是,

''.join(list_of_strings)


有很好的理由认为这是一种字符串方法而不是列表方法.这允许相同的函数连接任何可迭代的,而不是为每个可迭代类型复制连接.
如果这对你来说太难看了,你可以编写与`str.join('',list_of_strings)`完全相同的东西,但是其他pythonistas可能会因为你试图编写java而嘲笑你.

92> Chinmay Kanc..:

创建枚举

在Python中,您可以这样做以快速创建枚举:

>>> FOO, BAR, BAZ = range(3)
>>> FOO
0

但"枚举"不必具有整数值.你甚至可以这样做:

class Colors(object):
    RED, GREEN, BLUE, YELLOW = (255,0,0), (0,255,0), (0,0,255), (0,255,255)

#now Colors.RED is a 3-tuple that returns the 24-bit 8bpp RGB 
#value for saturated red



93> asmeurer..:

对象数据模型

您可以使用您自己的类的语言覆盖任何运算符.有关完整列表,请参阅此页面.一些例子:

您可以覆盖任何运算符(* + - / // % ^ == < > <= >= .等).所有这一切都是通过重写完成__mul__,__add__等你的对象.你甚至可以忽略的东西喜欢__rmul__单独处理your_object*something_elsesomething_else*your_object. .是属性access(a.b),可以b通过使用来覆盖任何任意处理__getattr__.此处还包括a(…)使用__call__.

你可以创建自己的切片语法(a[stuff]),这是非常复杂的,从列表(numpy的有这在他们的阵列电源的一个很好的例子),用于使用任意组合的标准语法完全不同,,:你喜欢,使用Slice对象.

特别处理语言中的许多关键字会发生什么.包括的是del,in,import,和not.

处理当您的对象调用许多内置函数时会发生什么.标准的__int__,__str__等去这里,但这么做__len__,__reversed__,__abs__,和三个参数__pow__(模块化幂).



94> dan_waterwor..:

re.Scanner班.http://code.activestate.com/recipes/457664-hidden-scanner-functionality-in-re-module/



95> csl..:

"解包"到功能参数

def foo(a, b, c):
        print a, b, c

bar = (3, 14, 15)
foo(*bar)

执行打印时:

3 14 15



96> Christian Ou..:

reversed()内置.在许多情况下,它使迭代更加清晰.

快速举例:

for i in reversed([1, 2, 3]):
    print(i)

生产:

3
2
1

但是,reversed()也适用于任意迭代器,例如文件中的行或生成器表达式.



97> 小智..:

Python的禅宗

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!



98> Foo Bah..:

在运行时更改功能标签:

>>> class foo:
...   def normal_call(self): print "normal_call"
...   def call(self): 
...     print "first_call"
...     self.call = self.normal_call

>>> y = foo()
>>> y.call()
first_call
>>> y.call()
normal_call
>>> y.call()
normal_call
...



99> Roman Bodnar..:

string-escapeunicode-escape编码

假设你有一个来自外部源的字符串,包含\n,\t等等.如何将它们转换为换行符或制表符?只需使用string-escape编码解码字符串!

>>> print s
Hello\nStack\toverflow
>>> print s.decode('string-escape')
Hello
Stack   overflow

另一个问题.你有正常的字符串与unicode文字像\u01245.如何使它工作?只需使用unicode-escape编码解码字符串!

>>> s = '\u041f\u0440\u0438\u0432\u0456\u0442, \u0441\u0432\u0456\u0442!'
>>> print s
\u041f\u0440\u0438\u0432\u0456\u0442, \u0441\u0432\u0456\u0442!
>>> print unicode(s)
\u041f\u0440\u0438\u0432\u0456\u0442, \u0441\u0432\u0456\u0442!
>>> print unicode(s, 'unicode-escape')
??????, ????!



100> Paddy3118..:

解压缩Python中不需要的东西

有人在博客上发表了关于Python没有解压缩功能的解决方案.unzip是直接计算的,因为:

>>> t1 = (0,1,2,3)
>>> t2 = (7,6,5,4)
>>> [t1,t2] == zip(*zip(t1,t2))
True

但是在反思时,我宁愿有一个明确的解压缩().


def unzip(x):return zip(*x)完成!

101> Lakshman Pra..:

创建具有相关数据的两个序列的字典

In [15]: t1 = (1, 2, 3)

In [16]: t2 = (4, 5, 6)

In [17]: dict (zip(t1,t2))
Out[17]: {1: 4, 2: 5, 3: 6}



102> L̲̳o̲̳̳n̲̳̳g..:

最高机密属性

>>> class A(object): pass
>>> a = A()
>>> setattr(a, "can't touch this", 123)
>>> dir(a)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', "can't touch this"]
>>> a.can't touch this # duh
  File "", line 1
    a.can't touch this
                     ^
SyntaxError: EOL while scanning string literal
>>> getattr(a, "can't touch this")
123
>>> setattr(a, "__class__.__name__", ":O")
>>> a.__class__.__name__
'A'
>>> getattr(a, "__class__.__name__")
':O'


AHHHH!坏,坏,坏!

103> Apalala..:

namedtuple是一个元组

>>> node = namedtuple('node', "a b")
>>> node(1,2) + node(5,6)
(1, 2, 5, 6)
>>> (node(1,2), node(5,6))
(node(a=1, b=2), node(a=5, b=6))
>>> 

还有一些回应评论的实验:

>>> from collections import namedtuple
>>> from operator import *
>>> mytuple = namedtuple('A', "a b")
>>> yourtuple = namedtuple('Z', "x y")
>>> mytuple(1,2) + yourtuple(5,6)
(1, 2, 5, 6)
>>> q = [mytuple(1,2), yourtuple(5,6)]
>>> q
[A(a=1, b=2), Z(x=5, y=6)]
>>> reduce(operator.__add__, q)
(1, 2, 5, 6)

所以,namedtuple是一个有趣的子类型tuple.


同样有趣的是,您可以将`namedtuple`调用的结果直接输入到类定义中,如`class rectangle(namedtuple("rectangle","width height")):`以便添加自定义方法

104> FernandoEsch..:

动态添加属性

如果您考虑通过调用它们来为类添加一些属性,这可能会很有用.这可以通过覆盖__getattribute__使用点操作数时调用的成员函数来完成.所以,让我们看一个虚拟类,例如:

class Dummy(object):
    def __getattribute__(self, name):
        f = lambda: 'Hello with %s'%name
        return f

当您实例化Dummy对象并执行方法调用时,您将获得以下内容:

>>> d = Dummy()
>>> d.b()
'Hello with b'

最后,您甚至可以将属性设置为您的类,以便可以动态定义它.如果您使用Python Web框架并希望通过解析属性的名称来执行查询,这可能很有用.

我有一个关于github 的要点,这个简单的代码和它在Ruby上由朋友制作.

照顾自己!



105> Johnsyweb..:

平展listsum().

sum()内置函数可用于小号一起,提供了一种方便的方法,以一个扁平化的S:__add__ listlistlist

Python 2.7.1 (r271:86832, May 27 2011, 21:41:45) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> l = [[1, 2, 3], [4, 5], [6], [7, 8, 9]]
>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]



106> cerberos..:

博格模式

这是Alex Martelli的杀手.Borg共享状态的所有实例.这消除了使用单例模式的需要(实例在共享状态时无关紧要)并且相当优雅(但新类更复杂).

foo可以在任何实例中重新分配值,并且所有值都将更新,您甚至可以重新分配整个dict.博格是一个完美的名字,在这里阅读更多.

class Borg:
    __shared_state = {'foo': 'bar'}
    def __init__(self):
        self.__dict__ = self.__shared_state
    # rest of your class here

这非常适合共享eventlet.GreenPool来控制并发性.



107> Tom Viner..:

pdb - Python调试器

作为程序员,严肃的程序开发需要的第一件事就是调试器.Python有一个内置的,可以作为一个名为pdb的模块使用(对于"Python DeBugger",当然!).

http://docs.python.org/library/pdb.html



108> haridsv..:

threading.enumerate()允许访问系统中的所有Thread对象,sys._current_frames()返回系统中所有线程的当前堆栈帧,因此将这两者结合起来,您将获得Java样式堆栈转储:

def dumpstacks(signal, frame):
    id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
    code = []
    for threadId, stack in sys._current_frames().items():
        code.append("\n# Thread: %s(%d)" % (id2name[threadId], threadId))
        for filename, lineno, name, line in traceback.extract_stack(stack):
            code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
            if line:
                code.append("  %s" % (line.strip()))
    print "\n".join(code)

import signal
signal.signal(signal.SIGQUIT, dumpstacks)

在多线程python程序的开头执行此操作,您可以通过发送SIGQUIT随时访问当前线程状态.您也可以选择signal.SIGUSR1或signal.SIGUSR2.

看到



109> Steen..:

... dict.get()具有默认值 None,从而避免了KeyErrors:

In [1]: test = { 1 : 'a' }

In [2]: test[2]
---------------------------------------------------------------------------
              Traceback (most recent call last)

<ipython console> in ()

: 2

In [3]: test.get( 2 )

In [4]: test.get( 1 )
Out[4]: 'a'

In [5]: test.get( 2 ) == None
Out[5]: True

甚至在现场指定这个:

In [6]: test.get( 2, 'Some' ) == 'Some'
Out[6]: True

你可以使用setdefault()来设置一个值,如果它不存在则返回:

>>> a = {}
>>> b = a.setdefault('foo', 'bar')
>>> a
{'foo': 'bar'}
>>> b
'bar



110> Pratik Deogh..:

检查模块也是一个很酷的功能.



111> Ken Arnold..:

重新加载模块可实现"实时编码"风格.但是类实例不会更新.这就是原因,以及如何解决它.记住,一切,是的,一切都是一个对象.

>>> from a_package import a_module
>>> cls = a_module.SomeClass
>>> obj = cls()
>>> obj.method()
(old method output)

现在,您更改了a_module.py中的方法,并希望更新您的对象.

>>> reload(a_module)
>>> a_module.SomeClass is cls
False # Because it just got freshly created by reload.
>>> obj.method()
(old method output)

这是更新它的一种方法(但考虑用剪刀运行):

>>> obj.__class__ is cls
True # it's the old class object
>>> obj.__class__ = a_module.SomeClass # pick up the new class
>>> obj.method()
(new method output)

这是"用剪刀运行",因为对象的内部状态可能与新类所期望的不同.这适用于非常简单的情况,但除此之外,pickle是你的朋友.但是,了解其原因仍然有用.



112> Denilson Sá ..:

原始字符串中的反斜杠仍然可以转义引号.看到这个:

>>> print repr(r"aaa\"bbb")
'aaa\\"bbb'

请注意,反斜杠和双引号都出现在最终字符串中.

因此,您无法使用反斜杠结束原始字符串:

>>> print repr(r"C:\")
SyntaxError: EOL while scanning string literal
>>> print repr(r"C:\"")
'C:\\"'

发生这种情况是因为实现了原始字符串以帮助编写正则表达式,而不是编写Windows路径.在Gotcha中阅读关于此的长篇讨论- Windows文件名中的反斜杠.


请注意,反斜杠后面仍然是*字符串的一部分......所以有人可能不认为这是常规的转义.

113> Brendon Craw..:

操作符可以作为函数调用:

from operator import add
print reduce(add, [1,2,3,4,5,6])



114> Elisha..:

列表中的无限递归

>>> a = [1,2]
>>> a.append(a)
>>> a
[1, 2, [...]]
>>> a[2]
[1, 2, [...]]
>>> a[2][2][2][2][2][2][2][2][2] == a
True



115> Paweł Hajdan..:

能够替换文件删除,文件打开等内容 - 直接操作语言库.这在测试时是一个巨大的优势.您不必将所有内容都包装在复杂的容器中.只需替换一个函数/方法然后去.这也称为猴子修补.



116> Armin Ronach..:

内置方法或函数不实现描述符协议,这使得无法执行以下操作:

>>> class C(object):
...  id = id
... 
>>> C().id()
Traceback (most recent call last):
  File "", line 1, in 
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



117> ironfroggy..:

嵌套函数参数重新绑定

def create_printers(n):
    for i in xrange(n):
        def printer(i=i): # Doesn't work without the i=i
            print i
        yield printer



118> Benjamin Pet..:

您可以使用元类覆盖类的mro

>>> class A(object):
...     def a_method(self):
...         print("A")
... 
>>> class B(object):
...     def b_method(self):
...         print("B")
... 
>>> class MROMagicMeta(type):
...     def mro(cls):
...         return (cls, B, object)
... 
>>> class C(A, metaclass=MROMagicMeta):
...     def c_method(self):
...         print("C")
... 
>>> cls = C()
>>> cls.c_method()
C
>>> cls.a_method()
Traceback (most recent call last):
 File "", line 1, in 
AttributeError: 'C' object has no attribute 'a_method'
>>> cls.b_method()
B
>>> type(cls).__bases__
(,)
>>> type(cls).__mro__
(, , )

这可能是有充分理由隐藏的.:)


那是在玩火,并要求以太诅咒.更好有充分的理由;)

119> Mykola Khare..:

小整数(-5 .. 256)的对象从未创建过两次:


>>> a1 = -5; b1 = 256
>>> a2 = -5; b2 = 256
>>> id(a1) == id(a2), id(b1) == id(b2)
(True, True)
>>>
>>> c1 = -6; d1 = 257
>>> c2 = -6; d2 = 257
>>> id(c1) == id(c2), id(d1) == id(d2)
(False, False)
>>>

编辑:列表对象永不销毁(仅列表中的对象).Python有一个数组,它可以保存多达80个空列表.当您销毁列表对象时 - python将它放到该数组中,当您创建新列表时 - python从此数组中获取最后的列表:


>>> a = [1,2,3]; a_id = id(a)
>>> b = [1,2,3]; b_id = id(b)
>>> del a; del b
>>> c = [1,2,3]; id(c) == b_id
True
>>> d = [1,2,3]; id(d) == a_id
True
>>>


此功能取决于实现,因此您不应该依赖它.

120> Markus..:

您可以使用类来装饰函数 - 用类实例替换函数:

class countCalls(object):
    """ decorator replaces a function with a "countCalls" instance
    which behaves like the original function, but keeps track of calls

    >>> @countCalls
    ... def doNothing():
    ...     pass
    >>> doNothing()
    >>> doNothing()
    >>> print doNothing.timesCalled
    2
    """
    def __init__ (self, functionToTrack):
        self.functionToTrack = functionToTrack
        self.timesCalled = 0
    def __call__ (self, *args, **kwargs):
        self.timesCalled += 1
        return self.functionToTrack(*args, **kwargs)



121> grayger..:

操纵递归限制

使用sys.getrecursionlimit()和sys.setrecursionlimit()获取或设置最大递归深度.

我们可以限制它以防止由无限递归引起的堆栈溢出.



122> Daniel Heppe..:

切片和可变性

复制列表

>>> x = [1,2,3]
>>> y = x[:]
>>> y.pop()
3
>>> y
[1, 2]
>>> x
[1, 2, 3]

替换列表

>>> x = [1,2,3]
>>> y = x
>>> y[:] = [4,5,6]
>>> x
[4, 5, 6]



123> Martin..:

如果在序列的最后一个元素之后找到,则Python 2.x会忽略逗号:

>>> a_tuple_for_instance = (0,1,2,3,)
>>> another_tuple = (0,1,2,3)
>>> a_tuple_for_instance == another_tuple
True

尾随逗号会将单个带括号的元素视为序列:

>>> a_tuple_with_one_element = (8,)


Python3也忽略了它们.

124> hughdbrown..:

切片作为左值.这个Eratosthenes筛选器生成一个具有素数或0的列表.元素在循环中使用切片赋值为0.

def eras(n):
    last = n + 1
    sieve = [0,0] + list(range(2, last))
    sqn = int(round(n ** 0.5))
    it = (i for i in xrange(2, sqn + 1) if sieve[i])
    for i in it:
        sieve[i*i:last:i] = [0] * (n//i - i + 1)
    return filter(None, sieve)

要工作,必须在左侧的切片上指定相同长度右侧的列表.



125> yoav.aviram..:

舍入整数:Python具有round函数,返回double类型的数字:

 >>> print round(1123.456789, 4)
1123.4568
 >>> print round(1123.456789, 2)
1123.46
 >>> print round(1123.456789, 0)
1123.0

这个功能有一个很棒的魔法属性:

 >>> print round(1123.456789, -1)
1120.0
 >>> print round(1123.456789, -2)
1100.0

如果你需要一个整数作为结果使用int来转换类型:

 >>> print int(round(1123.456789, -2))
1100
 >>> print int(round(8359980, -2))
8360000

谢谢Gregor.



126> 小智..:

列表理解

列表理解

比较更传统(没有列表理解):

foo = []
for x in xrange(10):
  if x % 2 == 0:
     foo.append(x)

至:

foo = [x for x in xrange(10) if x % 2 == 0]


列表推导以什么方式是Python的*隐藏*功能?
问题确实要求"功能的示例和简短描述,而不仅仅是文档的链接".有机会加一个吗?

127> pi...:

懒得初始化字典中的每个字段?没问题:

在Python> 2.3中:

from collections import defaultdict

在Python <= 2.3中:

def defaultdict(type_):
    class Dict(dict):
        def __getitem__(self, key):
            return self.setdefault(key, type_())
    return Dict()

在任何版本中:

d = defaultdict(list)
for stuff in lots_of_stuff:
     d[stuff.name].append(stuff)

更新:

感谢肯·阿诺德.我重新实现了一个更复杂的defaultdict版本.它应该与标准库中的行为完全相同.

def defaultdict(default_factory, *args, **kw):                              

    class defaultdict(dict):

        def __missing__(self, key):
            if default_factory is None:
                raise KeyError(key)
            return self.setdefault(key, default_factory())

        def __getitem__(self, key):
            try:
                return dict.__getitem__(self, key)
            except KeyError:
                return self.__missing__(key)

    return defaultdict(*args, **kw)



128> Armin Ronach..:

如果你在你的类上使用描述符,Python完全绕过__dict__该键,这使它成为存储这些值的好地方:

>>> class User(object):
...  def _get_username(self):
...   return self.__dict__['username']
...  def _set_username(self, value):
...   print 'username set'
...   self.__dict__['username'] = value
...  username = property(_get_username, _set_username)
...  del _get_username, _set_username
... 
>>> u = User()
>>> u.username = "foo"
username set
>>> u.__dict__
{'username': 'foo'}

这有助于保持dir()清洁.



129> tghw..:

__getattr __()

getattr制作泛型类是一种非常好的方法,这在编写API时特别有用.例如,在FogBugz Python API中,getattr用于无缝地将方法调用传递给Web服务:

class FogBugz:
    ...

    def __getattr__(self, name):
        # Let's leave the private stuff to Python
        if name.startswith("__"):
            raise AttributeError("No such attribute '%s'" % name)

        if not self.__handlerCache.has_key(name):
            def handler(**kwargs):
                return self.__makerequest(name, **kwargs)
            self.__handlerCache[name] = handler
        return self.__handlerCache[name]
    ...

当有人打电话时FogBugz.search(q='bug'),他们实际上并没有调用search方法.相反,getattr通过创建一个包装makerequest方法的新函数来处理调用,该函数为Web API提供适当的HTTP请求.任何错误都将由Web服务调度并传递回用户.



130> 小智..:

进口反重力


这个答案已经给出了

131> 小智..:

暴露可变缓冲区

使用Python 缓冲协议,以暴露可变面向字节的缓冲器在Python(2.5/2.6).

(对不起,此处没有代码.需要使用低级C API或现有适配器模块).



132> Amol..:

pythonic成语x = ... if ... else ...远远优于x = ... and ... or ...,这就是为什么:

声明虽然如此

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

相当于

x = y == 1 and 3 or 2

如果你使用这个x = ... and ... or ...成语,有一天你可能会被这种棘手的情况所困扰:

x = 0 if True else 1    # sets x equal to 0

因此不等同于

x = True and 0 or 1   # sets x equal to 1

有关正确执行此操作的更多信息,请参阅Python的隐藏功能.



133> Chinmay Kanc..:

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

这可以被利用来任意地向对象添加属性和功能.这也可以被利用来创建一个快速和肮脏的struct类型.

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

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


除了带有`__slots__`的类

134> Abbafei..:

我不确定它在Python文档中的位置(或者是否),但是对于python 2.x(至少2.5和2.6,我刚试过),print可以使用parenthenses调用该语句.如果您希望能够轻松地将一些Python 2.x代码移植到Python 3.x,这将非常有用.

示例: print('We want Moshiach Now')应该We want Moshiach Now在python 2.5,2.6和3.x中打印工作.

此外,not可以在Python 2和3中使用parenthenses调用运算符: not False 并且 not(False) 都应该返回True.

parenthenses也可以与其他语句和运算符一起使用.

编辑:不是一个好主意把括号放在not运算符(可能还有其他运算符)周围,因为它可以产生令人惊讶的情况,就像这样(这种情况发生是因为括号只是真的围绕着1):

>>> (not 1) == 9
False

>>> not(1) == 9
True

对于某些值(我认为它不是有效的标识符名称),这也可以工作,如下所示: not'val'应该返回False,并且print'We want Moshiach Now'应该返回We want Moshiach Now.(但not552会引发NameError,因为它是一个有效的标识符名称).


ssokolow说的是正确的.在python 2.6中,语言被更新为(更多)与python 3兼容.在python 3+括号中需要调用print.有关更多信息,请参阅此处:http://docs.python.org/whatsnew/2.6.html#pep-3105-print-as-a-function

135> armandino..:

除了之前由haridsv提到的:

>>> foo = bar = baz = 1
>>> foo, bar, baz
(1, 1, 1)

它也可以这样做:

>>> foo, bar, baz = 1, 2, 3
>>> foo, bar, baz
(1, 2, 3)



136> Ken Arnold..:

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) or isinstance(obj, b).)

当你创造一种新的东西时,你需要在它出现的任何地方将它添加到那个元组.(这种结构在重新加载模块或以两个名字导入同一个文件时也会引起问题.它发生的次数比人们喜欢的要多.)但你可以说:

class MyThing:
    processable = True
class MyOtherThing:
    processable = True
if getattr(obj, 'processable', False):
    process(obj)

添加继承并且它变得更好:所有可处理对象的示例都可以继承

class Processable:
    processable = True

但是你不必说服每个人继承你的基类,只是为了设置一个属性.



137> Douglas..:

简单的内置基准测试工具

Python标准库附带了一个非常易于使用的基准测试模块,名为"timeit".您甚至可以从命令行使用它来查看哪种语言结构最快.

例如,

% python -m timeit 'r = range(0, 1000)' 'for i in r: pass'
10000 loops, best of 3: 48.4 usec per loop

% python -m timeit 'r = xrange(0, 1000)' 'for i in r: pass'
10000 loops, best of 3: 37.4 usec per loop



138> mdeous..:

这是2个复活节彩蛋:


一个在python本身:

>>> import __hello__
Hello world...

Werkzeug模块中的另一个,有点复杂,这里是:

通过查看Werkzeug源代码,werkzeug/__init__.py有一行应引起你的注意:

'werkzeug._internal':   ['_easteregg']

如果你有点好奇,这应该让你看看werkzeug/_internal.py,那里,你会找到一个_easteregg()函数,它在参数中使用wsgi应用程序,它还包含一些base64编码数据和2个嵌套函数,似乎如果macgybarchakku在查询字符串中找到了名为的参数,则执行一些特殊操作.

所以,为了揭示这个复活节彩蛋,你似乎需要在_easteregg()函数中包装一个应用程序,让我们走吧:

from werkzeug import Request, Response, run_simple
from werkzeug import _easteregg

@Request.application
def application(request):
    return Response('Hello World!')

run_simple('localhost', 8080, _easteregg(application))

现在,如果你运行应用程序并访问http:// localhost:8080 /?macgybarchakku,你应该看到复活节彩蛋.



139> 小智..:

Dict理解

>>> {i: i**2 for i in range(5)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Python文档

维基百科条目



140> 小智..:

设置理解

>>> {i**2 for i in range(5)}                                                       
set([0, 1, 4, 16, 9])

Python文档

维基百科条目

推荐阅读
雯颜哥_135
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有