python自學筆記

 

python自學筆記

 



1.輸出

print用逗號隔開多個輸出字符串,也能夠用「+」來代替「,」php

print "李帥",「王子軒」

2.輸入

name = raw_input()
#有提示的輸入:
name = raw_input('please enter your name: ')
print 'hello,', name

3.零碎

  • 若是字符串裏面有不少字符都須要轉義,就須要加不少\,爲了簡化,Python還容許用r」表示」內部的字符串默認不轉義
  • 若是字符串內部有不少換行,用\n寫在一行裏很差閱讀,爲了簡化,Python容許用」’…」’的格式表示多行內容
  • 第一行註釋是爲了告訴Linux/OS X系統,這是一個Python可執行程序,Windows系統會忽略這個註釋;第二行註釋是爲了告訴Python解釋器,按照UTF-8編碼讀取源代碼,不然,你在源代碼中寫的中文輸出可能會有亂碼。
#!/usr/bin/env python
# -*- coding: utf-8 -*-+

4.數據結構

4.1 list 類比於java中的數組

classmates = ['Michael', 'Bob', 'Tracy']

用索引來訪問list中每個位置的元素,記得索引是從0開始的:
classmates[0]
若是要取最後一個元素,除了計算索引位置外,還能夠用-1作索引,直接獲取最後一個元素:
classmates[-1]
list是一個可變的有序表,因此,能夠往list中追加元素到末尾:
classmates.append(‘Adam’)
也能夠把元素插入到指定的位置,好比索引號爲1的位置
python
classmates.insert(1, 'Jack')
p = ['asp', 'php']
s = ['python', 'java', p, 'scheme']

要拿到’php’能夠寫p[1]或者s[2][1],所以s能夠當作是一個二維數組,相似的還有三維、四維……數組,不過不多用到。java

4.2 tuple 元祖

tuple和list很是相似,可是tuple一旦初始化就不能修改python

classmates = ('Michael', 'Bob', 'Tracy')

5.條件判斷和循環

5.1 條件判斷

if <條件判斷1>:
    <執行1>
elif <條件判斷2>:
    <執行2>
elif <條件判斷3>:
    <執行3>
else:
    <執行4>

5.2 循環

Python的循環有兩種linux

  • 一種是for…in循環,依次把list或tuple中的每一個元素迭代出來
names = ['Michael', 'Bob', 'Tracy']
for name in names:
    print name
  • 第二種循環是while循環,只要條件知足,就不斷循環,條件不知足時退出循環。好比咱們要計算100之內全部奇數之和,能夠用while循環實現:
sum = 0
n = 99while n > 0:
    sum = sum + n
    n = n - 2print sum

6.使用dict和set

6.1 dict

dict的支持,dict全稱dictionary,在其餘語言中也稱爲map算法

>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95

dict查找速度比較快的緣由:給定一個名字,好比’Michael’,dict在內部就能夠直接計算出Michael對應的存放成績的「頁碼」,也就是95這個數字存放的內存地址,直接取出來,因此速度很是快。編程

和list比較,dict有如下幾個特色:數組

  • 查找和插入的速度極快,不會隨着key的增長而增長;須要佔用大量的內存,內存浪費多。
    而list相反:
  • 查找和插入的時間隨着元素的增長而增長;
    佔用空間小,浪費內存不多。
    因此,dict是用空間來換取時間的一種方法。

6.2 set

set和dict相似,也是一組key的集合,但不存儲value。因爲key不能重複,因此,在set中,沒有重複的key。數據結構

要建立一個set,須要提供一個list做爲輸入集合:
s = set([1, 2, 3])閉包

7.函數的使用

7.1函數返回多個值,同時接受多個值

python中函數能夠直接返回多個值。實際上是個假象,是以tuple的形式返回的app

__author__ = 'shuai.li'import math
def distance(x, y, step, angle=45):
    nx = x + step * math.cos(angle)
    ny = y + step * math.sin(angle)
    return nx, ny
# main functionif __name__ == "__main__":
    nx, ny = distance(5, 10, 1)
    print nx, ny
>>>C:\pythonTest>python function.py
>>>4.55192638387 10.8939966636

下面的輸出能夠看出其實際上爲一個tuple類型

if __name__ == "__main__":
    r = distance(5, 10, 1)
    print r
>>>C:\pythonTest>python function.py
>>>(5.52532198881773, 10.850903524534118)

7.2函數參數的默認值

函數默認值的坑

def add_end(L=[]):
    L.append('END')
    return L
>>> add_end()
['END']
可是,再次調用add_end()時,結果就不對了:
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']

緣由是L實際上在python裏面是個變量,它指向對象[],當使用的時候改變了L的值,那麼其指向的內容就發生了變化,因此函數參數的默認值最好是個不可變對象

7.3可變參數的函數

在參數前面加上 * 就把函數的參數變成可變參數

def cal(*numbers):
    sum = 0
    for num in numbers:
        sum = sum + math.pow(num, 2)
    return sum

# main functionif __name__ == "__main__":
    r = cal(1, 2)
    print r
    r1 = cal(1, 2, 3)
    print r1
>>> C:\pythonTest>python function.py
>>> 5.0
>>> 14.0

可是我原本就是一個tuple或list不能讓我再把裏面的對象一個個提出來吧。不用,python提供了一種變通的方案,就是直接在你的tuple或者list前面加上」 *「其他操做交給python吧。

def cal(*numbers):
    sum = 0
    for num in numbers:
        sum += math.pow(num, 2)
    return sum

# main functionif __name__ == "__main__":
    r = (1, 2)
    print cal(*r)
>>> C:\pythonTest>python function.py
>>> 5.0

7.4可變個數帶參數名的入參

** 這樣就能夠傳入0個或者多個帶參數名的參數,用在有必填參數和非必填參數的狀況,和可變參數的函數相似在參數中直接傳入鍵值對,也能夠不傳參數

def student(name, age, **city):
    print name, age, city

# main functionif __name__ == "__main__":
    city = {"city": "beijing", "street": "suzhoujie"}
    student("lishuai", 12, city="beijing", street="suzhoujie")
>>>C:\pythonTest>python function.py
>>>lishuai 12 {'city': 'beijing', 'street': 'suzhoujie'}

固然傳入的參數能夠直接爲一個dict,這樣能夠像可變參數那樣直接傳入

def student(name, age, **city):
    print name, age, city['city'], city['street']

# main functionif __name__ == "__main__":
    city = {"city": "beijing", "street": "suzhoujie"}
    student("lishuai", 12, **city)

7.5參數類型組合

在Python中定義函數,能夠用必選參數、默認參數、可變參數和關鍵字參數,這4種參數均可以一塊兒使用,或者只用其中某些,可是請注意,參數定義的順序必須是:必選參數、默認參數、可變參數和關鍵字參數。

!!!當這四種類型都有的時候,能夠直接傳入 tuple和dict。注意此時tuple會自動填充前面的必填項因此,對於任意函數,均可以經過相似func(*args, **kw)的形式調用它,不管它的參數是如何定義的。

def func(a, b, c=0, *args, **kw):
    print 'a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw
>>> args = (1, 2, 3, 4)
>>> kw = {'x': 99}
>>> func(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'x': 99}

使用*args和**kw是Python的習慣寫法,固然也能夠用其餘參數名,但最好使用習慣用法。???
通過嘗試,是不能去掉參數前面的」「和」*

8.關於函數遞歸

遞歸時小心棧溢出。函數的調用是經過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就要增長一層,每當函數返回,棧就會減小一層。計算的內存裏面的棧是有限的。
解決遞歸調用棧溢出的方法是經過尾遞歸優化,實際上就是每次調用函數遞歸時,傳入的參數是已經提早算好的,這樣就不用棧層層堆疊。

9.python的高級特性

9.1切片

  • 切片至關於直接取其中一塊
  • -1能夠表明最後一個對象
  • []中左邊的對象在list中也在左邊,如果顛倒了順序,將獲得空list
__author__ = 'shuai.li'

if __name__ == "__main__":
    l = ["lishuai", "wangwang", "lili", "shuai"]
    print l[0:3]
    print l[-1]
    print l[-3:-1]
    print l[-1:-3]
    print l[-3:]
    print l[::2]
>>>C:\pythonTest>python special.py
['lishuai', 'wangwang', 'lili']
shuai
['wangwang', 'lili']
[]
['wangwang', 'lili', 'shuai']
['lishuai', 'lili']   #特別注意這個的用法,每兩個取一個

9.2遍歷

__author__ = 'shuai.li'

if __name__ == "__main__":
    student = {"name": "lishuai", "age": 12}
    for k, v in student.items():
        print k+":"+str(v)

C:\pythonTest>python  iteration.py
age:12
name:lishuai

9.3列表生成器

9.3.1 怎麼用?

列表生成式即List Comprehensions,是Python內置的很是簡單卻強大的能夠用來建立list的生成式。
前面寫要怎樣生成每一項(每一項的內容),後面加上要生成幾個(每一項的條件),從點到線

__author__ = 'shuai.li'if __name__ == "__main__":
    print [x + x * x for x in range(0,10,2)]
>>>C:\pythonTest>python listGenerate.py
>>>[0, 6, 20, 42, 72]

能夠在for循環後面加上 if條件.

if __name__ == "__main__":
    print [x for x in range(0, 50) if x % 3 == 0 if x % 4 == 0 ]

注意若是後面有if條件。程序會忽略步長。

if __name__ == "__main__":
    print [x for x in range(0, 50, 2) if x % 3 == 0 if x % 4 == 0 ]
>>>C:\pythonTest>python listGenerate.py
>>>[0, 12, 24, 36, 48]

還能夠多層循環

if __name__ == "__main__":
    print [m+n for m in 'xyz' for n in 'abc' ]
C:\pythonTest>python listGenerate.py
['xa', 'xb', 'xc', 'ya', 'yb', 'yc', 'za', 'zb', 'zc']

前面的條件還能夠寫成函數的形式

l = ['HELLO', 'Fuck', 'yoU']
    print [s.lower() for s in l]

9.3.2用在哪?

須要列出一長串的,而且每個對象都相似。
如:列出當前目錄下全部的文件和目錄

import os
if __name__ == "__main__":
    print [d for d in os.listdir(".")]
C:\pythonTest>python listGenerate.py
['.idea', 'function.py', 'iteration.py', 'listGenerate.py', 'special.py']

9.4生成器

生成器的好處是邊生成邊計算,這樣就不會像列表生成器那樣須要佔用很大的空間,尤爲是在很大的列表時比較有用。
寫法就是將列表生成式的[]改爲(),就建立了一個generator:
可是咱們能夠直接打印出列表生成器list的每個元素,可是不能直接打印 出生成器的元素,須要藉助於next()函數,還可使用for循環來迭代對象。

還有一種寫法是:包含yield關鍵字
最難理解的就是generator和函數的執行流程不同。函數是順序執行,遇到return語句或者最後一行函數語句就返回。而變成generator的函數,在每次調用next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。
yield 的做用就是把一個函數變成一個 generator,帶有 yield 的函數再也不是一個普通函數,Python 解釋器會將其視爲一個 generator,調用 fab(5) 不會執行 fab 函數,而是返回一個 iterable 對象!在 for 循環執行時,每次循環都會執行 fab 函數內部的代碼,執行到 yield b 時,fab 函數就返回一個迭代值,下次迭代時,代碼從 yield b 的下一條語句繼續執行,而函數的本地變量看起來和上次中斷執行前是徹底同樣的,因而函數繼續執行,直到再次遇到 yield。

帶yield的函數是一個生成器,可使用for in iterate的方式遍歷元素,或者使用 function.next()來遍歷元素

下面是一個生成3的整數倍數的生成器

__author__ = 'shuai.li'# coding:utf-8

# 一個返回3的整數倍的生成器def odd(n):
    a = 0
    while n > 0:
        a += 3
        n -= 1
        yield a

if __name__ == "__main__":
    for a in odd(5):
        print a
input:
>>> C:\pythonTest>python generator.py
3691215

10.函數式編程

函數式編程就是一種抽象程度很高的編程範式,純粹的函數式編程語言編寫的函數沒有變量,所以,任意一個函數,只要輸入是肯定的,輸出就是肯定的,這種純函數咱們稱之爲沒有反作用。而容許使用變量的程序設計語言,因爲函數內部的變量狀態不肯定,一樣的輸入,可能獲得不一樣的輸出,所以,這種函數是有反作用的。

函數式編程的一個特色就是,容許把函數自己做爲參數傳入另外一個函數,還容許返回一個函數!

Python對函數式編程提供部分支持。因爲Python容許使用變量,所以,Python不是純函數式編程語言。

10.1高階函數

函數能夠像變量同樣賦值給變量

if __name__ == "__main__":
    f = abs
    print f(-1)

上面的程序能夠看出f如今已經指向了abs函數自己

那麼函數名是什麼呢?函數名其實就是指向函數的變量!對於abs()這個函數,徹底能夠把函數名abs當作變量,它指向一個能夠計算絕對值的函數!

傳入函數

def add(a, b, f):
    return f(a) + f(b)

if __name__ == "__main__":
    print add(5, -10, abs)

編寫高階函數,就是讓函數的參數可以接收別的函數。

10.2 map()和reduce()函數

map函數就是傳入一個函數對傳入的另外一個對象中每個元素進行相同的處理。reduce()就是首先處理後面對象的前兩個元素,以後合成一個元素而後與第三個元素做用,一直到全部元素處理完畢。
把一個list中的數字轉換爲字符串:

map的簡單使用

if __name__ == "__main__":
    print map(str, [1, 2, 3, 4, 5])
>>> C:\pythonTest>python mapAndreduce.py
>>> ['1', '2', '3', '4', '5']

reduce的效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

轉換字符串爲int類型:

# str轉換爲int的函數def strtoint(s):
    # 首先要把str判斷下是否全是數字類型的字符,不作
    # 一個個字符轉換爲數字,而後數字列表
    l = map(int, s)
    # 數字列表變成int
    return reduce(numtoint, l)

def numtoint(a, b):
    return 10 * a + b

if __name__ == "__main__":
    print strtoint("356546")
    print isinstance(strtoint("356546"),int)
>>> C:\pythonTest>python mapAndreduce.py
>>> 356546>>> True

10.2.1 lambda函數

能夠用來寫單行函數,這樣當須要一個簡單的邏輯處理的時候就不用寫一個函數來處理,直接用lambda來處理
這樣能夠講上面的函數簡化一下:

# str轉換爲int的函數def strtoint(s):
    # 首先要把str判斷下是否全是數字類型的字符,不作
    # 一個個字符轉換爲數字,而後數字列表
    l = map(int, s)
    # 數字列表變成int
    return reduce(lambda x, y: 10 * x + y, l)

if __name__ == "__main__":
    print strtoint("356546")
    print isinstance(strtoint("356546"), int)

10.2.2練習

1.利用map()函數,把用戶輸入的不規範的英文名字,變爲首字母大寫,其餘小寫的規範名字。輸入:[‘adam’, ‘LISA’, ‘barT’],輸出:[‘Adam’, ‘Lisa’, ‘Bart’]。

if __name__ == "__main__":
    print map(lambda s:s[0].upper()+s[1:].lower(),['adam', 'LISA', 'barT'])
>>> C:\pythonTest>python exersize1.py
>>> ['Adam', 'Lisa', 'Bart']

2.Python提供的sum()函數能夠接受一個list並求和,請編寫一個prod()函數,能夠接受一個list並利用reduce()求積。

def prod(l):
    if not isinstance(l, list):
        return "錯誤的輸入參數類型"
    else:
        return reduce(lambda x, y: x + y, l)

if __name__ == "__main__":
    print prod([23,34,1,2])

10.3 filter

和map()相似,filter()也接收一個函數和一個序列。和map()不一樣的時,filter()把傳入的函數依次做用於每一個元素,而後根據返回值是True仍是False決定保留仍是丟棄該元素。

if __name__ == "__main__":
    print filter(lambda x: x % 2 == 0, range(1, 100))

10.4 sort

一般規定,對於兩個元素x和y,若是認爲x < y,則返回-1,若是認爲x == y,則返回0,若是認爲x > y,則返回1,這樣,排序算法就不用關心具體的比較過程,而是根據比較結果直接排序。所以咱們須要改寫排序算法的時候

倒序排列的函數

def revert(x, y):
    if x > y:
        return -1
    elif x == y:
        return 0
    else:
        return 1


if __name__ == "__main__":
    print sorted([34, 67, 89, 32, 56, 23, 12, 567, 3], revert)
>>> C:\pythonTest>python  filter.py
>>> [567, 89, 67, 56, 34, 32, 23, 12, 3]

11高級函數

11.1匿名函數

若是不須要馬上求和,而是在後面的代碼中,根據須要再計算怎麼辦?能夠不返回求和的結果,而是返回求和的函數!

def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

當咱們調用lazy_sum()時,返回的並非求和結果,而是求和函數:

>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function sum at 0x10452f668>

調用函數f時,才真正計算求和的結果:

>>> f()25

在這個例子中,咱們在函數lazy_sum中又定義了函數sum,而且,內部函數sum能夠引用外部函數lazy_sum的參數和局部變量,當lazy_sum返回函數sum時,相關參數和變量都保存在返回的函數中,這種稱爲「閉包(Closure)」的程序結構擁有極大的威力。

請再注意一點,當咱們調用lazy_sum()時,每次調用都會返回一個新的函數,即便傳入相同的參數:

>>> f1 = lazy_sum(1, 3, 5, 7, 9)
>>> f2 = lazy_sum(1, 3, 5, 7, 9)
>>> f1==f2
False

f1()和f2()的調用結果互不影響。

11.2裝飾器

我本身的理解:
後面跟一個函數,會將下面的函數給@後面的函數做爲參數。
裝飾器要有一個內部函數,將須要的邏輯作處理以後將函數返回,最後返回的是裝飾器。

def log(func):
    def wrapper(*args, **kw):
        print 'call %s():' % func.__name__
        return func(*args, **kw)
    return wrapper

@logdef sum():
    print "lishuai"


if __name__ == "__main__":
    sum()

12模塊

在Python中,一個.py文件就稱之爲一個模塊(Module)
爲了不模塊名衝突,Python又引入了按目錄來組織模塊的方法,稱爲包(Package)。
1)爲何要有 模塊和包?
便於組織代碼,同時避免衝突。

2)怎樣表示一個包?
每個包目錄下面都會有一個init.py的文件,這個文件是必須存在的,不然,Python就把這個目錄當成普通目錄,而不是一個包。init.py能夠是空文件,也能夠有Python代碼,由於init.py自己就是一個模塊,而它的模塊名就是mycompany。

3)怎樣肯定模塊的名字?
包名+模塊的名字

12.1使用模塊

12.1.1直接在命令行使用

if __name__=='__main__':
    test()
當咱們在命令行運行hello模塊文件時,Python解釋器把一個特殊變量__name__置爲__main__,而若是在其餘地方導入該hello模塊時,if判斷將失敗,所以,這種if測試可讓一個模塊經過命令行運行時執行一些額外的代碼,最多見的就是運行測試。

12.1.2使用別名導入模塊

好處是能夠根據實際狀況選擇庫

try:
    import cStringIO as StringIO
except ImportError: # 導入失敗會捕獲到ImportError
    import StringIO

在一個模塊中,咱們可能會定義不少函數和變量,但有的函數和變量咱們但願給別人使用,有的函數和變量咱們但願僅僅在模塊內部使用。在Python中,是經過_前綴來實現的。

正常的函數和變量名是公開的(public),能夠被直接引用,好比:abc,x123,PI等;

相似xxx這樣的變量是特殊變量,能夠被直接引用,可是有特殊用途,好比上面的authorname就是特殊變量,hello模塊定義的文檔註釋也能夠用特殊變量doc訪問,咱們本身的變量通常不要用這種變量名;

相似_xxx和xxx這樣的函數或變量就是非公開的(private),不該該被直接引用,好比_abc,abc等;

之因此咱們說,private函數和變量「不該該」被直接引用,而不是「不能」被直接引用,是由於Python並無一種方法能夠徹底限制訪問private函數或變量,可是,從編程習慣上不該該引用private函數或變量。

12.2模塊的搜索路徑

默認狀況下,Python解釋器會搜索當前目錄、全部已安裝的內置模塊和第三方模塊,搜索路徑存放在sys模塊的path變量中:

>>> import sys
>>> sys.path
['', '/usr/lib64/python26.zip', '/usr/lib64/python2.6', '/usr/lib64/python2.6/plat-linux2', '/usr/lib64/python2.6/lib-tk', '/usr/lib64/python2.6/lib-old', '/usr/lib64/python2.6/lib-dynload', '/usr/lib64/python2.6/site-packages', '/usr/lib/python2.6/site-packages']
>>>

若是咱們要添加本身的搜索目錄,有兩種方法:

一是直接修改sys.path,添加要搜索的目錄:

>>> import sys
>>> sys.path.append('/Users/michael/my_py_scripts')

這種方法是在運行時修改,運行結束後失效。

第二種方法是設置環境變量PYTHONPATH,該環境變量的內容會被自動添加到模塊搜索路徑中。設置方式與設置Path環境變量相似。注意只須要添加你本身的搜索路徑,Python本身自己的搜索路徑不受影響。???

相關文章
相關標籤/搜索