python學習簡要筆記整理

#學習自廖雪峯的博客

#解決中文編碼:
Import sys
reload(sys) 
sys.setdefaultencoding('utf8')


cmp(x,y), x<y retun -1,== 0, > 1 
#判斷類型:isinstance('abc', str) = Ture

類型轉換:
>>> int('123')
>>> int(12.34)
>>> float('12.34')
>>> str(1.23)
>>> unicode(100)
>>> bool(1)
>>> bool('')

a = abs,a 指向函數
a(-1) = 1

#數據類型:
#整形,浮點,字符串,布爾(Ture,False)     a='abc',a.replce(‘a’,'A')是創建一個新的字符串反回
#運算符:and,or,not
#集合類型:
#1,list:定義l= ['a','b'],list有序,可增減
#	 len(list),append('x'),insert(1,'x'),pop(),list[1] = 'x',l.sort()
#	切片訪問:l[0:3],l[-2:],前10個數,每兩個取一個:l[:10:2],也可用於字符串
#2,tuple:定義t=('a','b'),tuple和list一樣,但不可增刪改
#3,dict: 定義d = {'a'=1,'b'=2},訪問d['key'],不存在會報錯,所以'a'in d = Ture,d.get('a'),不存在返回None不報錯
#	d.pop('a')
#4,set:定義 s = set([1,2,3]),set和dict類似只存key值,發生重複會過濾掉

#列表生成公式:
>>> range(1, 11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

#兩個變量來生成list:
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.iteritems()]
['y=B', 'x=A', 'z=C']
#字符串變成小寫:
>>> L = ['Hello', 'World', 'IBM', 'Apple']
>>> [s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']


#列表生成器續:內建generator
#要創建一個generator,有很多種方法。第一種方法很簡單,只要把一個列表生成式的[]改成(),就創建了一個generator:
>>> L = [x * x for x in range(10)]生成list//如果[]變成(),則是生成generator,可用for遍歷
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))#g屬於gennerater型
>>> g
<generator object <genexpr> at 0x104feab40>



#函數:
#1,參數類型檢查:
def myf(x):
	if not instance(x, (int, float)):
		raise TypeError('type error!')
	
#2,多個返回值:定義默認參數要牢記一點:默認參數必須指向不變對象(非變量)!
def move(x,y,anlge=10):
	nx = x+math.cos(angle)
	ny = x+math.sin(angle)
	return nx,ny
nx,ny = move(4,6)#返回值兩個是tuple(),tuple正好可以x,y = ('x','y')這樣賦值


#3,不定個參數:*//最後的*p會獨立組裝成tuple
def myf(*p):
	sum = 0
	for n in p:
		sum = sum+p
	return sum

a = myf(3,4,56,3),如傳入l=[3,6,78] a=myf(*l)



#4,關鍵字參數:**//最後的**kw會獨立組裝成dict,
def person(name, age, **ky):
    print 'name:', name, 'age:', age, 'other:', kw

>>> kw = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **kw)//或者person('Jack', 24, city= 'Beijing', job='Engineer')
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

	
#5迭代:
#判斷能否用for ch in d 來迭代
>>> from collections import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代
True
>>> isinstance([1,2,3], Iterable) # list是否可迭代
True
>>> isinstance(123, Iterable) # 整數是否可迭代
False

>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
...     print x, y
...
1 1
2 4
3 9
#遍歷字典的kv,方法:iteritems()
>>> for k, v in d.iteritems():
...     print k, '=', v


#6高階函數:
#一個函數就可以接收另一個函數作爲參數
def add(x, y, f):
    return f(x) + f(y)

map:
>>> def f(x):
...     return x * x
...
>>> map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])#函數內對列表每個參數調用一次f函數,對外部只算一次
	[1, 4, 9, 16, 25, 36, 49, 64, 81]
	>>> map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])#轉換字符串
	['1', '2', '3', '4', '5', '6', '7', '8', '9']
#reduce:reduce把一個函數作用在一個序列[x1, x2, x3...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算
	reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

>>> def fn(x, y):
...     return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579


#map和reduce:把str轉換爲int的函數:
>>> def fn(x, y):
...     return x * 10 + y
...
>>> def char2num(s):
...     return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
...
>>> reduce(fn, map(char2num, '13579'))
13579


#filter:和map()不同的時,filter()把傳入的函數依次作用於每個元素,然後根據返回值是True還是False決定保留還是丟棄該元素。
#把一個序列中的空字符串刪掉:
def not_empty(s):
    return s and s.strip()
filter(not_empty, ['A', '', 'B', None, 'C', '  '])


#sorted:sorted()函數也是一個高階函數,它還可以接收一個比較函數來實現自定義的排序
def reversed_cmp(x, y):
    if x > y:
        return -1
    if x < y:
        return 1
    return 0
#傳入自定義的比較函數reversed_cmp,就可以實現倒序排序:

>>> sorted([36, 5, 12, 9, 21], reversed_cmp)
[36, 21, 12, 9, 5]

>>> sorted([36, 5, 12, 9, 21])
[5, 9, 12, 21, 36]


#返回函數、閉包函數:
#當一個函數返回了一個函數後,其內部的局部變量還被新函數引用
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()
>>> f1()
9
>>> f2()
9
>>> f3()
9
#返回閉包時牢記的一點就是:返回函數不要引用任何循環變量,或者後續會發生變化的變量。


#關鍵字lambda:表示匿名函數,關鍵字lambda表示匿名函數,冒號前面的x表示函數參數。
#匿名函數有個限制,就是隻能有一個表達式,不用寫return,返回值就是該表達式的結果。
lambda x:x*x 相當於:
def f(x):
    return x * x




#模塊:

#Python本身就內置了很多非常有用的模塊,只要安裝完畢,這些模塊就可以立刻使用。
import sys
#sys模塊有一個argv變量,用list存儲了命令行的所有參數。argv至少有一個元素,因爲第一個參數永遠是該.py文件的名稱
hello.py
if __name__=='__main__':
    test()
#當我們在命令行運行hello模塊文件時,Python解釋器把一個特殊變量__name__置爲__main__,而如果在其他地方導入該hello模塊時,
#if判斷將失敗,因此,這種if測試可以讓一個模塊通過命令行運行時執行一些額外的代碼,最常見的就是運行測試。


#訪問權限:
#__xxx__這樣的變量是特殊變量,可以被直接引用(public),但是有特殊用途
#_xxx雖然我可以被訪問,但是,請把我視爲私有變量,不要隨意訪問(public)
#_xxx和__xxx這樣的函數或變量就是非公開的(private)



#類:可以多繼承,其它特性類似java,如多態子類覆蓋父類方法
class student(object): #繼承object


#類型判斷:type
>>> import types
>>> type('abc')==types.StringType

isinstance:
>>> h = Husky()
>>> isinstance(h, Husky)
True
>>> isinstance('a', (str, unicode))
True


dir()
#如果要獲得一個對象的所有屬性和方法,可以使用dir()函數,它返回一個包含字符串的list

#類似__xxx__的屬性和方法在Python中都是有特殊用途的,比如__len__方法返回長度。在Python中,如果你調用len()函數試圖獲取一個對象的長度,
#實際上,在len()函數內部,它自動去調用該對象的__len__()方法,所以,下面的代碼是等價的:
>>> len('ABC')
3
>>> 'ABC'.__len__()
3


#配合getattr()、setattr()以及hasattr(),我們可以直接操作一個對象的狀態:
>>> getattr(obj, 'z', 404) # 獲取屬性'z',如果不存在,返回默認值404
404
>>> hasattr(obj, 'x') # 有屬性'x'嗎?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有屬性'y'嗎?
False
>>> setattr(obj, 'y', 19) # 設置一個屬性'y'
>>> hasattr(obj, 'y') # 有屬性'y'嗎?
True
>>> getattr(obj, 'y') # 獲取屬性'y'
19

#fn = getattr(obj, 'power') # 獲取屬性'power'並賦值到變量fn
#調用fn()



__slots__
#創建了一個class的實例後,我們可以給該實例綁定任何屬性和方法,這就是動態語言的靈活性
>>> class Student(object):
...     pass
...
>>> s = Student()
>>> s.name = 'Michael' # 動態給實例綁定一個屬性
>>> print s.name
Michael

>>> def set_age(self, age): # 定義一個函數作爲實例方法
...     self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s, Student) # 給實例綁定一個方法MethodType(方法名,實例,參數)
>>> s.set_age(25) # 調用實例方法
>>> s.age # 測試結果
25

#也可以對類綁定,這樣對所有實例起作用
>>> def set_score(self, score):
...     self.score = score
...
>>> Student.set_score = MethodType(set_score, None, Student)


#__slots__限制類的屬性:(__slots__定義的屬性僅對當前類起作用,對繼承的子類是不起作用的)
>>> class Student(object):
...     __slots__ = ('name', 'age') # 用tuple定義允許綁定的屬性名稱
...

#@property :通過getter和setter方法
class Student(object):

    @property
    def birth(self):
        return self._birth

    @birth.setter#只設置setter方法
    def birth(self, value):
        self._birth = value


#自定義類:

#__str__:(相當於java重寫toString()方法)
<__main__.Student object at 0x109afb190>
#打印出來的是字符串,實現__str__
>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...     def __str__(self):
...         return 'Student object (name: %s)' % self.name
...
>>> print Student('Michael')
Student object (name: Michael)

#__iter__:Python的for循環就會不斷調用該迭代對象的next()方法拿到循環的下一個值(像list和tuple)

class Student(object):
 def __init__(self):
        self.a, self.b = 0, 1 # 初始化兩個計數器a,b

    def __iter__(self):
        return self # 實例本身就是迭代對象,故返回自己

    def next(self):
        self.a, self.b = self.b, self.a + self.b # 計算下一個值
        if self.a > 100000: # 退出循環的條件
            raise StopIteration();
        return self.a # 返回下一個值

>>> for n in Fib():
...     print n
...
1
1
2
3
5
...
46368
75025

#__getitem__:(可像list一樣下標訪問)

class Sutdent(object):
    def __getitem__(self, n):
        a, b = 1, 1
        for x in range(n):
            a, b = b, a + b
        return a


#Python的內建模塊itertools提供了非常有用的用於操作迭代對象的函數


#__getattr__:(動態返回一個屬性、方法,實現後不存在就不報錯了,如果存在則不會執行自己實現的)
class Student(object):

    def __init__(self):
        self.name = 'Michael'

    def __getattr__(self, attr):
        if attr=='score':
            return 99

#函方法也可用
class Student(object):

    def __getattr__(self, attr):
        if attr=='age':
            return lambda: 25

>>> s.age()
25


__call__:
#任何類,只需要定義一個__call__()方法,就可以直接對實例進行調用。請看示例:

class Student(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
        print('My name is %s.' % self.name)
#調用方式如下:

>>> s = Student('Michael')
>>> s()
My name is Michael.


>>> callable(Student())
True


type():
#運行時創建類/元類:
#動態語言和靜態語言最大的不同,就是函數和類的定義,不是編譯時定義的,而是運行時動態創建的。
>>> Hello = type('Hello', (object,), dict(hello=fn)) # 創建Hello class
>>> h = Hello()
>>> h.hello()
Hello, world.
#1,class的名稱;
#2,繼承的父類集合,注意Python支持多重繼承,如果只有一個父類,別忘了tuple的單元素寫法;
#3,class的方法名稱與函數綁定,這裏我們把函數fn綁定到方法名hello上。


#metaclass:元類
#metaclass是Python面向對象裏最難理解,也是最難使用的魔術代碼。正常情況下,你不會碰到需要使用metaclass的情況,
#所以,以下內容看不懂也沒關係,因爲基本上你不會用到。




#常用內建模塊:
#namedtuple:
#看到(1, 2),很難看出這個tuple是用來表示一個座標的。
定義一個class又小題大做了
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(1, 2)
>>> p.x
1
>>> p.y
2
>>> isinstance(p, Point)
True
>>> isinstance(p, tuple)
True




#deque:

#使用list存儲數據時,按索引訪問元素很快,但是插入和刪除元素就很慢了,
#因爲list是線性存儲,數據量大的時候,插入和刪除效率很低。
#deque是爲了高效實現插入和刪除操作的雙向列表,適合用於隊列和棧:

>>> from collections import deque
>>> q = deque(['a', 'b', 'c'])
>>> q.append('x')
>>> q.appendleft('y')
>>> q
#deque(['y', 'a', 'b', 'c', 'x'])
#deque除了實現list的append()和pop()外,還支持appendleft()和popleft(),這樣就可以非常高效地往頭部添加或刪除元素。


#defaultdict
#使用dict時,如果引用的Key不存在,就會拋出KeyError。如果希望key不存在時,返回一個默認值,就可以用defaultdict:

>>> from collections import defaultdict
>>> dd = defaultdict(lambda: 'N/A')
>>> dd['key1'] = 'abc'
>>> dd['key1'] # key1存在
'abc'
>>> dd['key2'] # key2不存在,返回默認值
'N/A'

OrderedDict

#使用dict時,Key是無序的。在對dict做迭代時,我們無法確定Key的順序。
#如果要保持Key的順序,可以用OrderedDict:
>>> from collections import OrderedDict
>>> d = dict([('a', 1), ('b', 2), ('c', 3)])
>>> d # dict的Key是無序的
{'a': 1, 'c': 3, 'b': 2}
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od # OrderedDict的Key是有序的
OrderedDict([('a', 1), ('b', 2), ('c', 3)])


#OrderedDict可以實現一個FIFO(先進先出)的dict,當容量超出限制時,先刪除最早添加的Key:
#Counter是一個簡單的計數器,例如,統計字符出現的個數:



#多進程:
#multiprocessing模塊就是跨平臺版本的多進程模塊。
from multiprocessing import Process
import os

# 子進程要執行的代碼
def run_proc(name):
    print 'Run child process %s (%s)...' % (name, os.getpid())

if __name__=='__main__':
    print 'Parent process %s.' % os.getpid()
    p = Process(target=run_proc, args=('test',))
    print 'Process will start.'
    p.start()
    p.join()
    print 'Process end.'

#執行結果如下:

Parent process 928.
Process will start.
Run child process test (929)...
Process end.
#創建子進程時,只需要傳入一個執行函數和函數的參數,創建一個Process實例,用start()方法啓動,這樣創建進程比fork()還要簡單。
#join()方法可以等待子進程結束後再繼續往下運行(等),通常用於進程間的同步。



Pool:

#如果要啓動大量的子進程,可以用進程池的方式批量創建子進程:

from multiprocessing import Pool
import os, time, random

def long_time_task(name):
    print 'Run task %s (%s)...' % (name, os.getpid())
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print 'Task %s runs %0.2f seconds.' % (name, (end - start))

if __name__=='__main__':
    print 'Parent process %s.' % os.getpid()
    p = Pool()
    for i in range(5):
        p.apply_async(long_time_task, args=(i,))
    print 'Waiting for all subprocesses done...'
    p.close()
    p.join()
    print 'All subprocesses done.'



#Process之間肯定是需要通信的,操作系統提供了很多機制來實現進程間的通信。Python的multiprocessing模塊包裝了底層的機制,提供了Queue、Pipes等多種方式來交換數據。
#我們以Queue爲例,在父進程中創建兩個子進程,一個往Queue裏寫數據,一個從Queue裏讀數據:

from multiprocessing import Process, Queue
import os, time, random

# 寫數據進程執行的代碼:
def write(q):
    for value in ['A', 'B', 'C']:
        print 'Put %s to queue...' % value
        q.put(value)
        time.sleep(random.random())

# 讀數據進程執行的代碼:
def read(q):
    while True:
        value = q.get(True)
        print 'Get %s from queue.' % value

if __name__=='__main__':
    # 父進程創建Queue,並傳給各個子進程:
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 啓動子進程pw,寫入:
    pw.start()
    # 啓動子進程pr,讀取:
    pr.start()
    # 等待pw結束:
    pw.join()
    # pr進程裏是死循環,無法等待其結束,只能強行終止:
    pr.terminate()



#Python的標準庫提供了兩個模塊:thread和threading,thread是低級模塊,
#threading是高級模塊,對thread進行了封裝。絕大多數情況下,我們只需要使用threading這個高級模塊。
#啓動一個線程就是把一個函數傳入並創建Thread實例,然後調用start()開始執行:

#線程:
import time, threading

# 新線程執行的代碼:
def loop():
    print 'thread %s is running...' % threading.current_thread().name
    n = 0
    while n < 5:
        n = n + 1
        print 'thread %s >>> %s' % (threading.current_thread().name, n)
        time.sleep(1)
    print 'thread %s ended.' % threading.current_thread().name

print 'thread %s is running...' % threading.current_thread().name
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print 'thread %s ended.' % threading.current_thread().name
#執行結果如下:

thread MainThread is running...
thread LoopThread is running...
thread LoopThread >>> 1
thread LoopThread >>> 2
thread LoopThread >>> 3
thread LoopThread >>> 4
thread LoopThread >>> 5
thread LoopThread ended.

#線程枷鎖:
balance = 0
lock = threading.Lock()

def run_thread(n):
    for i in range(100000):
        # 先要獲取鎖:
        lock.acquire()
        try:
            # 放心地改吧:
            change_it(n)
        finally:
            # 改完了一定要釋放鎖:
            lock.release()
thread MainThread ended.



import threading



# 創建全局ThreadLocal對象:

#全局變量local_school就是一個ThreadLocal對象,每個Thread對它都可以讀寫student屬性,但互不影響。
#你可以把local_school看成全局變量,但每個屬性如local_school.student都是線程的局部變量,可以任意讀寫而互不干擾,也不用管理鎖的問題,ThreadLocal內部會處理。
#可以理解爲全局變量local_school是一個dict,不但可以用local_school.student,還可以綁定其他變量,如local_school.teacher等等。
#ThreadLocal最常用的地方就是爲每個線程綁定一個數據庫連接,HTTP請求,用戶身份信息等,這樣一個線程的所有調用到的處理函數都可以非常方便地訪問這些資源。
#local_school = threading.local()

def process_student():
    print 'Hello, %s (in %s)' % (local_school.student, threading.current_thread().name)

def process_thread(name):
    # 綁定ThreadLocal的student:
    local_school.student = name
    process_student()

t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()
執行結果:

Hello, Alice (in Thread-A)
Hello, Bob (in Thread-B)




#單元測試:
#需要引入Python自帶的unittest模塊,編寫mydict_test.py如下:
import unittest

from mydict import Dict

class TestDict(unittest.TestCase):

    def test_init(self):
        d = Dict(a=1, b='test')
        self.assertEquals(d.a, 1)
        self.assertEquals(d.b, 'test')
        self.assertTrue(isinstance(d, dict))



    def test_attr(self):
        d = Dict()
        d.key = 'value'
        self.assertTrue('key' in d)
        self.assertEquals(d['key'], 'value')

#以test開頭的方法就是測試方法,測試時纔會被執行
#一旦編寫好單元測試,我們就可以運行單元測試。最簡單的運行方式是在mydict_test.py的最後加上兩行代碼:

if __name__ == '__main__':
    unittest.main()

setUp與tearDown

#可以在單元測試中編寫兩個特殊的setUp()和tearDown()方法。這兩個方法會分別在每調用一個測試方法的前後分別被執行。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章