http://docs.python-guide.org/en/latest/
Reuqests庫的做者寫的經驗python
https://www.kennethreitz.org/essays/repository-structure-and-python
https://github.com/kennethreitz/samplemodgit
furn.pygithub
class Table(): def isdoneby(): pass class Chair(): def isdoneby(): pass
workers.pyapp
class Carpenter(): def whatdo(): pass
若是table.isdoneby()依賴import Carapenter才能執行;相反地,carpenter.whatdo()又要依賴import Table和Chiar。若是一開始就import,出現循環引入。
一個能解決問題可是很差的技巧是在方法或者函數裏import。編輯器
若是Table內部的改變都使Carpenter的某些test cases不經過,那麼Table和Carpenter的耦合性過大,Table的內部改變影響到Carpenter。ide
https://blog.csdn.net/godsme_yuan/article/details/6594013
麪條代碼:冗長,控制結構複雜(例如充滿if,for),混亂而難以理解的代碼。本人以爲,在編輯器裏這些代碼有很是多的guidelines垂下來,很是形象的」麪條「。
餛飩代碼:程序由許多小的,鬆散耦合的部分(方法,類,包等)組成。沒有遵循高內聚,低耦合。書中舉了個例子:若是你不知道何時用必須用FurnitureTable,AssetTable和TableNew,那麼這些代碼就是混沌代碼一塊一塊的,很鬆散。函數
3.1 Being able to tell immediately where a class or function comes from, as in the modu.func idiom, greatly improves code readability and understandability in all but the simplest single file projects.
3.2 In many languages, an include file directive is used by the preprocessor to take all code found in the file and‘copy’ it into the caller’s code. It is different in Python: the included code is isolated in a module namespace, whichmeans that you generally don’t have to worry that the included code could have unwanted effects, e.g. override an
existing function with the same name (即import module, 可用module.func)
3.3 不要用from module import *ui
4.1 文件夾裏有__init__.py就視做一個包
4.2 A file modu.py in the directory pack/ is imported with the statement import pack.modu. This statement will look for an __init__.py file in pack, execute all of its top-level statements. Then it will look for a file named pack/modu.py and execute all of its top-level statements. After these operations, any variable, function, or class defined in modu.py is available in the pack.modu namespace.
4.3 當項目複雜性上升的時候,可能有sub-packages或者sub-sub-packages在一個很深的目錄層次結構裏面(包裏有包,嵌套關係)。這種狀況下,import一個在很深層次的包裏的module時,會執行所有__init__.py文件(files);因此,若是包(package)和包裏的包(sub-package)不共享代碼,最好把__init__.py置空。
4.4 用import very.deep.module as mod 代替 import very.deep.modulethis
Pure functions are more efficient building blocks than classes and objects for some architectures because they have no context or side-effectsspa
6.1 A decorator is a function or a class that wraps (or decorates) a function or a method. The ‘decorated’ function or method will replace the original ‘undecorated’ function or method. Because functions are first-class objects in Python, this can be done ‘manually’, but using the @decorator syntax is clearer and thus preferred.
6.2 This mechanism is useful for separating concerns and avoiding external un-related logic ‘polluting’ the core logic of the function or method.
6.3 A good example of a piece of functionality that is better handled with decoration is memoization or caching: you want to store the results of an expensive function in a table and use them directly instead of recomputing them when they have already been computed. This is clearly not part of the function logic.
7.1 A context manager is a Python object that provides extra contextual information to an action. 用with語句.
with open('file.txt') as f: contents = f.read()
7.2 有兩種實現方法:class和generator. Since the two approaches appear the same, we should follow the Zen of Python to decide when to use which. The class approach might be better if there’s a considerable amount of logic to encapsulate. The function approach might be better for situations where we’re dealing with a simple action.
CustomOpen is first instantiated and then its __enter__ method is called and whatever __enter__ returns is assigned to f in the as f part of the statement. When the contents of the with block is finished executing, the __exit__ method is then called.
# class實現上下文管理 class CustomOpen(object): def __init__(self, filename): self.file = open(filename) def __enter__(self): return self.file def __exit__(self, ctx_type, ctx_value, ctx_traceback): self.file.close() with CustomOpen('file') as f: contents = f.read()
The custom_open function executes until it reaches the yield statement. It then gives control back to the with statement, which assigns whatever was yield‘ed to f in the as f portion. The finally clause ensures that close() is called whether or not there was an exception inside the with
# generator實現上下文管理 from contextlib import contextmanager @contextmanager def custom_open(filename): f = open(filename) try: yield f finally: f.close() with custom_open('file') as f: contents = f.read()
- Python是動態類型語言,也便是variables沒有fixed type,只是引用;
- The dynamic typing of Python is often considered to be a weakness, and indeed it can lead to complexities and hardto-debug code. 例如變量a能夠是任何object.
# Bad a = 1 a = 'a string' def a(): pass # Do something
# Good count = 1 msg = 'a string' def func(): pass # Do something
#Bad items = 'a b c d' # This is a string items = items.split(' ') # ..becoming a list items = set(items) # ... and then a set
9.1 像list這些可變對象,list.append()和list.pop()是原地修改list
9.2 像6這個integer,是不可變對象, x = x + 1會是x指向另外一個對象。
my_list = [1, 2, 3] my_list[0] = 4 print(my_list) # [4, 2, 3] <- The same list has changed x = 6 x = x + 1 # The new x is another object
9.3 string在Python中是不變的
#Bad # 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 # 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
# Better # create a concatenated string from 0 to 19 (e.g. "012..1819") # list comprehension nums = [str(n) for n in range(20)] print("".join(nums))
# Best # create a concatenated string from 0 to 19 (e.g. "012..1819") # map nums = map(str, range(20)) print("".join(nums))
One final thing to mention about strings is that using join() is not always best. In the instances where you are creating a new string from a pre-determined number of strings, using the addition operator is actually faster, but in cases like above or in cases where you are adding to an existing string, using join() should be your preferred method.
foo = 'foo' bar = 'bar' foobar = foo + bar # This is good foo += 'ooo' # This is bad, instead you should do: foo = ''.join([foo, 'ooo'])
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
#Bad def make_complex(*args): x, y = args return dict(**locals()) #Good def make_complex(x, y): return {'x':x, 'y':y}
第二個Good的寫法,可讀性強
#Bad print('one'); print('two') if x == 1: print('one') if <complex comparison> and < other complex comparison>: # Do Something #Good print('one') print('two') if x == 1: print('one') cond1 = <complex comparison> cond2 = <other complex comparision> if cond1 and cond2: # Do Something
關於Positional arguments(位置參數).
Positional arguments are mandatory and have no default values.
def send(message, recipient): pass def point(x, y): pass # Bad, 雖然能夠這樣作 send(recipient='World', message='Hello') point(y=2, x=1) # Good, straightforward而且可讀性高 send('Hello', 'World') and point(1, 2)
關於Keyword arguments(關鍵字參數)
Keyword arguments are not mandatory and have default values. for optional parameters sent to the function.
def send(message, to, cc=None, bcc=None)
arbitrary argument list
In the function body, args will be a tuple of all the remaining positional arguments.
def send(message, *args): pass # send('a', 'b', 'c' ,'d'), args就等於('b', 'c', 'd')
arbitrary keyword argument dictionary
kwargs will be a dictionary of all the passed named arguments that have not been caught by
other keyword arguments in the function signature.
Python裏沒有真正的private屬性, 因此開發者和用戶有責任去遵照約定(conventions).
Rather, instead of relying on concrete walls erected by the developers between their code and other’s, the Python community prefers to rely on a set of conventions indicating that these elements should not be accessed directly.
保持單一return就好
def complex_function(a, b, c): if not a: return None # Raising an exception might be better if not b: return None # Raising an exception might be better if not c: return None # Raising an exception might be better # Plan A: Compute X from a, b and c x = a + b + c if not x: # Plan B for computing x return x # One single exit point for the returned value x will help when maintaining the code.
A programming idiom, put simply, is a way to write code.