文件地址 The Hitchhiker’s Guide to Python!
這份文件
1 2 |
目標物件:入門後,有一定基礎的Pythonista 關鍵詞:最佳實踐,Pythonic,各類工具介紹 |
粗粗粗略地過了一遍,大體撈了一些東西出來,大段大段英文太費眼了,回頭細讀在更新進來
濃縮版,20分鐘可大體過完,然後根據自己需要去看詳細的吧
整體內容還是很不錯的,建議細讀英文
PS:文件含有巨量的TODO(沒寫空白著待補充的),不過但從目錄上來看還是很強大滴,相信完善後,會成為一份很牛逼的指南(難度比官方指南高一點點)
第零部分 Getting Started
不解釋,不翻譯,自個看….真的沒啥(每本入門書籍第一章…)
第一部分 Writing Great Code
Structuring Your Project
import 最佳實踐
Very bad
1 2 3 4 |
[...] from modu import * [...] x = sqrt(4) # Is sqrt part of modu? A builtin? Defined above? |
Better
1 2 3 |
from modu import sqrt [...] x = sqrt(4) # sqrt may be part of modu, if not redefined in between |
Best
1 2 3 |
import modu [...] x = modu.sqrt(4) # sqrt is visibly part of modu's namespace |
Python中關於OOP的 觀點
Decorators
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def foo(): # do something def decorator(func): # manipulate func return func foo = decorator(foo) # Manually decorate @decorator def bar(): # Do something # bar() is decorated |
動態型別(Dynamic typing)
Avoid using the same variable name for different things.
Bad
1 2 3 4 |
a = 1 a = 'a string' def a(): pass # Do something |
Good
1 2 3 4 |
count = 1 msg = 'a string' def func(): pass # Do something |
It is better to use different names even for things that are related, when they have a different type:
1 2 3 4 5 |
Bad items = 'a b c d' # This is a string... items = items.split(' ') # ...becoming a list items = set(items) # ...and then a set |
可變和不可變型別(Mutable and immutable types)
字串拼接最佳實踐
Bad
1 2 3 4 5 |
# create a concatenated string from 0 to 19 (e.g. "012..1819") nums = "" for n in range(20): nums += str(n) # slow and inefficient print nums |
Good
1 2 3 4 5 |
# create a concatenated string from 0 to 19 (e.g. "012..1819") nums = [] for n in range(20): nums.append(str(n)) print "".join(nums) # much more efficient |
Best
1 2 3 |
# create a concatenated string from 0 to 19 (e.g. "012..1819") nums = [str(n) for n in range(20)] print "".join(nums) |
join() is not always best
建立新字串和修改原有字串
1 2 3 4 5 6 |
foo = 'foo' bar = 'bar' foobar = foo + bar # This is good foo += 'ooo' # This is bad, instead you should do: foo = ''.join([foo, 'ooo']) |
字串格式化
1 2 3 4 5 6 |
foo = 'foo' bar = 'bar' foobar = '%s%s' % (foo, bar) # It is OK foobar = '{0}{1}'.format(foo, bar) # It is better foobar = '{foo}{bar}'.format(foo=foo, bar=bar) # It is best |
Code Style
一般概念(General concepts)
明確的程式碼
Bad
1 2 3 |
def make_complex(*args): x, y = args return dict(**locals()) |
Good
1 2 |
def make_complex(x, y): return {'x': x, 'y': y} |
每行一個宣告
Bad
1 2 3 4 5 6 |
print 'one'; print 'two' if x == 1: print 'one' if and : # do something |
Good
1 2 3 4 5 6 7 8 9 10 |
print 'one' print 'two' if x == 1: print 'one' cond1 = cond2 = if cond1 and cond2: # do something |
函式引數
1 2 |
#不解釋了 位置引數,預設引數,*args, **args |
Avoid the magical wand(這個腫麼翻…)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
原因: Python comes with a very rich set of hooks and tools allowing to do almost any kind of tricky tricks 建議: it is always better to use the most straightforward way to achieve your goal 感受一下: We consider that a Python developer should know about these nearly infinite possibilities, because it grows the confidence that no hard-wall will be on the way. However, knowing how to use them and particularly when not to use them is the most important. Like a Kungfu master, a Pythonista knows how to kill with a single finger, and never to actually do it. 其實就是告訴你,騷年,這玩意你要去學習去了解去掌握,目的是增強實力保持自信,但是不要去用啊 (說的原子彈吧....) |
方言(Idioms)
Idiomatic Python code is often referred to as being Pythonic.
列舉了一些:
Unpacking
1 2 3 4 5 6 |
for index, item in enumerate(some_list): # do something with index and item a, b = b, a a, (b, c) = 1, (2, 3) |
忽略接收變數,這裡用的是兩個下劃線,原因
http://docs.python-guide.org/en/latest/writing/style/#create-an-ignored-variable
1 2 |
filename = 'foobar.txt' basename, __, ext = filename.rpartition('.') |
同一個元素建立一個長度為N的列表
1 |
four_nones = [None] * 4 |
建立一個長度N的巢狀列表
1 |
four_lists = [[] for __ in xrange(4)] |
由列表拼接字串
1 2 |
letters = ['s', 'p', 'a', 'm'] word = ''.join(letters) |
快速查詢
1 2 3 4 5 6 7 8 |
d = {'s': [], 'p': [], 'a': [], 'm': []} l = ['s', 'p', 'a', 'm'] def lookup_dict(d): #O(1) return 's' in d def lookup_list(l): #O(n) return 's' in l |
Zen of Python
1 |
import this |
PEP8
1 2 3 4 |
$ pip install pep8 $ pep8 optparse.py optparse.py:69:11: E401 multiple imports on one line optparse.py:77:1: E302 expected 2 blank lines, found 1 |
慣例(Conventions)
判斷值是否等於常量
Bad:
1 2 3 4 5 |
if attr == True: print 'True!' if attr == None: print 'attr is None!' |
Good:
1 2 3 4 5 6 7 8 9 10 11 |
# Just check the value if attr: print 'attr is truthy!' # or check for the opposite if not attr: print 'attr is falsey!' # or, since None is considered false, explicitly check for it if attr is None: print 'attr is None!' |
獲取字典元素
Bad:
1 2 3 4 5 |
d = {'hello': 'world'} if d.has_key('hello'): print d['hello'] # prints 'world' else: print 'default_value' |
Good:
1 2 3 4 5 6 7 8 |
d = {'hello': 'world'} print d.get('hello', 'default_value') # prints 'world' print d.get('thingy', 'default_value') # prints 'default_value' # Or: if 'hello' in d: print d['hello'] |
快捷列表操作
Bad:
1 2 3 4 5 6 |
# Filter elements greater than 4 a = [3, 4, 5] b = [] for i in a: if i > 4: b.append(i) |
Good:
1 2 3 |
a = [3, 4, 5] b = [i for i in a if i > 4] b = filter(lambda x: x > 4, a) |
Bad:
1 2 3 4 |
# Add three to all list members. a = [3, 4, 5] for i in range(len(a)): a[i] += 3 |
Good:
1 2 3 4 |
a = [3, 4, 5] a = [i + 3 for i in a] # Or: a = map(lambda i: i + 3, a) |
使用enumerate
1 2 3 4 5 6 |
for i, item in enumerate(a): print i, item # prints # 0 3 # 1 4 # 2 5 |
讀檔案
Bad:
1 2 3 4 |
f = open('file.txt') a = f.read() print a f.close() |
Good:
1 2 3 |
with open('file.txt') as f: for line in f: print line |
超長的行
Bad:
1 2 3 4 5 6 |
my_very_big_string = """For a long time I used to go to bed early. Sometimes, when I had put out my candle, my eyes would close so quickly that I had not even time to say “I’m going to sleep.”""" from some.deep.module.inside.a.module import a_nice_function, another_nice_function, yet_another_nice_function |
Good:
1 2 3 4 5 6 7 8 9 |
#受教了.... my_very_big_string = ( "For a long time I used to go to bed early. Sometimes, " "when I had put out my candle, my eyes would close so quickly " "that I had not even time to say “I’m going to sleep.”" ) from some.deep.module.inside.a.module import ( a_nice_function, another_nice_function, yet_another_nice_function) |
Reading Great Code
感受下:The number one thing that Python programmers do is read code.
再感受一把:One of the secrets of becoming a great Python programmer is to read, understand, and comprehend excellent code.
幾個推薦閱讀原始碼專案
文件(Documentation)
感受一下:Readability is a primary focus for Python developers, in both project and code documentation.
具體還是讀原文吧
專案文件組成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
1.A README file at the root directory should give general information to the users and the maintainers. reStructuredText 或 Markdown 2.An INSTALL file is less necessary with python setup.py 3.A LICENSE file should always be present and specify the license under which the software is made available to the public 4.A TODO file or a TODO section in README should list the planned development for the code. 5.A CHANGELOG file or section in README should compile a short overview of the changes in the code base for the latest versions. |
幾種文件工具
1 2 3 |
Sphinx(聽說最強大....) reStructuredText Markdown(俺的最愛...) |
程式碼文件建議
Comments clarify code and begin with a hash (#).
In Python, docstrings describe modules, classes, and functions:
1 2 |
def square_and_rooter(x): """Returns the square root of self times self.""" |
註解程式碼塊
Do not use triple-quote strings to comment code.
This is not a good practice, because line-oriented command-line tools such as grep will not be aware that the commented code is inactive.
It is better to add hashes at the proper indentation level for every commented line.
最佳實踐:
1 2 |
不用三引號註解程式碼塊 每一行加#來註釋 |
測試你的程式碼(Testing Your Code)
測試一些通用原則
1 2 3 4 5 6 7 8 9 10 11 12 13 |
1.A testing unit should focus on one tiny bit of functionality and prove it correct. 2.Each test unit must be fully independent 3.Try hard to make tests that run fast 4.Learn your tools and learn how to run a single test or a test case 5.Always run the full test suite before a coding session, and run it again after. 6.It is a good idea to implement a hook that runs all tests before pushing code to a shared repository. 7.If you are in the middle of a development session and have to interrupt your work, it is a good idea to write a broken unit test about what you want to develop next. 8.The first step when you are debugging your code is to write a new test pinpointing the bug. 9.Use long and descriptive names for testing functions 10.When something goes wrong or has to be changed, and if your code has a good set of tests, you or other maintainers will rely largely on the testing suite to fix the problem or modify a given behavior. 11.Another use of the testing code is as an introduction to new developers. |
單元測試(Unittest)
Python內建模組, 文件
1 2 3 4 5 6 7 8 |
import unittest def fun(x): return x + 1 class MyTest(unittest.TestCase): def test(self): self.assertEqual(fun(3), 4) |
文件測試(Doctest)
非精細case,只驗證主體功能可用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
def square(x): """Squares x. >>> square(2) 4 >>> square(-2) 4 """ return x * x if __name__ == '__main__': import doctest doctest.testmod() |
相關工具
py.text
$ pip install pytest
Nose unittest的擴充套件
$ pip install nose
tox
$ pip install tox
Unittest2
$ pip install unittest2
mock
$ pip install mock
Common Gotchas(不懂怎麼翻…╮(╯▽╰)╭ )
一些新手可能疑惑的例子
兩個例子
1.可變預設引數
What You Wrote
1 2 3 |
def append_to(element, to=[]): to.append(element) return to |
What You Might Have Expected to Happen
1 2 3 4 5 6 7 8 |
my_list = append_to(12) print my_list my_other_list = append_to(42) print my_other_list [12] [42] |
What Does Happen
1 2 |
[12] [12, 42] |
What You Should Do Instead
1 2 3 4 5 |
def append_to(element, to=None): if to is None: to = [] to.append(element) return to |
Python預設引數在函式定義處執行一次,而不是每次函式呼叫時執行。
2.Late Binding Closures(又一個,延遲繫結閉包?)
What You Wrote
1 2 |
def create_multipliers(): return [lambda x : i * x for i in range(5)] # |
What You Might Have Expected to Happen
1 2 3 4 5 6 7 8 |
for multiplier in create_multipliers(): print multiplier(2) # 任意一個返回的函式被呼叫時,內部迴圈i=4 0 2 4 6 8 |
What Does Happen
1 2 3 4 5 |
8 8 8 8 8 |
What You Should Do Instead
1 2 3 4 5 |
from functools import partial from operator import mul def create_multipliers(): return [partial(mul, i) for i in range(5)] |
Python的閉包是延時繫結
選擇證照(Choosing a License)
開源證照 列表
證照選擇器 入口
第二部分 Scenario Guide
都是介紹性質的,類似工具目錄,而且大部分是空的,目前沒詳細資訊
要了解具體,goole相關關鍵詞吧
具體自己翻吧 位置
目錄:
Network Applications
Http:
1 |
Requests |
Distributed Systems
1 2 |
ZeroMQ RabbitMQ |
Web Applications
Context
1 |
WSGI |
Frameworks
1 2 3 4 5 |
Django Flask Werkzeug Tornado Pyramid |
Web Servers
1 |
Nginx |
WSGI Servers
1 |
Gunicorn |
Hosting
1 2 3 4 |
PasS (Platform as a service) Heroku DotCloud Gondor |
Templating
1 |
Jinja2 |
HTML Scraping
1 2 |
lxml Requests |
Command Line Applications
1 2 |
Clint docopt |
GUI Applications
1 2 3 4 5 6 7 8 |
Qt Cocoa wxPython GTk Tk Kivy PyjamasDesktop (pyjs Desktop) Camelot |
Databases
1 2 3 |
DB-API SQLAlchemy Django ORM |
Networking
1 2 3 |
Twisted PyZMQ gevent |
Systems Administration
1 2 3 4 5 6 7 |
Fabric Salt Psutil Chef Puppet Blueprint Buildout |
Continuous Integration
1 2 3 4 5 |
Jenkins Buildbot Mule? Tox Travis-CI |
Speed
C Extensions
1 2 3 4 5 |
GIL Cython Pyrex Shedskin Numba |
Threading
1 2 |
Threading Multiprocessing |
Scientific Applications
Tools
1 |
IPython |
Libraries
1 2 3 4 5 6 7 |
NumPy Numba SciPy Matplotlib Pandas Rpy2 PsychoPy |
Image Manipulation
1 |
Python Imaging Library(PIL) |
XML parsing
1 2 |
untangle xmltodict |
有需要自取…..
第三部分 Shipping Great Code
http://docs.python-guide.org/en/latest/#shipping-great-code
第四部分 Development Environment
http://docs.python-guide.org/en/latest/#development-environment
第五部分 Additional Notes
http://docs.python-guide.org/en/latest/#additional-notes
The end!
2013-11-25
wklken
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式