前言
算来学会 python 已经 4 年有余,使用它作为我的工作语言也 3 年了。这个过程中我读过一些书,看了很多人的博客.
也读了一些开源项目的代码,但是尤其重要的是和同事在一起得到的进步。一直到现在我都有习惯了解 python, 提高自己的 python 能力
说到 idiomatic. python 有自己独特的语法和习惯。而实现同样功能的代码不用的人呢也会使用不同的方式.
写出来的代码内容也有非常大的区别,但是总是会有一个是更好的,idiomatic 的写法。今天突然翻到了一个我之前一直维护的 keynote. 这里面记录了我总结和从其他的 ppt 或者代码里看到更优美的写法.
其中有些已经放在 python3 中,说明这样的功能确实是程序员蛮有用的。我整理了一下。来给大家分享下.
PS: 这些是编程的思维,举一反三,再适合的时候利用上.
循环列表,直到找到符合的结果,没有结果返回一个默认值
通常这样:
a = -1
for i in range(1, 10):
if not i % 4:
a = i
break
# a = 4
|
更好的写法:
a = ''
a = next((i for i in range(1, 10) if not i % 4), -1)
# a = 4
|
执行调用直到某种情况
通常这样:
blocks = []
while True:
block = f.read(32)
if block == '':
break
blocks.append(block)
|
更好的写法:
from functools import partial
blocks = []
for block in iter(partial(f.read, 32), ''):
blocks.append(block)
|
标记区分
def find(seq, target):
found = False
for i, value in enumerate(seq):
if value == target:
found = True
break
if not found:
return -1
return i
|
更好的写法:
def find(seq, target):
for i, value in enumerate(seq):
if value == target:
break
else:
return -1
return i
|
threading.Lock
lock = threading.Lock()
lock.acquire()
try:
print 'Critical section 1'
print 'Critical section 2'
finally:
lock.release()
|
其实是这样的:
lock = threading.Lock()
with lock:
print 'Critical section 1'
print 'Critical section 2'
|
忽略抛出的异常
try:
os.remove('somefile.tmp')
except OSError:
pass
|
with ignored(OSError):
os.remove('somefile.tmp')
|
就算用 python2, 我也强烈建议把这样的函数放在项目里
@contextmanager
def ignored(*exceptions):
try:
yield
except exceptions:
pass
|
如果你使用 python3.4 或以上可以使用标准库的contextlib.suppress
class suppress:
def __init__(self, *exceptions):
self._exceptions = exceptions
def __enter__(self):
pass
def __exit__(self, exctype, excinst, exctb):
return exctype is not None and issubclass(exctype, self._exceptions)
|
直接把输出存进文件中
with open('help.txt', 'w') as f:
oldstdout = sys.stdout
sys.stdout = f
try:
help(pow)
finally:
sys.stdout = oldstdout
|
同样使用 python3.4 以上可以使用
with open('help.txt', 'w') as f:
with redirect_stdout(f):
help(pow)
|
redirect_stdout 是这样的:
@contextmanager
def redirect_stdout(fileobj):
oldstdout = sys.stdout
sys.stdout = fileobj
try:
yield fieldobj
finally:
sys.stdout = oldstdout
|
最简单的缓存
通常这样实现缓存:
def web_lookup(url, saved={}):
if url in saved:
return saved[url]
page = urllib.urlopen(url).read()
saved[url] = page
return page
|
可以这样写
@cache
def web_lookup(url):
return urllib.urlopen(url).read()
def cache(func):
saved = {}
@wraps(func)
def newfunc(*args):
if args in saved:
return saved[args]
result = func(*args)
saved[args] = result
return result
return newfunc
|