jel*_*irt 1419 python hidden-features
Python编程语言有哪些鲜为人知但有用的功能?
Tho*_*ers 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
Run Code Online (Sandbox Code Playgroud)
如果你正在考虑它正在做什么1 < x,True然后进行比较True < 10,然后比较,那么True,那么不,那真的不是发生了什么(参见最后一个例子.)它真正转化为1 < x and x < 10,并且x < 10 and 10 < x * 10 and x*10 < 100,但是打字较少,每个术语仅评估一次.
Bat*_*hyX 512
获取python正则表达式解析树来调试你的正则表达式.
正则表达式是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
Run Code Online (Sandbox Code Playgroud)
一旦理解了语法,就可以发现错误.在那里,我们可以看到我忘了逃避[]进入[/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)
Run Code Online (Sandbox Code Playgroud)
Dav*_*ave 460
枚举
用枚举包装一个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
>>>
Run Code Online (Sandbox Code Playgroud)
参考文献:
fre*_*ace 419
创建生成器对象
如果你写
x=(n for n in foo if bar(n))
Run Code Online (Sandbox Code Playgroud)
你可以拿出发电机并将其分配给x.现在它意味着你可以做到
for n in x:
Run Code Online (Sandbox Code Playgroud)
这样做的好处是您不需要中间存储,如果您需要,则需要中间存储
x = [n for n in foo if bar(n)]
Run Code Online (Sandbox Code Playgroud)
在某些情况下,这可以显着加快速度.
您可以将许多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)
Run Code Online (Sandbox Code Playgroud)
mba*_*768 353
iter()可以采用可调用的参数
例如:
def seek_next_line(f):
for c in iter(lambda: f.read(1),'\n'):
pass
Run Code Online (Sandbox Code Playgroud)
该iter(callable, until_value)函数重复调用callable并生成其结果,直到until_value返回.
Jas*_*ker 339
小心可变的默认参数
>>> def foo(x=[]):
... x.append(1)
... print x
...
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]
Run Code Online (Sandbox Code Playgroud)
相反,你应该使用表示"not given"的sentinel值,并将你想要的mutable替换为默认值:
>>> def foo(x=None):
... if x is None:
... x = []
... x.append(1)
... print x
>>> foo()
[1]
>>> foo()
[1]
Run Code Online (Sandbox Code Playgroud)
Raf*_*ird 317
将值发送到生成器函数.例如具有此功能:
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
Run Code Online (Sandbox Code Playgroud)
您可以:
>>> 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
Run Code Online (Sandbox Code Playgroud)
edu*_*ffy 313
如果您不喜欢使用空格来表示范围,可以通过发出以下命令来使用C风格的{}:
from __future__ import braces
Run Code Online (Sandbox Code Playgroud)
Raf*_*ird 305
切片运算符中的步骤参数.例如:
a = [1,2,3,4,5]
>>> a[::2] # iterate over the whole list in 2-increments
[1,3,5]
Run Code Online (Sandbox Code Playgroud)
特殊情况x[::-1]是'x颠倒'的有用习语.
>>> a[::-1]
[5,4,3,2,1]
Run Code Online (Sandbox Code Playgroud)
Dzi*_*inX 289
装饰
装饰器允许将函数或方法包装在另一个可以添加功能,修改参数或结果等的函数中.您可以在函数定义上方一行编写装饰器,以"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
Run Code Online (Sandbox Code Playgroud)
rle*_*lut 288
for ... else语法(参见http://docs.python.org/ref/for.html)
for i in foo:
if i == 0:
break
else:
print("i was never 0")
Run Code Online (Sandbox Code Playgroud)
除非调用中断,否则"else"块通常在for循环结束时执行.
上面的代码可以模拟如下:
found = False
for i in foo:
if i == 0:
found = True
break
if not found:
print("i was never 0")
Run Code Online (Sandbox Code Playgroud)
Arm*_*her 258
从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]}
Run Code Online (Sandbox Code Playgroud)
在collections调用defaultdict中还有一个dict子类几乎完全相同,但是对于不存在的项调用没有参数的函数:
>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}
Run Code Online (Sandbox Code Playgroud)
我建议将这些dicts转换为常规dicts,然后再将它们传递给不期望这些子类的函数.很多代码使用d[a_key]并捕获KeyErrors来检查是否存在可以向dict添加新项的项.
Luc*_* S. 247
就地价值交换
>>> a = 10
>>> b = 5
>>> a, b
(10, 5)
>>> a, b = b, a
>>> a, b
(5, 10)
Run Code Online (Sandbox Code Playgroud)
赋值的右侧是一个创建新元组的表达式.赋值的左侧立即将该(未引用的)元组解包为名称a和b.
转让后,新的元组是未引用和标记为垃圾回收,和值必然a与b被交换.
请注意,多重赋值实际上只是元组打包和序列解包的组合.
Mvd*_*vdD 235
可读的正则表达式
在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)
Run Code Online (Sandbox Code Playgroud)
命名匹配的示例(来自Regular Expression HOWTO)
>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'
Run Code Online (Sandbox Code Playgroud)
您还可以在不使用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})$"
Run Code Online (Sandbox Code Playgroud)
e-s*_*tis 222
函数参数解包
您可以解压缩列表或使用字典作为函数的参数*和**.
例如:
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)
Run Code Online (Sandbox Code Playgroud)
非常有用的快捷方式,因为列表,元组和dicts被广泛用作容器.
And*_*dré 205
当您在代码文件的顶部使用正确的编码声明时,ROT13是源代码的有效编码:
#!/usr/bin/env python
# -*- coding: rot13 -*-
cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")
Run Code Online (Sandbox Code Playgroud)
Tor*_*rek 183
>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"
Run Code Online (Sandbox Code Playgroud)
这完全一样
>>> class NewType(object):
>>> x = "hello"
>>> n = NewType()
>>> n.x
"hello"
Run Code Online (Sandbox Code Playgroud)
可能不是最有用的东西,但很高兴知道.
编辑:固定新类型的名称,应该NewType与class语句完全相同.
编辑:调整标题以更准确地描述该功能.
Ycr*_*ros 179
上下文管理器和" 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!')
Run Code Online (Sandbox Code Playgroud)
幕后发生的事情是"with"语句调用文件对象上的特殊__enter__和__exit__方法.__exit__如果从with语句体引发任何异常,也会传递异常详细信息,从而允许在那里进行异常处理.
在这种特殊情况下,它对您的作用是它保证在执行超出with套件范围时关闭文件,无论是否正常发生或是否抛出异常.它基本上是一种抽象掉常见异常处理代码的方法.
其他常见用例包括使用线程和数据库事务进行锁定.
Ror*_*ory 168
字典有一个'get()'方法.如果你执行d ['key']并且键不存在,则会出现异常.如果你做了d.get('key'),如果'key'不存在,你就会回来.您可以添加第二个参数来获取该项而不是None,例如:d.get('key',0).
它非常适合添加数字:
sum[value] = sum.get(value, 0) + 1
Nic*_*son 152
它们是一大堆核心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)
Run Code Online (Sandbox Code Playgroud)
你就像内置属性()一样使用它:
class MyClass(object):
@Property
def foo(self):
return "Foo!"
Run Code Online (Sandbox Code Playgroud)
Python中使用描述符来实现属性,绑定方法,静态方法,类方法和插槽等.理解它们可以很容易地理解为什么许多以前看起来像Python'怪癖'的东西都是它们的样子.
Raymond Hettinger有一个很好的教程,比我更好地描述它们.
tgh*_*ghw 142
有条件的分配
x = 3 if (y == 1) else 2
Run Code Online (Sandbox Code Playgroud)
它完全听起来像:"如果y为1,则将3分配给x,否则将2分配给x".请注意,parens不是必需的,但我喜欢它们以便于阅读.如果你有更复杂的东西,你也可以链接它:
x = 3 if (y == 1) else 2 if (y == -1) else 1
Run Code Online (Sandbox Code Playgroud)
虽然在某个时刻,它有点太过分了.
请注意,您可以在任何表达式中使用if ... else.例如:
(func1 if y == 1 else func2)(arg1, arg2)
Run Code Online (Sandbox Code Playgroud)
如果y为1,则调用func1,否则调用func2.在这两种情况下,将使用参数arg1和arg2调用相应的函数.
类似地,以下内容也是有效的:
x = (class1 if y == 1 else class2)(arg1, arg2)
Run Code Online (Sandbox Code Playgroud)
其中class1和class2是两个类.
Pie*_*ert 141
从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()
Run Code Online (Sandbox Code Playgroud)
Pas*_*nen 138
%-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.
Run Code Online (Sandbox Code Playgroud)
由于locals()也是一个字典,你可以简单地将它作为一个字典传递,并从你的局部变量中获得%-substitions.我认为这是不赞成的,但简化了事情..
新风格格式
>>> print("The {foo} is {bar}".format(foo='answer', bar=42))
Run Code Online (Sandbox Code Playgroud)
dgr*_*ant 132
要添加更多python模块(特别是第三方模块),大多数人似乎都使用PYTHONPATH环境变量,或者在他们的site-packages目录中添加符号链接或目录.另一种方法是使用*.pth文件.这是官方python doc的解释:
"[修改python的搜索路径]最方便的方法是将路径配置文件添加到已经在Python路径上的目录中,通常添加到.../site-packages /目录.路径配置文件的扩展名为.pth ,每行必须包含一个将附加到sys.path的路径.(因为新路径附加到sys.path,添加目录中的模块不会覆盖标准模块.这意味着您不能使用此机制用于安装固定版本的标准模块.)"
Con*_*tin 122
例外其他条款:
try:
put_4000000000_volts_through_it(parrot)
except Voom:
print "'E's pining!"
else:
print "This parrot is no more!"
finally:
end_sketch()
Run Code Online (Sandbox Code Playgroud)
使用else子句比向try子句添加其他代码要好,因为它可以避免意外捕获由try ... except语句保护的代码未引发的异常.
请参见http://docs.python.org/tut/node10.html
Tho*_*ers 114
重新提出例外:
# 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)
Run Code Online (Sandbox Code Playgroud)
对错误处理程序中没有参数的'raise'语句告诉Python重新引发原始回溯的异常,允许你说"哦,对不起,对不起,我不是故意要抓住它,对不起,对不起. "
如果你想打印,存储或摆弄原始的追溯,你可以使用sys.exc_info()获取它,并像Python一样使用'traceback'模块进行打印.
cle*_*leg 106
主要信息:)
import this
# btw look at this module's source :)
Run Code Online (Sandbox Code Playgroud)
解密:
Tim Peters的Python之禅
美丽胜过丑陋.
显式优于隐式.
简单比复杂更好.
复杂比复杂更好.
Flat优于嵌套.
稀疏优于密集.
可读性很重要.
特殊情况不足以打破规则.
虽然实用性胜过纯洁.
错误不应该默默地传递.
除非明确沉默.
面对模棱两可,拒绝猜测的诱惑.应该有一个 - 最好只有一个 - 明显的方法来做到这一点.
虽然这种方式起初可能并不明显,除非你是荷兰人.
现在比永远好.正确的现在.
虽然从来没有经常好过
如果实施很难解释,这是一个坏主意.
如果实现很容易解释,那可能是个好主意.
命名空间是一个很棒的主意 - 让我们做更多的事情吧!
mja*_*ard 105
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.<TAB>
class_instance.__class__ class_instance.__module__
class_instance.__doc__ class_instance.function
>>> class_instance.f<TAB>unction()
Run Code Online (Sandbox Code Playgroud)
您还必须设置PYTHONSTARTUP环境变量.
Raf*_*ird 91
嵌套列表推导和生成器表达式:
[(i,j) for i in range(3) for j in range(i) ]
((i,j) for i in range(4) for j in range(i) )
Run Code Online (Sandbox Code Playgroud)
这些可以取代大块的嵌套循环代码.
Kiv*_*Kiv 91
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}
Run Code Online (Sandbox Code Playgroud)
标准库参考的更多细节:设置类型
Abg*_*gan 85
负圆
该round()函数将浮点数舍入为十进制数的给定精度,但精度可以为负数:
>>> str(round(1234.5678, -2))
'1200.0'
>>> str(round(1234.5678, 2))
'1234.57'
Run Code Online (Sandbox Code Playgroud)
注意: round()总是返回一个浮点数,str()在上面的例子中使用,因为浮点数学是不精确的,而在2.x下,第二个例子可以打印为1234.5700000000001.另见decimal模块.
jps*_*ons 81
乘以布尔值
我在Web开发中经常做的一件事是可选地打印HTML参数.我们都看到过其他语言的代码:
class='<% isSelected ? "selected" : "" %>'
Run Code Online (Sandbox Code Playgroud)
在Python中,您可以乘以布尔值,它完全符合您的期望:
class='<% "selected" * isSelected %>'
Run Code Online (Sandbox Code Playgroud)
这是因为乘法将布尔值强制转换为整数(0表示False,1表示True),而在python中,字符串乘以int会重复字符串N次.
Arm*_*her 74
Python的高级切片操作有一个鲜为人知的语法元素,省略号:
>>> class C(object):
... def __getitem__(self, item):
... return item
...
>>> C()[1:2, ..., 3]
(slice(1, 2, None), Ellipsis, 3)
Run Code Online (Sandbox Code Playgroud)
不幸的是,它几乎没有用,因为只有在涉及元组的情况下才支持省略号.
Sco*_*ood 72
事实上你可以在每次匹配正则表达式时调用函数都非常方便.在这里,我有一个样本,用"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?'
Run Code Online (Sandbox Code Playgroud)
Adr*_*son 70
元组在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]
Run Code Online (Sandbox Code Playgroud)
但是一个鲜为人知且功能更强大的功能允许您在列表中间包含未知数量的元素:
>>> first,*rest,last = (1,2,3,4,5,6,7,8)
>>> first
1
>>> rest
[2, 3, 4, 5, 6, 7]
>>> last
8
Run Code Online (Sandbox Code Playgroud)
sa1*_*125 67
多行字符串
一种方法是使用反斜杠:
>>> sql = "select * from some_table \
where id > 10"
>>> print sql
select * from some_table where id > 10
Run Code Online (Sandbox Code Playgroud)
另一种是使用三重报价:
>>> sql = """select * from some_table
where id > 10"""
>>> print sql
select * from some_table where id > 10
Run Code Online (Sandbox Code Playgroud)
问题在于它们没有缩进(在代码中看起来很差).如果您尝试缩进,它只会打印您放置的空白区域.
我最近发现的第三个解决方案是将你的字符串分成几行并用括号括起来:
>>> 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
Run Code Online (Sandbox Code Playgroud)
注意行之间没有逗号(这不是元组),你必须考虑字符串需要的任何尾随/前导空格.顺便说一句,所有这些都与占位符一起工作(例如"my name is %s" % name).
Way*_*ner 63
根据许多人的要求,这个答案已经转移到了问题本身.
Tzu*_*hay 59
>>> (a for a in xrange(10000)) <generator object at 0x81a8fcc> >>> b = 'blah' >>> _ <generator object at 0x81a8fcc>
>>> import webbrowser
>>> webbrowser.open_new_tab('http://www.stackoverflow.com')
python -m SimpleHTTPServer 8000
>>> import atexit
Tam*_*más 56
有一个鲜为人知的内置pow()函数的第三个参数,它允许你比简单地做更有效地计算x y modulo z (x ** y) % z:
>>> x, y, z = 1234567890, 2345678901, 17
>>> pow(x, y, z) # almost instantaneous
6
Run Code Online (Sandbox Code Playgroud)
相比之下,(x ** y) % z在我的机器上一分钟没有给出相同值的结果.
小智 52
您可以轻松地使用zip转置数组.
a = [(1,2), (3,4), (5,6)]
zip(*a)
# [(1, 3, 5), (2, 4, 6)]
Run Code Online (Sandbox Code Playgroud)
Tam*_*más 52
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")]
Run Code Online (Sandbox Code Playgroud)
我发现它非常有用的一个地方就是我在列举对称矩阵的条目时.由于矩阵是对称的,我可以通过迭代上三角形来节省时间,但在这种情况下,我必须enumerate在内部for循环中使用不同的起始索引来正确跟踪行和列索引:
for ri, row in enumerate(matrix):
for ci, column in enumerate(matrix[ri:], ri):
# ci now refers to the proper column index
Run Code Online (Sandbox Code Playgroud)
奇怪的是,这种行为enumerate没有记录在案help(enumerate),仅在在线文档中.
jfs*_*jfs 50
您可以使用属性使您的类接口更严格.
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__)
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
要了解有关属性如何工作的更多信息,请参阅描述符.
lac*_*ker 48
很多人不了解"dir"功能.这是一个很好的方法来确定一个对象可以从解释器做什么.例如,如果要查看所有字符串方法的列表:
>>> dir("foo")
['__add__', '__class__', '__contains__', (snipped a bunch), 'title',
'translate', 'upper', 'zfill']
Run Code Online (Sandbox Code Playgroud)
然后,如果您想了解有关特定方法的更多信息,可以在其上调用"帮助".
>>> help("foo".upper)
Help on built-in function upper:
upper(...)
S.upper() -> string
Return a copy of the string S converted to uppercase.
Run Code Online (Sandbox Code Playgroud)
mon*_*kut 47
可能容易被忽视的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
Run Code Online (Sandbox Code Playgroud)
当然,要获取列表中的唯一身份数量:
>>> len(set([1,2,1,1,2,3,4]))
4
Run Code Online (Sandbox Code Playgroud)
您还可以使用set()查找列表是否是另一个列表的子集.issubset():
>>> set([1,2,3,4]).issubset([0,1,2,3,4,5])
True
Run Code Online (Sandbox Code Playgroud)
从Python 2.7和3.0开始,您可以使用花括号来创建一个集合:
myset = {1,2,3,4}
Run Code Online (Sandbox Code Playgroud)
以及设定理解:
{x for x in stuff}
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请访问:http: //docs.python.org/library/stdtypes.html#set
spi*_*piv 46
内置base64,zlib和rot13编解码器
字符串也有encode和decode方法.通常这用于转换str,unicode反之亦然,例如u = s.encode('utf8').但是还有其他一些方便的内置编解码器.使用zlib(和bz2)进行压缩和解压缩是没有明确导入的:
>>> s = 'a' * 100
>>> s.encode('zlib')
'x\x9cKL\xa4=\x00\x00zG%\xe5'
Run Code Online (Sandbox Code Playgroud)
同样,您可以编码和解码base64:
>>> 'Hello world'.encode('base64')
'SGVsbG8gd29ybGQ=\n'
>>> 'SGVsbG8gd29ybGQ=\n'.decode('base64')
'Hello world'
Run Code Online (Sandbox Code Playgroud)
当然,你可以腐烂13:
>>> 'Secret message'.encode('rot13')
'Frperg zrffntr'
Run Code Online (Sandbox Code Playgroud)
Jam*_*ady 43
口译员内的口译员
标准库的代码模块允许您在程序中包含自己的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'
Run Code Online (Sandbox Code Playgroud)
这对于您希望接受来自用户的脚本输入或实时查询VM状态的情况非常有用.
TurboGears通过使用WebConsole来实现这一效果,您可以从中查询实时Web应用程序的状态.
小智 40
>>> 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]
Run Code Online (Sandbox Code Playgroud)
不是真正隐藏的功能,但是部分对于对功能的后期评估非常有用.
您可以根据需要在初始调用中绑定尽可能多的参数,并稍后使用任何剩余参数调用它(在此示例中,我将开始/结束参数绑定到范围,但是第二次调用它步骤arg)
请参阅文档.
utk*_*tas 36
在调试复杂的数据结构时,pprint模块非常方便.
引用文档..
>>> import pprint
>>> stuff = sys.path[:]
>>> stuff.insert(0, stuff)
>>> pprint.pprint(stuff)
[<Recursion on list with id=869440>,
'',
'/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']
Run Code Online (Sandbox Code Playgroud)
Con*_*tin 34
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"
Run Code Online (Sandbox Code Playgroud)
小智 32
dict的构造函数接受关键字参数:
>>> dict(foo=1, bar=2)
{'foo': 1, 'bar': 2}
Run Code Online (Sandbox Code Playgroud)
Rus*_*vak 29
序列乘法和反射操作数
>>> 'xyz' * 3
'xyzxyzxyz'
>>> [1, 2] * 3
[1, 2, 1, 2, 1, 2]
>>> (1, 2) * 3
(1, 2, 1, 2, 1, 2)
Run Code Online (Sandbox Code Playgroud)
我们使用反射(交换)操作数获得相同的结果
>>> 3 * 'xyz'
'xyzxyzxyz'
Run Code Online (Sandbox Code Playgroud)
它的工作原理如下:
>>> s = 'xyz'
>>> num = 3
Run Code Online (Sandbox Code Playgroud)
要评估表达式s*num解释器调用s .___ mul ___(num)
>>> s * num
'xyzxyzxyz'
>>> s.__mul__(num)
'xyzxyzxyz'
Run Code Online (Sandbox Code Playgroud)
要评估表达式num*s解释器调用num .___ mul ___(s)
>>> num * s
'xyzxyzxyz'
>>> num.__mul__(s)
NotImplemented
Run Code Online (Sandbox Code Playgroud)
如果调用返回NotImplemented,则解释器调用反射操作s .___ rmul ___(num)如果操作数具有不同类型
>>> s.__rmul__(num)
'xyzxyzxyz'
Run Code Online (Sandbox Code Playgroud)
请参阅http://docs.python.org/reference/datamodel.html#object.RMUL
Tor*_*rek 28
交错if和for列表理解
>>> [(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)]
Run Code Online (Sandbox Code Playgroud)
在我学习Haskell之前,我从未意识到这一点.
ian*_*anb 27
元组拆包:
>>> (a, (b, c), d) = [(1, 2), (3, 4), (5, 6)]
>>> a
(1, 2)
>>> b
3
>>> c, d
(4, (5, 6))
Run Code Online (Sandbox Code Playgroud)
更晦涩的是,您可以在函数参数中执行此操作(在Python 2.x中; Python 3.x将不再允许此操作):
>>> def addpoints((x1, y1), (x2, y2)):
... return (x1+x2, y1+y2)
>>> addpoints((5, 0), (3, 5))
(8, 5)
Run Code Online (Sandbox Code Playgroud)
dav*_*avr 26
Python解释器
>>>
Run Code Online (Sandbox Code Playgroud)
也许不是鲜为人知,但肯定是我最喜欢的Python功能之一.
小智 25
Python排序函数正确排序元组(即使用熟悉的词典顺序):
a = [(2, "b"), (1, "a"), (2, "a"), (3, "c")]
print sorted(a)
#[(1, 'a'), (2, 'a'), (2, 'b'), (3, 'c')]
Run Code Online (Sandbox Code Playgroud)
如果您想在年龄之后对人员列表进行排序然后命名,则非常有用.
Jak*_*ake 25
您可以引用列表推导,因为它是由符号'_ [1]'构建的.例如,以下函数unique-ifies元素列表,而不通过引用其列表推导来更改其顺序.
def unique(my_list):
return [x for x in my_list if x not in locals()['_[1]']]
Run Code Online (Sandbox Code Playgroud)
Noc*_*wer 25
解压缩语法已在最新版本中升级,如示例中所示.
>>> 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)
Run Code Online (Sandbox Code Playgroud)
Chm*_*nah 25
简单:
>>> 'str' in 'string'
True
>>> 'no' in 'yes'
False
>>>
Run Code Online (Sandbox Code Playgroud)
是我喜欢Python的东西,我已经看到很多不那么像这样的pythonic成语:
if 'yes'.find("no") == -1:
pass
Run Code Online (Sandbox Code Playgroud)
Tom*_*Tom 24
我个人喜欢3种不同的报价
str = "I'm a string 'but still I can use quotes' inside myself!"
str = """ For some messy multi line strings.
Such as
<html>
<head> ... </head>"""
Run Code Online (Sandbox Code Playgroud)
同样很酷:不必逃避正则表达式,使用原始字符串避免可怕的反斜杠沙拉:
str2 = r"\n"
print str2
>> \n
Run Code Online (Sandbox Code Playgroud)
e-s*_*tis 22
隐式连接:
>>> print "Hello " "World"
Hello World
Run Code Online (Sandbox Code Playgroud)
想要在脚本中的多行上创建长文本时很有用:
hello = "Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello " \
"Word"
Run Code Online (Sandbox Code Playgroud)
要么
hello = ("Greaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello "
"Word")
Run Code Online (Sandbox Code Playgroud)
Gia*_*olà 22
使用交互式shell时,"_"包含最后打印项的值:
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> _
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
Run Code Online (Sandbox Code Playgroud)
Rem*_*ndt 22
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("""\
<?xml version="1.0" encoding="utf-8"?>
<root_node>
<my_node>my_content</my_node>
</root_node>
""")
self.assertEqual(expected_value, returned_xml)
Run Code Online (Sandbox Code Playgroud)
Dav*_*d Z 22
Lambda函数通常用于将一个值快速转换为另一个值,但它们也可用于在函数中包装值:
>>> f = lambda: 'foo'
>>> f()
'foo'
Run Code Online (Sandbox Code Playgroud)
他们也可以接受通常*args和**kwargs语法:
>>> g = lambda *args, **kwargs: args[0], kwargs['thing']
>>> g(1, 2, 3, thing='stuff')
(1, 'stuff')
Run Code Online (Sandbox Code Playgroud)
小智 21
使用关键字参数作为分配
有时,人们希望根据一个或多个参数构建一系列函数.但是,这可能很容易导致闭包所有引用相同的对象和值:
funcs = []
for k in range(10):
funcs.append( lambda: k)
>>> funcs[0]()
9
>>> funcs[7]()
9
Run Code Online (Sandbox Code Playgroud)
通过将lambda表达式转换为仅依赖于其参数的函数,可以避免此行为.关键字参数存储绑定到它的当前值.函数调用不必更改:
funcs = []
for k in range(10):
funcs.append( lambda k = k: k)
>>> funcs[0]()
0
>>> funcs[7]()
7
Run Code Online (Sandbox Code Playgroud)
jps*_*ons 20
Mod可以正数使用负数
-1%5是4,因为它应该是-1,而不是像其他语言一样的JavaScript.这使得"环绕式窗口"在Python中变得更干净,你只需这样做:
index = (index + increment) % WINDOW_SIZE
Run Code Online (Sandbox Code Playgroud)
Jer*_*ell 19
一流的功能
它并不是一个隐藏的功能,但功能是一流的对象这一事实非常棒.你可以像任何其他变量一样传递它们.
>>> 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".'
Run Code Online (Sandbox Code Playgroud)
Ale*_*kov 19
三元运算符
>>> 'ham' if True else 'spam'
'ham'
>>> 'ham' if False else 'spam'
'spam'
Run Code Online (Sandbox Code Playgroud)
这是在2.5中添加的,在此之前您可以使用:
>>> True and 'ham' or 'spam'
'ham'
>>> False and 'ham' or 'spam'
'spam'
Run Code Online (Sandbox Code Playgroud)
但是,如果您要使用的值将被视为false,则存在差异:
>>> [] if True else 'spam'
[]
>>> True and [] or 'spam'
'spam'
Run Code Online (Sandbox Code Playgroud)
Tor*_*rek 19
分配和删除切片:
>>> 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]
Run Code Online (Sandbox Code Playgroud)
注意:分配给扩展切片(s[start:stop:step])时,指定的可迭代必须与切片具有相同的长度.
Mar*_*kus 19
不是很隐蔽,但功能有属性:
def doNothing():
pass
doNothing.monkeys = 4
print doNothing.monkeys
4
Run Code Online (Sandbox Code Playgroud)
evi*_*pie 19
很多Python函数都接受元组,它似乎也不像.例如,您想测试您的变量是否为数字,您可以这样做:
if isinstance (number, float) or isinstance (number, int):
print "yaay"
Run Code Online (Sandbox Code Playgroud)
但是,如果你通过我们元组,这看起来更清洁:
if isinstance (number, (float, int)):
print "yaay"
Run Code Online (Sandbox Code Playgroud)
Evg*_*eny 19
在字典中无限递归的好处理:
>>> a = {}
>>> b = {}
>>> a['b'] = b
>>> b['a'] = a
>>> print a
{'b': {'a': {...}}}
Run Code Online (Sandbox Code Playgroud)
小智 18
使用负步骤反转可迭代
>>> 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]
Run Code Online (Sandbox Code Playgroud)
Nou*_*him 18
不是"隐藏"但非常有用且不常用
像这样快速创建字符串连接功能
comma_join = ",".join
semi_join = ";".join
print comma_join(["foo","bar","baz"])
'foo,bar,baz
Run Code Online (Sandbox Code Playgroud)
和
能够比引号,逗号混乱更优雅地创建字符串列表.
l = ["item1", "item2", "item3"]
Run Code Online (Sandbox Code Playgroud)
取而代之
l = "item1 item2 item3".split()
Run Code Online (Sandbox Code Playgroud)
Kim*_*ais 18
可以说,这本身并不是一个编程功能,但是非常有用,我会发布它.
$ python -m http.server
Run Code Online (Sandbox Code Playgroud)
......其次是$ wget http://<ipnumber>:8000/filename其他地方.
如果您仍在运行较旧的(2.x)版本的Python:
$ python -m SimpleHTTPServer
Run Code Online (Sandbox Code Playgroud)
您也可以指定一个端口python -m http.server 80(例如,如果您在服务器端有根,则可以省略URL中的端口)
Dav*_*d Z 17
对迭代器的多个引用
您可以使用列表乘法创建对同一迭代器的多个引用:
>>> 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
Run Code Online (Sandbox Code Playgroud)
这可以在本实施例中被用来组可迭代成块,例如,作为来自itertools文档
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
Run Code Online (Sandbox Code Playgroud)
Pio*_*uda 17
从python 3.1(2.7)支持字典和集合理解:
{ a:a for a in range(10) }
{ a for a in range(10) }
Run Code Online (Sandbox Code Playgroud)
u0b*_*6ae 15
Python 可以理解任何类型的unicode数字,而不仅仅是ASCII类:
>>> s = u'?????'
>>> s
u'\uff11\uff10\uff15\uff18\uff15'
>>> print s
?????
>>> int(s)
10585
>>> float(s)
10585.0
Run Code Online (Sandbox Code Playgroud)
Arm*_*her 14
__slots__是一种节省内存的好方法,但很难得到对象值的字典.想象一下以下对象:
class Point(object):
__slots__ = ('x', 'y')
Run Code Online (Sandbox Code Playgroud)
现在该对象显然有两个属性.现在我们可以创建它的实例并以这种方式构建它的字典:
>>> p = Point()
>>> p.x = 3
>>> p.y = 5
>>> dict((k, getattr(p, k)) for k in p.__slots__)
{'y': 5, 'x': 3}
Run Code Online (Sandbox Code Playgroud)
但是如果点被子类化并且添加了新的插槽,则这将不起作用.但是Python会自动实现__reduce_ex__以帮助copy模块.这可能会被滥用来获得价值观:
>>> p.__reduce_ex__(2)[2][1]
{'y': 5, 'x': 3}
Run Code Online (Sandbox Code Playgroud)
小智 14
itertools
这个模块经常被忽视.以下示例用于itertools.chain()
展平列表:
>>> from itertools import *
>>> l = [[1, 2], [3, 4]]
>>> list(chain(*l))
[1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)
有关更多应用程序,请参阅http://docs.python.org/library/itertools.html#recipes.
Tho*_*ers 14
您可以直接操作模块缓存,使模块可用或不可用:
>>> import sys
>>> import ham
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
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 "<stdin>", line 1, in <module>
ImportError: No module named ham
Run Code Online (Sandbox Code Playgroud)
这适用于可用的模块,在某种程度上适用于已导入的模块:
>>> import os
# Stop future imports of 'os'.
>>> sys.modules['os'] = None
>>> import os
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named os
# Our old imported module is still available.
>>> os
<module 'os' from '/usr/lib/python2.5/os.pyc'>
Run Code Online (Sandbox Code Playgroud)
如最后一行所示,更改sys.modules只影响将来的import语句,而不是过去的语句,所以如果你想影响其他模块,在给他们机会尝试导入模块之前进行这些更改是很重要的 - 所以在你之前通常导入它们.None是一个特殊的值sys.modules,用于负缓存(表示第一次找不到模块,所以再看一遍没有意义.)任何其他值都将是import操作的结果- 即使它不是模块对象.您可以使用它来替换具有与您想要的行为完全相同的对象的模块.sys.modules完全删除条目会导致下一个条目import正常搜索模块,即使它之前已经导入过.
Joh*_*ook 14
您可以通过查看其__ module__属性来询问任何对象来自哪个模块.例如,如果您在命令行进行实验并导入了很多东西,这很有用.
同样,您可以通过查看其__ file__属性来询问模块的来源.这在调试路径问题时很有用.
dan*_*iel 13
一些内置的收藏夹,map(),reduce()和filter().一切都非常快速和强大.
小智 13
猜整数基数
>>> 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
Run Code Online (Sandbox Code Playgroud)
Dan*_*ski 12
您可以从一组长度为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}
Run Code Online (Sandbox Code Playgroud)
Den*_*ach 12
有时,扩展(修改)子类中描述符"返回"的值是有用的.它可以很容易地完成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)
Run Code Online (Sandbox Code Playgroud)
将其存储test.py并运行python -i test.py(另一个隐藏功能:-i选项执行脚本并允许您以交互模式继续):
>>> B().prop
{'a': 1, 'b': 2}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ett 11
蟒蛇的轻微错误.将字符串列表连接在一起的正常快速方法是,
''.join(list_of_strings)
Run Code Online (Sandbox Code Playgroud)
Chi*_*chi 11
创建枚举
在Python中,您可以这样做以快速创建枚举:
>>> FOO, BAR, BAZ = range(3)
>>> FOO
0
Run Code Online (Sandbox Code Playgroud)
但"枚举"不必具有整数值.你甚至可以这样做:
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
Run Code Online (Sandbox Code Playgroud)
asm*_*rer 11
对象数据模型
您可以使用您自己的类的语言覆盖任何运算符.有关完整列表,请参阅此页面.一些例子:
您可以覆盖任何运算符(* + - / // % ^ == < > <= >= .等).所有这一切都是通过重写完成__mul__,__add__等你的对象.你甚至可以忽略的东西喜欢__rmul__单独处理your_object*something_else和something_else*your_object. .是属性access(a.b),可以b通过使用来覆盖任何任意处理__getattr__.此处还包括a(…)使用__call__.
你可以创建自己的切片语法(a[stuff]),这是非常复杂的,从列表(numpy的有这在他们的阵列电源的一个很好的例子),用于使用任意组合的标准语法完全不同,,:和…你喜欢,使用Slice对象.
特别处理语言中的许多关键字会发生什么.包括的是del,in,import,和not.
处理当您的对象调用许多内置函数时会发生什么.标准的__int__,__str__等去这里,但这么做__len__,__reversed__,__abs__,和三个参数__pow__(模块化幂).
csl*_*csl 10
"解包"到功能参数
def foo(a, b, c):
print a, b, c
bar = (3, 14, 15)
foo(*bar)
Run Code Online (Sandbox Code Playgroud)
执行打印时:
3 14 15
Run Code Online (Sandbox Code Playgroud)
Chr*_*ard 10
该reversed()内置.在许多情况下,它使迭代更加清晰.
快速举例:
for i in reversed([1, 2, 3]):
print(i)
Run Code Online (Sandbox Code Playgroud)
生产:
3
2
1
Run Code Online (Sandbox Code Playgroud)
但是,reversed()也适用于任意迭代器,例如文件中的行或生成器表达式.
小智 10
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!
Run Code Online (Sandbox Code Playgroud)
Foo*_*Bah 10
在运行时更改功能标签:
>>> 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
...
Run Code Online (Sandbox Code Playgroud)
Rom*_*huk 10
string-escape和unicode-escape编码
假设你有一个来自外部源的字符串,包含\n,\t等等.如何将它们转换为换行符或制表符?只需使用string-escape编码解码字符串!
>>> print s
Hello\nStack\toverflow
>>> print s.decode('string-escape')
Hello
Stack overflow
Run Code Online (Sandbox Code Playgroud)
另一个问题.你有正常的字符串与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')
??????, ????!
Run Code Online (Sandbox Code Playgroud)
有人在博客上发表了关于Python没有解压缩功能的解决方案.unzip是直接计算的,因为:
>>> t1 = (0,1,2,3)
>>> t2 = (7,6,5,4)
>>> [t1,t2] == zip(*zip(t1,t2))
True
Run Code Online (Sandbox Code Playgroud)
但是在反思时,我宁愿有一个明确的解压缩().
创建具有相关数据的两个序列的字典
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}
Run Code Online (Sandbox Code Playgroud)
最高机密属性
>>> 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 "<stdin>", 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'
Run Code Online (Sandbox Code Playgroud)
>>> 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))
>>>
Run Code Online (Sandbox Code Playgroud)
还有一些回应评论的实验:
>>> 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)
Run Code Online (Sandbox Code Playgroud)
所以,namedtuple是一个有趣的子类型tuple.
动态添加属性
如果您考虑通过调用它们来为类添加一些属性,这可能会很有用.这可以通过覆盖__getattribute__使用点操作数时调用的成员函数来完成.所以,让我们看一个虚拟类,例如:
class Dummy(object):
def __getattribute__(self, name):
f = lambda: 'Hello with %s'%name
return f
Run Code Online (Sandbox Code Playgroud)
当您实例化Dummy对象并执行方法调用时,您将获得以下内容:
>>> d = Dummy()
>>> d.b()
'Hello with b'
Run Code Online (Sandbox Code Playgroud)
最后,您甚至可以将属性设置为您的类,以便可以动态定义它.如果您使用Python Web框架并希望通过解析属性的名称来执行查询,这可能很有用.
我有一个关于github 的要点,这个简单的代码和它在Ruby上由朋友制作.
照顾自己!
list用sum().该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]
Run Code Online (Sandbox Code Playgroud)
这是Alex Martelli的杀手.Borg共享状态的所有实例.这消除了使用单例模式的需要(实例在共享状态时无关紧要)并且相当优雅(但新类更复杂).
foo可以在任何实例中重新分配值,并且所有值都将更新,您甚至可以重新分配整个dict.博格是一个完美的名字,在这里阅读更多.
class Borg:
__shared_state = {'foo': 'bar'}
def __init__(self):
self.__dict__ = self.__shared_state
# rest of your class here
Run Code Online (Sandbox Code Playgroud)
这非常适合共享eventlet.GreenPool来控制并发性.
pdb - Python调试器
作为程序员,严肃的程序开发需要的第一件事就是调试器.Python有一个内置的,可以作为一个名为pdb的模块使用(对于"Python DeBugger",当然!).
http://docs.python.org/library/pdb.html
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)
Run Code Online (Sandbox Code Playgroud)
在多线程python程序的开头执行此操作,您可以通过发送SIGQUIT随时访问当前线程状态.您也可以选择signal.SIGUSR1或signal.SIGUSR2.
... dict.get()具有默认值 None,从而避免了KeyErrors:
In [1]: test = { 1 : 'a' }
In [2]: test[2]
---------------------------------------------------------------------------
<type 'exceptions.KeyError'> Traceback (most recent call last)
<ipython console> in <module>()
<type 'exceptions.KeyError'>: 2
In [3]: test.get( 2 )
In [4]: test.get( 1 )
Out[4]: 'a'
In [5]: test.get( 2 ) == None
Out[5]: True
Run Code Online (Sandbox Code Playgroud)
甚至在现场指定这个:
In [6]: test.get( 2, 'Some' ) == 'Some'
Out[6]: True
Run Code Online (Sandbox Code Playgroud)
你可以使用setdefault()来设置一个值,如果它不存在则返回:
>>> a = {}
>>> b = a.setdefault('foo', 'bar')
>>> a
{'foo': 'bar'}
>>> b
'bar
Run Code Online (Sandbox Code Playgroud)
重新加载模块可实现"实时编码"风格.但是类实例不会更新.这就是原因,以及如何解决它.记住,一切,是的,一切都是一个对象.
>>> from a_package import a_module
>>> cls = a_module.SomeClass
>>> obj = cls()
>>> obj.method()
(old method output)
Run Code Online (Sandbox Code Playgroud)
现在,您更改了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)
Run Code Online (Sandbox Code Playgroud)
这是更新它的一种方法(但考虑用剪刀运行):
>>> 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)
Run Code Online (Sandbox Code Playgroud)
这是"用剪刀运行",因为对象的内部状态可能与新类所期望的不同.这适用于非常简单的情况,但除此之外,pickle是你的朋友.但是,了解其原因仍然有用.
原始字符串中的反斜杠仍然可以转义引号.看到这个:
>>> print repr(r"aaa\"bbb")
'aaa\\"bbb'
Run Code Online (Sandbox Code Playgroud)
请注意,反斜杠和双引号都出现在最终字符串中.
因此,您无法使用反斜杠结束原始字符串:
>>> print repr(r"C:\")
SyntaxError: EOL while scanning string literal
>>> print repr(r"C:\"")
'C:\\"'
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为实现了原始字符串以帮助编写正则表达式,而不是编写Windows路径.在Gotcha中阅读关于此的长篇讨论- Windows文件名中的反斜杠.
操作符可以作为函数调用:
from operator import add
print reduce(add, [1,2,3,4,5,6])
Run Code Online (Sandbox Code Playgroud)
列表中的无限递归
>>> 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
Run Code Online (Sandbox Code Playgroud)
内置方法或函数不实现描述符协议,这使得无法执行以下操作:
>>> class C(object):
... id = id
...
>>> C().id()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: id() takes exactly one argument (0 given)
Run Code Online (Sandbox Code Playgroud)
但是,您可以创建一个小的绑定描述符,使其成为可能:
>>> 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
Run Code Online (Sandbox Code Playgroud)
嵌套函数参数重新绑定
def create_printers(n):
for i in xrange(n):
def printer(i=i): # Doesn't work without the i=i
print i
yield printer
Run Code Online (Sandbox Code Playgroud)
您可以使用元类覆盖类的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 "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'a_method'
>>> cls.b_method()
B
>>> type(cls).__bases__
(<class '__main__.A'>,)
>>> type(cls).__mro__
(<class '__main__.C'>, <class '__main__.B'>, <class 'object'>)
Run Code Online (Sandbox Code Playgroud)
这可能是有充分理由隐藏的.:)
小整数(-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
>>>
您可以使用类来装饰函数 - 用类实例替换函数:
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)
Run Code Online (Sandbox Code Playgroud)
操纵递归限制
使用sys.getrecursionlimit()和sys.setrecursionlimit()获取或设置最大递归深度.
我们可以限制它以防止由无限递归引起的堆栈溢出.
切片和可变性
复制列表
>>> x = [1,2,3]
>>> y = x[:]
>>> y.pop()
3
>>> y
[1, 2]
>>> x
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
替换列表
>>> x = [1,2,3]
>>> y = x
>>> y[:] = [4,5,6]
>>> x
[4, 5, 6]
Run Code Online (Sandbox Code Playgroud)
如果在序列的最后一个元素之后找到,则Python 2.x会忽略逗号:
>>> a_tuple_for_instance = (0,1,2,3,)
>>> another_tuple = (0,1,2,3)
>>> a_tuple_for_instance == another_tuple
True
Run Code Online (Sandbox Code Playgroud)
尾随逗号会将单个带括号的元素视为序列:
>>> a_tuple_with_one_element = (8,)
Run Code Online (Sandbox Code Playgroud)
切片作为左值.这个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)
Run Code Online (Sandbox Code Playgroud)
要工作,必须在左侧的切片上指定相同长度右侧的列表.
舍入整数:Python具有round函数,返回double类型的数字:
>>> print round(1123.456789, 4)
1123.4568
>>> print round(1123.456789, 2)
1123.46
>>> print round(1123.456789, 0)
1123.0
Run Code Online (Sandbox Code Playgroud)
这个功能有一个很棒的魔法属性:
>>> print round(1123.456789, -1)
1120.0
>>> print round(1123.456789, -2)
1100.0
Run Code Online (Sandbox Code Playgroud)
如果你需要一个整数作为结果使用int来转换类型:
>>> print int(round(1123.456789, -2))
1100
>>> print int(round(8359980, -2))
8360000
Run Code Online (Sandbox Code Playgroud)
谢谢Gregor.
小智 5
列表理解
比较更传统(没有列表理解):
foo = []
for x in xrange(10):
if x % 2 == 0:
foo.append(x)
Run Code Online (Sandbox Code Playgroud)
至:
foo = [x for x in xrange(10) if x % 2 == 0]
Run Code Online (Sandbox Code Playgroud)
懒得初始化字典中的每个字段?没问题:
在Python> 2.3中:
from collections import defaultdict
Run Code Online (Sandbox Code Playgroud)
在Python <= 2.3中:
def defaultdict(type_):
class Dict(dict):
def __getitem__(self, key):
return self.setdefault(key, type_())
return Dict()
Run Code Online (Sandbox Code Playgroud)
在任何版本中:
d = defaultdict(list)
for stuff in lots_of_stuff:
d[stuff.name].append(stuff)
Run Code Online (Sandbox Code Playgroud)
更新:
感谢肯·阿诺德.我重新实现了一个更复杂的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)
Run Code Online (Sandbox Code Playgroud)
如果你在你的类上使用描述符,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'}
Run Code Online (Sandbox Code Playgroud)
这有助于保持dir()清洁.
__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]
...
Run Code Online (Sandbox Code Playgroud)
当有人打电话时FogBugz.search(q='bug'),他们实际上并没有调用search方法.相反,getattr通过创建一个包装makerequest方法的新函数来处理调用,该函数为Web API提供适当的HTTP请求.任何错误都将由Web服务调度并传递回用户.
pythonic成语x = ... if ... else ...远远优于x = ... and ... or ...,这就是为什么:
声明虽然如此
x = 3 if (y == 1) else 2
Run Code Online (Sandbox Code Playgroud)
相当于
x = y == 1 and 3 or 2
Run Code Online (Sandbox Code Playgroud)
如果你使用这个x = ... and ... or ...成语,有一天你可能会被这种棘手的情况所困扰:
x = 0 if True else 1 # sets x equal to 0
Run Code Online (Sandbox Code Playgroud)
因此不等同于
x = True and 0 or 1 # sets x equal to 1
Run Code Online (Sandbox Code Playgroud)
有关正确执行此操作的更多信息,请参阅Python的隐藏功能.
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
Run Code Online (Sandbox Code Playgroud)
这可以被利用来任意地向对象添加属性和功能.这也可以被利用来创建一个快速和肮脏的struct类型.
class struct(object):
def __init__(**kwargs):
self.__dict__.update(kwargs)
s = struct(foo=10, bar=11, baz="i'm a string!')
Run Code Online (Sandbox Code Playgroud)
我不确定它在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
Run Code Online (Sandbox Code Playgroud)
对于某些值(我认为它不是有效的标识符名称),这也可以工作,如下所示:
not'val'应该返回False,并且print'We want Moshiach Now'应该返回We want Moshiach Now.(但not552会引发NameError,因为它是一个有效的标识符名称).
除了之前由haridsv提到的:
>>> foo = bar = baz = 1
>>> foo, bar, baz
(1, 1, 1)
Run Code Online (Sandbox Code Playgroud)
它也可以这样做:
>>> foo, bar, baz = 1, 2, 3
>>> foo, bar, baz
(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)
getattr 采用第三个参数getattr(obj, attribute_name, default) 就好像:
try:
return obj.attribute
except AttributeError:
return default
Run Code Online (Sandbox Code Playgroud)
除了attribute_name可以是任何字符串.
这对于鸭子打字非常有用.也许你有类似的东西:
class MyThing:
pass
class MyOtherThing:
pass
if isinstance(obj, (MyThing, MyOtherThing)):
process(obj)
Run Code Online (Sandbox Code Playgroud)
(顺便说一下,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)
Run Code Online (Sandbox Code Playgroud)
添加继承并且它变得更好:所有可处理对象的示例都可以继承
class Processable:
processable = True
Run Code Online (Sandbox Code Playgroud)
但是你不必说服每个人继承你的基类,只是为了设置一个属性.
简单的内置基准测试工具
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
Run Code Online (Sandbox Code Playgroud)
这是2个复活节彩蛋:
一个在python本身:
>>> import __hello__
Hello world...
Run Code Online (Sandbox Code Playgroud)
Werkzeug模块中的另一个,有点复杂,这里是:
通过查看Werkzeug源代码,werkzeug/__init__.py有一行应引起你的注意:
'werkzeug._internal': ['_easteregg']
Run Code Online (Sandbox Code Playgroud)
如果你有点好奇,这应该让你看看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))
Run Code Online (Sandbox Code Playgroud)
现在,如果你运行应用程序并访问http:// localhost:8080 /?macgybarchakku,你应该看到复活节彩蛋.
小智 5
Dict理解
>>> {i: i**2 for i in range(5)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Run Code Online (Sandbox Code Playgroud)
小智 5
设置理解
>>> {i**2 for i in range(5)}
set([0, 1, 4, 16, 9])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
669474 次 |
| 最近记录: |