1. 程式人生 > >Updating -- Python知識

Updating -- Python知識


  最近密集使用Python,重又拾起曾經的工具。學的快,忘的也快。大的知識點雖還記得,一些細節已經記不得了。

  使用開發語言coding,只是當作工具使用,不求甚解,理解當然不深刻,自然忘的也快。
  FQA,立此文以記錄之,方便查詢,不斷更新,減少網路查詢時間,以求加深理解和加速回憶。

【https://www.python.org/dev/peps/pep-0008/ -- Style Guide for Python Code】

import this

The Zen of Python, by Tim Peters   python哲學/python之禪

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.  雖然這並不容易,因為你不是python之父
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!  名稱空間是個好主意,應該多用


“Don't Reinvent the Wheel”--不要重複發明輪子

DRY是指Don't Repeat Yourself特指在程式設計以及計算中避免重複程式碼,因為這樣會降低靈活性、簡潔性,並且可能導致程式碼之間的矛盾。《The Pragmatic Programmer》對這一思想做了很好的闡述。
把一切重複的程式碼抽象出來。最主要的原因是很好維護,當需要改動時只需要改動一次。
程式碼複用的層次:函式級別複用,物件級別複用,介面級別的,類庫級別複用,框架級別複用。
把固定的部分和變化的部分分離出來。固定的部分分離有利於程式碼複用,變換的部分分離,在變換髮生時容易修改替換。簡潔比簡單更重要,維護成本高低的決定因素。


--------------------------------------------------------------------------------------------------------------------------

1. Python中的“_”,"__"  

【https://segmentfault.com/a/1190000002611411】

  1)_, 互動直譯器中最後一次執行語句的返回結果
  _用作被丟棄 的名稱,不作特殊使用
  以“_”開頭,弱內部標識,指私有變數或方法,定義為類內部變數或方法,只能在類內部訪問。使用from module_name  import * 匯入時不會被匯入,但可以使用import module_name呼叫。
   a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.

  2)以"_"結尾,是為了使用python關鍵字作為變數名,在結尾新增"_"以避免與python關鍵字的命名衝突。

  3)"__A", 避免被子類重寫,只能在類內部呼叫。模組內的成員,表示私有成員,外部無法直接呼叫。使用dir()命令顯示此類方法,顯示為 類名__A

  4)"__A__", 表示A是一個只能被python呼叫的方法 或 用作特殊用途。  magic methods??

 

2. Self: Python中物件方法的定義很怪異,第一個引數一般都命名為self(相當於其它語言的this),用於傳遞物件本身,而在呼叫的時候則不必顯式傳遞,系統會自動傳遞。

 

3. Super: 在super機制裡可以保證公共父類僅被執行一次

super(type[, object-or-type])  Return the superclass of type. If the second argument is omitted the super object returned is bound. If the second argument is an object, isinstance(obj, type) must be true. If the second argument is a type, issubclass(type2, type) must be true. super() only works for new-style classes. A typical use for calling a cooperative superclass method

super就是用來呼叫所繼承你類的方法,只是多繼承時公共僅被 執行一次,而 父類.方法 的用法,每一次申明都會呼叫一次父類。

 

4. __ini__: 作用是初始化已例項化後的物件, 例項化子類時,會自動隱式呼叫超類中已定義的__init__。如果子類重寫了__init__,例項化子類時,則不會隱式的再去呼叫超類中已定義的__init__,因此需要顯示呼叫父類方法,即super(子類名,self). __init__

 

5. MRO: MRO(Method Resolution Order):方法解析順序。 【http://python.jobbole.com/85685/】
Python語言包含了很多優秀的特性,其中多重繼承就是其中之一,但是多重繼承會引發很多問題,比如二義性,Python中一切皆引用,這使得他不會像C++一樣使用虛基類處理基類物件重複的問題,但是如果父類存在同名函式的時候還是會產生二義性,Python中處理這種問題的方法就是MRO。


6. sys.path: python的搜尋模組的路徑集,list。【https://docs.python.org/3/using/cmdline.html】

import sys
sys.path.append('c:\\mypythonlib')

7. @ decorator 修飾符/裝飾器,將下一行的類或函式作為引數傳遞到修飾行,因此@修飾的函式必須有引數,而被傳遞的類或函式將無法單獨執行

def t1(a):          # if there is no parameter "a": TypeError: t1() takes 0 positional arguments but 1 was given
    print(1)

def t2(b):
    print(2)

@t1
@t2                   

def t3():           # if there is no t3: SyntaxError: unexpected EOF while parsing
    print(3)        # t3(): TypeError: 'NoneType' object is not callable

# t1(t2(t3())).   @t1: @t2 is t1's parameter, @t2: t3 is t2's parameter, interact
# >> 2 1
 

8. python2.7和python3.5的區別

   1)print 和 print()

   2) /: int 和 float

   3) BIF及functools的引用

   4)iter的next方法實現(2.7__next__, 3.X next())


9.string, tuble, list的slice操作分為正向和逆向,因此表達分為

  1)開始:結束:步長 (步長可以省略,預設值為1),其中的步長與開始與結束的方向要一致,即相同的正負值 

  2)開始::步長,此時的遍歷只能正向進行到結束(1)或逆向進行到開始(-1),而不能迴圈進行

  3)slice結束值為開區間,也就是計算中結束值不在其中

a = [1,2,3] => a[0:3:1] => a[-1:-4:-1] 


10.using Excel

import xlrd
import xlwt

#read
rd = xlrd.open_workbook(filename)  #read file
sh = rd.sheets()[0]   #get sheet data
nrow = sh.nrows  #get row number
row = sh.row(n)  #get row content
cel = row[i].value #get cell value

#write
wr = xlwt.Workbook()    #get file
sh = wr.add_sheet(sheetname,Formate)  #add new sheet with format

sh.write(rowN,columnN,value)
wr.save(filename)

11. __name__ == "__main__"

     1) 直接執行檔案,則 __name__指向檔案中的__main__,會執行__main__中的所有內容
     2) import該檔案時,則__name__指向引用檔案本身,只會執行引用檔案自身,不會執行__main__中的內容

def test():
    return lambda x,y: x+ y

print(test()(5,6))

if __name__ == "__main__":
    print("This is test: ", test())
    print(__name__)
    print(test()(1,2))
#直接執行
11
This is test:  <function test.<locals>.<lambda> at 0x00000000031D3510>
__main__
3

import t1
from functools import reduce

print("This is Main test: ", t1.test()(8,9))
print(t1.__name__)
#引用檔案
11
This is Main test:  17
t1

12. map, filter, reduce

都是通過函式對迭代器進行運算,在py3 map和filter生成為對像,因此輸出要用list就行轉化;而reduce不能直接使用,需要在functools中引入

  1) map: 對迭代器中的每個元素進行函式運算,並輸出map對像,使用list轉化後即可輸出
  2) filter: 按函式對迭代器中的每個元素進行篩選,並輸出filter對像,使用list轉化後即可輸出
  3) reduce: 需要兩個引數,將迭代器中的元素從左至右兩兩按函式進行運算,輸出最終值

from functools import reduce

print(list(map(lambda x: x**2,[1,2,3,4,5])))
print(list(filter(lambda x: x%2 == 0, [1,2,3,4,5])))
print(reduce(lambda x,y: x*y,[1,2,3,4,5]))
#輸出結果
[1, 4, 9, 16, 25]
[2, 4]
120


13. set: Build an unordered collection of unique elements. -- 可以使用set進行去除重複


14.list轉字串: ''.join(list)  -- 其中,‘’為分隔符,list中的每個元素應為字串


15.python函式引數中的 * 和 **

  * 以Tuple形式傳遞任意個無名引數

  ** 以Dict形式傳遞任意個有名引數


17. from . import sessions

    “ . ” 指當前資料夾裡的初始化,即__init__.py檔案。

  如果沒有__init__.py,則需要使用 .XXX進行檔案引用

18. django.models.admin    Model.__str__()
__str__() is a Python "magic method" that defines what should be returned if you call str() on the object. Django uses str(obj) (or the related function, unicode(obj) -- see below) in a number of places, most notably as the value displayed to render an object in the Django admin site and as the value inserted into a template when it displays an object. Thus, you should always return a nice, human-readable string for the object's __str__. Although this isn't required, it's strongly encouraged (see the description of __unicode__, below, before putting __str__ methods everywhere).
    Model.__unicode__()
The __unicode__() method is called whenever you call unicode() on an object. Since Django's database backends will return Unicode strings in your model's attributes, you would normally want to write a __unicode__() method for your model. The example in the previous section could be written more simply as:
If you define a __unicode__() method on your model and not a __str__() method, Django will automatically provide you with a __str__() that calls __unicode__() and then converts the result correctly to a UTF-8 encoded string object. This is recommended development practice: define only __unicode__() and let Django take care of the conversion to string objects when required.


19. CSV(Comma-Separated Values),檔案以純文字形式儲存表格資料(數字和文字)。

無需引入第三方庫,可以用來做資料的儲存。

存在問題UnicodeDecodeError: 'gbk' codec can't decode byte 0x94 in position 48: illegal multibyte sequence。

嘗試解決,未果: 1) 檔案頭新增encoding; 2)開啟檔案時定義encoding

import csv

with open('filecsv.csv','r') as fp:
    freader = csv.reader(fp)
    rl = fp.readlines()
    for i in range(1,len(rl)):
        [ID,Action, Object, Method, Data, Memo] = map(lambda x: x.ljust(10),rl[i].split(","))
        print(ID,Action,Object,Method,Data,Memo)

20. 模組A定義一無返回值方法a(),在模組B中呼叫print(a()),輸出a()結果和None。輸出None原因是python的方法如果沒有返回值,預設返回值為None

21. 模組T中方法a()的引用
    import T --> T.a()
    import T as t --> t.a()
    from T import* --> a()

22. 三目運算 ...?...:...     python中的三目運算有兩種方法可以實現     1)result1 if condition else result2     2) condition and result1 or result2  -- 有缺陷,具體看API中的FAQ 
23. list的反向輸出     1)使用迴圈,從len(list)-1 到 0 逐一輸出,不改變原有list     2)list.reverse(), 直接將list反轉,改變原有list     3)list[::-1],以步長為-1輸出,不改變原有list\
24.BIF: build in function, 內建函式,指python自身的內建函式
25.ZIP: zip(iter1 [,iter2 [...]]) --> zip object    Return a zip object whose .__next__() method returns a tuple where the i-th element comes from the i-th iterable argument.The .__next__() method continues until the shortest iterable in the argument sequence is exhausted and then it raises StopIteration.    解釋:以元組形式返回迭代器的對應元素組合,直到最短長度的迭代器匹配完成。 例:
>>> a = [1,2,3,4]
>>> b = [6,7,8,9,0]
>>> c =zip(a,b)
>>> list(c)
[(1, 6), (2, 7), (3, 8), (4, 9)]

26.yield:generator生成器,生成一個迭代器iterator。在函式中使用yield,返回型別為generator,函式作為生成器,返回生成器引數構成的元組
>>> def test(m):
    a = b = 1
    while(a<m):
        yield a
        a,b=b,a+b        
>>> type(test(15))
<class 'generator'>
>>> test(15)
<generator object test at 0x00000000033D8F68>
>>> list(test(15))
[1, 1, 2, 3, 5, 8, 13]
  修改程式
>>> def test(m):
    a = b = 1
    while(a<m):
        yield a,b
        a,b=b,a+b
>>> test(15)
<generator object test at 0x00000000033D8F68>
>>> list(test(15))
[(1, 1), (1, 2), (2, 3), (3, 5), (5, 8), (8, 13), (13, 21)]
 
  27. 偏函式 -- import functoolspartial(func, *args, **keywords) - new function with partial application of the given arguments and keywords.  
  
 
  
 
  --通過partial實現一個新的函式,新函式需要給定指定的引數或關鍵字,即用指定的引數替代原有函式的引數
  
 
  
  
import functools

def test(a,b):
    print(a,"-",b)

test(1,2)

t = functools.partial(test,5)
t(6)

print(functools.partialmethod(t))
1 - 2
5 - 6
functools.partialmethod(functools.partial(<function test at 0x000000000336E488>, 5), , )

28. from itertools import islice (迭代器切片)
>>> from itertools import islice
>>> a = '12345'
>>> list(islice(a,0,len(a)))
['1', '2', '3', '4', '5']