python面試必問 知識整理

 

 

一 數據類型

1 數字

整型與浮點型html

 
#整型int   做用:年紀,等級,身份證號,qq號等整型數字相關   定義:     age=10 #本質age=int(10) #浮點型float   做用:薪資,身高,體重,體質參數等浮點數相關 salary=3000.3 #本質salary=float(3000.3) #二進制,十進制,八進制,十六進制 
 

其餘數字類型(瞭解)python

 
#長整形(瞭解)  在python2中(python3中沒有長整形的概念):       >>> num=2L >>> type(num) <type 'long'> #複數(瞭解)   >>> x=1-2j >>> x.real 1.0 >>> x.imag -2.0  
 
 

2 字符串

 
#做用:名字,性別,國籍,地址等描述信息 #定義:在單引號\雙引號\三引號內,由一串字符組成 name='egon' #優先掌握的操做: 按索引取值(正向取+反向取) :只能取 切片(顧頭不顧尾,步長) 長度len 成員運算in和not in 
移除空白strip 切分split
循環
 

 

3 列表

 
#做用:多個裝備,多個愛好,多門課程,多個女友等 #定義:[]內能夠有多個任意類型的值,逗號分隔 my_girl_friends=['laoyi','laoer','laosan',4,5] #本質my_girl_friends=list([...]) 或 l=list('abc') #優先掌握的操做: 按索引存取值(正向存取+反向存取):便可存也能夠取 切片(顧頭不顧尾,步長) 長度 成員運算in和not in 
追加 刪除 循環
 
 
#ps:反向步長 l=[1,2,3,4,5,6] #正向步長 l[0:3:1] #[1, 2, 3] #反向步長 l[2::-1] #[3, 2, 1] #列表翻轉 l[::-1] #[6, 5, 4, 3, 2, 1]
 

 

4 元組

 
#做用:存多個值,對比列表來講,元組不可變(是能夠當作字典的key的),主要是用來讀 #定義:與列表類型比,只不過[]換成() age=(11,22,33,44,55)本質age=tuple((11,22,33,44,55)) #優先掌握的操做: 按索引取值(正向取+反向取):只能取 切片(顧頭不顧尾,步長) 長度 成員運算in和not in 循環
 

 

5 字典

 
#做用:存多個值,key-value存取,取值速度快 #定義:key必須是不可變類型,value能夠是任意類型 info={'name':'laoyi','age':18,'sex':'male'} #本質info=dict({....}) 或 info=dict(name='laoyi',age=18,sex='male') 或 info=dict([['name','laoyi'],('age',18)]) 或 {}.fromkeys(('name','age','sex'),None) #優先掌握的操做: 按key存取值:可存可取 長度len 成員運算in和not in 刪除 鍵keys(),值values(),鍵值對items() 循環
 

 

 #利用setdefault解決重複賦值 ''' setdefault的功能 1:key存在,則不賦值,key不存在則設置默認值 2:key存在,返回的是key對應的已有的值,key不存在,返回的則是要設置的默認值 d={} print(d.setdefault('a',1)) #返回1 d={'a':2222} print(d.setdefault('a',1)) #返回2222 ''' s='hello alex alex say hello sb sb' dic={} words=s.split() for word in words: #word='alex'  dic.setdefault(word,s.count(word)) print(dic) #利用集合,去掉重複,減小循環次數 s='hello laoda laoda say hello sb sb' dic={} words=s.split() words_set=set(words) for word in words_set: dic[word]=s.count(word) print(dic)
 
 

6 集合 

 
#做用:去重,關係運算, #定義:  知識點回顧 可變類型是不可hash類型 不可變類型是可hash類型 #定義集合:  集合:能夠包含多個元素,用逗號分割, 集合的元素遵循三個原則: 1:每一個元素必須是不可變類型(可hash,可做爲字典的key) 2:沒有重複的元素 3:無序 注意集合的目的是將不一樣的值存放到一塊兒,不一樣的集合間用來作關係運算,無需糾結於集合中單個值 #優先掌握的操做: 長度len 成員運算in和not in |合集 &交集 -差集 ^對稱差集 == >,>= ,<,<= 父集,子集 
 

 

7 數據類型總結

按存儲空間的佔用分(從低到高)程序員

數字
字符串
集合:無序,即無序存索引相關信息
元組:有序,須要存索引相關信息,不可變
列表:有序,須要存索引相關信息,可變,須要處理數據的增刪改
字典:無序,須要存key與value映射的相關信息,可變,須要處理數據的增刪改

按存值個數區分web

標量/原子類型 數字,字符串
容器類型 列表,元組,字典

 

 

按可變不可變區分算法

可變 列表,字典
不可變 數字,字符串,元組

 

 

按訪問順序區分shell

直接訪問 數字
順序訪問(序列類型) 字符串,列表,元組
key值訪問(映射類型) 字典

 

 

  

 

二 匿名函數

1. 什麼是匿名函數?數據庫

 
匿名就是沒有名字
def func(x,y,z=1): return x+y+z 匿名 lambda x,y,z=1:x+y+z #與函數有相同的做用域,可是匿名意味着引用計數爲0,使用一次就釋放,除非讓其有名字 func=lambda x,y,z=1:x+y+z func(1,2,3) #讓其有名字就沒有意義

匿名函數有個限制,就是隻能有一個表達式,不用寫,返回值就是該表達式的結果。
return
 

2. 有名字的函數與匿名函數的對比express

#有名函數與匿名函數的對比 有名函數:循環使用,保存了名字,經過名字就能夠重複引用函數功能 匿名函數:一次性使用,隨時隨時定義 應用:max,min,sorted,map,reduce,filter
它語法簡單,簡化代碼,不會產生命名衝突,污染命名空間。即用即拋。
 

三 閉包,裝飾器、生成器、迭代器

閉包

一 什麼是閉包?
 
#內部函數包含對外部做用域而非全局做用域的引用 #提示:以前咱們都是經過參數將外部的值傳給函數,閉包提供了另一種思路 def counter(): n=0 def incr(): nonlocal n x=n n+=1 return x return incr c=counter() print(c()) print(c()) print(c()) print(c.__closure__[0].cell_contents) #查看閉包的元素
 
二 閉包的意義與應用
 
#閉包的意義:返回的函數對象,不只僅是一個函數對象,在該函數外還包裹了一層做用域,這使得,該函數不管在何處調用,優先使用本身外層包裹的做用域 #應用領域:延遲計算(原來咱們是傳參,如今咱們是包起來) from urllib.request import urlopen def index(url): def get(): return urlopen(url).read() return get baidu=index('http://www.baidu.com') print(baidu().decode('utf-8'))
 

裝飾器

裝飾器就是閉包函數的一種應用場景編程

1 爲什麼要用裝飾器
#開放封閉原則:對修改封閉,對擴展開放
2 什麼是裝飾器
裝飾器他人的器具,自己能夠是任意可調用對象,被裝飾者也能夠是任意可調用對象。
強調裝飾器的原則:1 不修改被裝飾對象的源代碼 2 不修改被裝飾對象的調用方式 裝飾器的目標:在遵循1和2的前提下,爲被裝飾對象添加上新功能
3 裝飾器的使用
import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper

@timmer
def foo():
    time.sleep(3)
    print('from foo')
foo()
無參裝飾器
def auth(driver='file'):
    def auth2(func):
        def wrapper(*args,**kwargs):
            name=input("user: ")
            pwd=input("pwd: ")

            if driver == 'file':
                if name == 'egon' and pwd == '123':
                    print('login successful')
                    res=func(*args,**kwargs)
                    return res
            elif driver == 'ldap':
                print('ldap')
        return wrapper
    return auth2

@auth(driver='file')
def foo(name):
    print(name)

foo('egon')
有參裝飾器

 

4 裝飾器語法
 
被裝飾函數的正上方,單獨一行
        @deco1
        @deco2
        @deco3
        def foo(): pass foo=deco1(deco2(deco3(foo)))
 
5 裝飾器補充:wraps
 
from functools import wraps def deco(func): @wraps(func) #加在最內層函數正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @deco def index(): '''哈哈哈哈''' print('from index') print(index.__doc__)
 

迭代器

1 迭代的概念瀏覽器

 
#迭代是一個重複的過程,每次重複即一次迭代,而且每次迭代的結果都是下一次迭代的初始值 while True: #只是單純地重複,於是不是迭代 print('===>') l=[1,2,3] count=0 while count < len(l): #迭代 print(l[count]) count+=1
 

2 爲什麼要有迭代器?什麼是可迭代對象?什麼是迭代器對象?


#一、爲什麼要有迭代器? 對於序列類型:字符串、列表、元組,咱們可使用索引的方式迭代取出其包含的元素。但對於字典、集合、文件等類型是沒有索引的,若還想取出其內部包含的元素,則必須找出一種不依賴於索引的迭代方式,這就是迭代器 #二、什麼是可迭代對象? 可迭代對象指的是內置有__iter__方法的對象,即obj.__iter__,以下 'hello'.__iter__ (1,2,3).__iter__ [1,2,3].__iter__ {'a':1}.__iter__ {'a','b'}.__iter__ open('a.txt').__iter__ #三、什麼是迭代器對象? 可迭代對象執行obj.__iter__()獲得的結果就是迭代器對象 而迭代器對象指的是即內置有__iter__又內置有__next__方法的對象 文件類型是迭代器對象 open('a.txt').__iter__() open('a.txt').__next__() #四、注意: 迭代器對象必定是可迭代對象,而可迭代對象不必定是迭代器對象
 

3 迭代器對象的使用


dic={'a':1,'b':2,'c':3} iter_dic=dic.__iter__() #獲得迭代器對象,迭代器對象即有__iter__又有__next__,可是:迭代器.__iter__()獲得的仍然是迭代器自己 iter_dic.__iter__() is iter_dic #True print(iter_dic.__next__()) #等同於next(iter_dic) print(iter_dic.__next__()) #等同於next(iter_dic) print(iter_dic.__next__()) #等同於next(iter_dic) # print(iter_dic.__next__()) #拋出異常StopIteration,或者說結束標誌 #有了迭代器,咱們就能夠不依賴索引迭代取值了 iter_dic=dic.__iter__() while 1: try: k=next(iter_dic) print(dic[k]) except StopIteration: break #這麼寫太醜陋了,須要咱們本身捕捉異常,控制next,python這麼牛逼,能不能幫我解決呢?能,請看for循環
 

4 for循環

 
#基於for循環,咱們能夠徹底再也不依賴索引去取值了 dic={'a':1,'b':2,'c':3} for k in dic: print(dic[k]) #for循環的工做原理 #1:執行in後對象的dic.__iter__()方法,獲得一個迭代器對象iter_dic #2: 執行next(iter_dic),將獲得的值賦值給k,而後執行循環體代碼 #3: 重複過程2,直到捕捉到異常StopIteration,結束循環
 

5 迭代器的優缺點

#優勢: - 提供一種統一的、不依賴於索引的迭代方式 - 惰性計算,節省內存 #缺點: - 沒法獲取長度(只有在next完畢才知道到底有幾個值) - 一次性的,只能日後走,不能往前退

 生成器

1 什麼是生成器

 
#只要函數內部包含有yield關鍵字,那麼函數名()的到的結果就是生成器,而且不會執行函數內部代碼 def func(): print('====>first') yield 1 print('====>second') yield 2 print('====>third') yield 3 print('====>end') g=func() print(g) #<generator object func at 0x0000000002184360> 
 

2 生成器就是迭代器

g.__iter__ g.__next__ #二、因此生成器就是迭代器,所以能夠這麼取值 res=next(g) print(res)

3 生成器表達式

 
#一、把列表推導式的[]換成()就是生成器表達式 #二、示例:生一筐雞蛋變成給你一隻老母雞,用的時候就下蛋,這也是生成器的特性 >>> chicken=('雞蛋%s' %i for i in range(5)) >>> chicken <generator object <genexpr> at 0x10143f200> >>> next(chicken) '雞蛋0' >>> list(chicken) #因chicken可迭代,於是能夠轉成列表 ['雞蛋1', '雞蛋2', '雞蛋3', '雞蛋4',] #三、優勢:省內存,一次只產生一個值在內存中
 

四 內置函數、高階函數

內置函數 參考:https://docs.python.org/3/library/functions.html?highlight=built#ascii

高階函數

sorted

  排序算法


排序也是在程序中常常用到的算法。不管使用冒泡排序仍是快速排序,排序的核心是比較兩個元素的大小。
若是是數字,咱們能夠直接比較,但若是是字符串或者兩個dict呢?直接比較數學上的大小是沒有意義的,所以,比較的過程必須經過函數抽象出來。
一般規定,對於兩個元素x和y,若是認爲x < y,則返回-1,若是認爲x == y,則返回0,若是認爲x > y,則返回1,這樣,排序算法就不用關心具體的比較過程,而是根據比較結果直接排序。 Python內置的sorted()函數就能夠對list進行排序: >>> sorted([36, 5, 12, 9, 21]) [5, 9, 12, 21, 36] 此外,sorted()函數也是一個高階函數,它還能夠接收一個比較函數來實現自定義的排序。好比,若是要倒序排序,咱們就能夠自定義一個reversed_cmp函數: 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(['bob', 'about', 'Zoo', 'Credit']) ['Credit', 'Zoo', 'about', 'bob'] 默認狀況下,對字符串排序,是按照ASCII的大小比較的,因爲'Z' < 'a',結果,大寫字母Z會排在小寫字母a的前面。 如今,咱們提出排序應該忽略大小寫,按照字母序排序。要實現這個算法,沒必要對現有代碼大加改動,只要咱們能定義出忽略大小寫的比較算法就能夠: def cmp_ignore_case(s1, s2): u1 = s1.upper() u2 = s2.upper() if u1 < u2: return -1 if u1 > u2: return 1 return 0 忽略大小寫來比較兩個字符串,實際上就是先把字符串都變成大寫(或者都變成小寫),再比較。 這樣,咱們給sorted傳入上述比較函數,便可實現忽略大小寫的排序: >>> sorted(['bob', 'about', 'Zoo', 'Credit'], cmp_ignore_case) ['about', 'bob', 'Credit', 'Zoo'] 從上述例子能夠看出,高階函數的抽象能力是很是強大的,並且,核心代碼能夠保持得很是簡潔。

 

 

map/reduce

map()函數接收兩個參數,一個是函數,一個是Iterable,map將傳入的函數依次做用到序列的每一個元素,並把結果做爲新的Iterator返回。
舉例說明,好比咱們有一個函數f(x)=x2,要把這個函數做用在一個list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就能夠用map()實現以下:
如今,咱們用Python代碼實現:
>>> def f(x):
...     return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
map()傳入的第一個參數是f,即函數對象自己。因爲結果r是一個Iterator,Iterator是惰性序列,所以經過list()函數讓它把整個序列都計算出來並返回一個list。
L = []
for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]:
    L.append(f(n))
print(L)

map()做爲高階函數,事實上它把運算規則抽象了,所以,咱們不但能夠計算簡單的f(x)=x2,還能夠計算任意複雜的函數,好比,把這個list全部數字轉爲字符串:

>>> list(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)
比方說對一個序列求和,就能夠用reduce實現:
>>> from functools import reduce
>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25
固然求和運算能夠直接用Python內建函數sum(),不必動用reduce。

可是若是要把序列[1, 3, 5, 7, 9]變換成整數13579,reduce就能夠派上用場:

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

這個例子自己沒多大用處,可是,若是考慮到字符串str也是一個序列,對上面的例子稍加改動,配合map(),咱們就能夠寫出把str轉換爲int的函數:

>>> from functools import reduce
>>> 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

整理成一個str2int的函數就是:

from functools import reduce

def str2int(s):
    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]
    return reduce(fn, map(char2num, s))

還能夠用lambda函數進一步簡化成:

from functools import reduce

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]

def str2int(s):
    return reduce(lambda x, y: x * 10 + y, map(char2num, s))

也就是說,假設Python沒有提供int()函數,你徹底能夠本身寫一個把字符串轉化爲整數的函數,並且只須要幾行代碼!

五 列表推導式

二 列表推導式

#一、示例
egg_list=[]
for i in range(10):
    egg_list.append('雞蛋%s' %i)

egg_list=['雞蛋%s' %i for i in range(10)]

#二、語法
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
]
相似於
res=[]
for item1 in iterable1:
    if condition1:
        for item2 in iterable2:
            if condition2
                ...
                for itemN in iterableN:
                    if conditionN:
                        res.append(expression)

#三、優勢:方便,改變了編程習慣,可稱之爲聲明式編程
 

 

 

六 and-or , True -False

其一, 在不加括號時候, and優先級大於or
其二, x or y 的值只多是x或y. x爲真就是x, x爲假就是y
第三, x and y 的值只多是x或y. x爲真就是y, x爲假就是x
顯然,對於, 1 or 5 and 4: 先算5 and 4, 5爲真, 值爲4. 再算1 or 4, 1 爲真,值爲1
對於, (1 or 5) and 4: 先算1 or 5, 1爲真, 值爲1. 再算1 and 4, 1爲真,值爲4

求值技巧

關於求值的順序,先左部,再右部,還要加入「短路」機制,說明這點的文檔原文: 
對應同一優先級,我我的的理解爲:or的目的是找到做用範圍內第一個True或最後一個False,and的目的是找到做用範圍第一個False或最後一個True。(其中,做用範圍內的概念必須明確)。
#對於and而言,第一行返回(做用範圍內)第一個假值,第二行返回最後一個正值
#對於or而言,第一行返回(做用範圍內)第一個真值,第二行返回最後一個假值
 

 

七 多進程多線程

這個說實話,我三言兩語無法說清,因此我只能po上老師的博客了:

http://www.cnblogs.com/linhaifeng/articles/6817679.html

八 GIL鎖

GIL鎖
GIL鎖並非PYTHON的特性,是在實現cpython解釋器的時候引入的一個概念,
python徹底能夠不依賴GIL


一個防止   多線程併發執行機器碼的一個互斥鎖

爲何會有GIL鎖


因爲物理上的限制,cpu廠商在覈心頻率上的比賽被多核取代,爲了更有效的利用多喝處理器的性能,
就出現了多線程的編程方式,隨之帶來的問題就是線程間數據一致性和狀態同步的困難
即便在cpu內部的緩存也不例外,

python固然也逃不開,爲了利用多核,python開始支持多線程。而解決多線程之間數據完整性和狀態同步的最簡單方法就是枷鎖。
因此就有了GIL這把超級大鎖,而當愈來愈多代碼庫開發者,接收了這種設定以後,開始大量依賴這樣特性(即默認線程安全)

但是慢慢的這種方式被發現是蛋疼並且低效的,當你們視圖去拆分和去除GIL的時候,發現大量庫的開發組已經中毒依賴GIL並且很難去除了


總結:
由於GIL的存在,只有IO密集型的場景下,多線程會獲得較好的性能
若是對計算性能較高的程序能夠考慮把核心部分換成或者用其餘語言實現

 

九 os模塊,sys模塊,time,datetime模塊

os就是一個普通的python庫,用來向Python程序提供運行環境,特別是在文件系統、建立新進程、獲取操做系統自己的一些信息(好比uname),並屏蔽各類不一樣操做系統之間的細節差別。

sys模塊則是python程序用來請求解釋器行爲的接口。
好比關於調試類的(trace, frames,
except)等,profiling類(stats, getsizeof),運行時環境類(python path, stderr, stdout),解釋器自己(如version)
。inspect某種程度上能夠當作是在sys提供的功能上的一個包裝。

 

OS模塊

os.getcwd() 獲取當前工做目錄,即當前python腳本工做的目錄路徑
os.chdir("dirname")  改變當前腳本工做目錄;至關於shell下cd
os.curdir  返回當前目錄: ('.')
os.pardir  獲取當前目錄的父目錄字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多層遞歸目錄
os.removedirs('dirname1')    若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推
os.mkdir('dirname')    生成單級目錄;至關於shell中mkdir dirname
os.rmdir('dirname')    刪除單級空目錄,若目錄不爲空則沒法刪除,報錯;至關於shell中rmdir dirname
os.listdir('dirname')    列出指定目錄下的全部文件和子目錄,包括隱藏文件,並以列表方式打印
os.remove()  刪除一個文件
os.rename("oldname","newname")  重命名文件/目錄
os.stat('path/filename')  獲取文件/目錄信息
os.sep    輸出操做系統特定的路徑分隔符,win下爲"\\",Linux下爲"/"
os.linesep    輸出當前平臺使用的行終止符,win下爲"\t\n",Linux下爲"\n"
os.pathsep    輸出用於分割文件路徑的字符串 win下爲;,Linux下爲:
os.name    輸出字符串指示當前使用平臺。win->'nt'; Linux->'posix'
os.system("bash command")  運行shell命令,直接顯示
os.environ  獲取系統環境變量
os.path.abspath(path)  返回path規範化的絕對路徑
os.path.split(path)  將path分割成目錄和文件名二元組返回
os.path.dirname(path)  返回path的目錄。其實就是os.path.split(path)的第一個元素
os.path.basename(path)  返回path最後的文件名。如何path以/或\結尾,那麼就會返回空值。即os.path.split(path)的第二個元素
os.path.exists(path)  若是path存在,返回True;若是path不存在,返回False
os.path.isabs(path)  若是path是絕對路徑,返回True
os.path.isfile(path)  若是path是一個存在的文件,返回True。不然返回False
os.path.isdir(path)  若是path是一個存在的目錄,則返回True。不然返回False
os.path.join(path1[, path2[, ...]])  將多個路徑組合後返回,第一個絕對路徑以前的參數將被忽略
os.path.getatime(path)  返回path所指向的文件或者目錄的最後存取時間
os.path.getmtime(path)  返回path所指向的文件或者目錄的最後修改時間
os.path.getsize(path) 返回path的大小
os路徑處理

import os
#具體應用
import os,sys
possible_topdir = os.path.normpath(os.path.join(
    os.path.abspath(__file__),
    os.pardir, #上一級
    os.pardir,
    os.pardir
))
sys.path.insert(0,possible_topdir)

 

sys模塊

 sys.argv           命令行參數List,第一個元素是程序自己路徑
 sys.exit(n)        退出程序,正常退出時exit(0)
 sys.version        獲取Python解釋程序的版本信息
 sys.maxint         最大的Int值
 sys.path           返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
 sys.platform       返回操做系統平臺名稱

 

datetime模塊

在Python中,一般有這幾種方式來表示時間:

    時間戳(timestamp):一般來講,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量。咱們運行「type(time.time())」,返回的是float類型。
    格式化的時間字符串(Format String)
    結構化的時間(struct_time):struct_time元組共有9個元素共九個元素:(年,月,日,時,分,秒,一年中第幾周,一年中第幾天,夏令時)

 

 
 import time  #--------------------------咱們先以當前時間爲準,讓你們快速認識三種形式的時間 print(time.time()) # 時間戳:1487130156.419527  print(time.strftime("%Y-%m-%d %X")) #格式化的時間字符串:'2017-02-15 11:40:53'   print(time.localtime()) #本地時區的struct_time print(time.gmtime()) #UTC時區的struct_time 結構化時間
 

計算機認識的時間只能是'時間戳'格式,而程序員可處理的或者說人類能看懂的時間有: '格式化的時間字符串','結構化的時間' ,因而有了下圖的轉換關係

 
  #--------------------------按圖1轉換時間  # localtime([secs])  # 將一個時間戳轉換爲當前時區的struct_time。secs參數未提供,則以當前時間爲準。  time.localtime()  time.localtime(1473525444.037215)   # gmtime([secs]) 和localtime()方法相似,gmtime()方法是將一個時間戳轉換爲UTC時區(0時區)的struct_time。   # mktime(t) : 將一個struct_time轉化爲時間戳。  print(time.mktime(time.localtime()))#1473525749.0    # strftime(format[, t]) : 把一個表明時間的元組或者struct_time(如由time.localtime()和  # time.gmtime()返回)轉化爲格式化的時間字符串。若是t未指定,將傳入time.localtime()。若是元組中任何一個  # 元素越界,ValueError的錯誤將會被拋出。  print(time.strftime("%Y-%m-%d %X", time.localtime()))#2016-09-11 00:49:56   # time.strptime(string[, format])  # 把一個格式化時間字符串轉化爲struct_time。實際上它和strftime()是逆操做。  print(time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X'))  #time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6,  # tm_wday=3, tm_yday=125, tm_isdst=-1)  #在這個函數中,format默認爲:"%a %b %d %H:%M:%S %Y"。
 

 
1 #--------------------------按圖2轉換時間 2 # asctime([t]) : 把一個表示時間的元組或者struct_time表示爲這種形式:'Sun Jun 20 23:21:05 1993'。 3 # 若是沒有參數,將會將time.localtime()做爲參數傳入。 4 print(time.asctime())#Sun Sep 11 00:43:43 2016 5 6 # ctime([secs]) : 把一個時間戳(按秒計算的浮點數)轉化爲time.asctime()的形式。若是參數未給或者爲 7 # None的時候,將會默認time.time()爲參數。它的做用至關於time.asctime(time.localtime(secs))。 8 print(time.ctime()) # Sun Sep 11 00:46:38 2016 9 print(time.ctime(time.time())) # Sun Sep 11 00:46:38 2016
 
1 #--------------------------其餘用法 2 # sleep(secs) 3 # 線程推遲指定的時間運行,單位爲秒。

datetime

#時間加減
import datetime

# print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925
#print(datetime.date.fromtimestamp(time.time()) )  # 時間戳直接轉成日期格式 2016-08-19
# print(datetime.datetime.now() )
# print(datetime.datetime.now() + datetime.timedelta(3)) #當前時間+3天
# print(datetime.datetime.now() + datetime.timedelta(-3)) #當前時間-3天
# print(datetime.datetime.now() + datetime.timedelta(hours=3)) #當前時間+3小時
# print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #當前時間+30分


#
# c_time  = datetime.datetime.now()
# print(c_time.replace(minute=3,hour=2)) #時間替換

 

十 實例方法,靜態方法,類方法

首先:方法(method)和函數(function)有什麼區別?

函數是一段代碼,經過名字來進行調用。它能將一些數據(參數)傳遞進去進行處理,而後返回一些數據(返回值),也能夠沒有返回值。
全部傳遞給函數的數據都是顯式傳遞的。

方法也是一段代碼,也經過名字來進行調用,但它跟一個對象相關聯。方法和函數大體上是相同的,但有兩個主要的不一樣之處:
    1.方法中的數據是隱式傳遞的;
    2.方法能夠操做類內部的數據(請記住,對象是類的實例化–類定義了一個數據類型,而對象是該數據類型的一個實例化)

以上只是簡略的解釋,忽略了做用域之類的問題。

類中最經常使用到的方法是

實例方法(instance methods)

 即,實例對象做爲第一個參數傳遞給函數

例如,下面是一個基本的實例方法

class Kls(object):
    def __init__(self, data):
        self.data = data
 
    def printd(self):
        print(self.data)
 
ik1 = Kls('arun')
ik2 = Kls('seema')
 
ik1.printd()
ik2.printd()
獲得的輸出:

   arun
   seema
 

調用關係圖:

1/2 參數傳遞給函數
3   self參數指向實例自己 
4   咱們不須要顯式提供實例,解釋器自己會處理

假如咱們想僅實現類之間交互而不是經過實例?咱們能夠在類以外創建一個簡單的函數來實現這個功能,可是將會使代碼擴散到類以外,這個可能對將來代碼維護帶來問題。

例如:

def get_no_of_instances(cls_obj):
    return cls_obj.no_inst
 
class Kls(object):
    no_inst = 0
 
    def __init__(self):
        Kls.no_inst = Kls.no_inst + 1
 
ik1 = Kls()
ik2 = Kls()
 
print(get_no_of_instances(Kls))

2

The Python @classmethod   類方法

如今咱們要作的是在類裏建立一個函數,這個函數參數是類對象而不是實例對象.

在上面那個實現中,若是要實現不獲取實例,須要修改以下:

def iget_no_of_instance(ins_obj):
    return ins_obj.__class__.no_inst
 
class Kls(object):
    no_inst = 0
 
    def __init__(self):
        Kls.no_inst = Kls.no_inst + 1
 
ik1 = Kls()
ik2 = Kls()
print iget_no_of_instance(ik1)
 
結果
2

可使用Python2.2引入的新特性,使用@classmethod在類代碼中建立一個函數

class Kls(object):
    no_inst = 0
 
    def __init__(self):
        Kls.no_inst = Kls.no_inst + 1
 
    @classmethod
    def get_no_of_instance(cls_obj):
        return cls_obj.no_inst
 
ik1 = Kls()
ik2 = Kls()
 
print ik1.get_no_of_instance()
print Kls.get_no_of_instance()

2
2

The Python @staticmethod   靜態方法

一般,有不少狀況下一些函數與類相關,但不須要任何類或實例變量就能夠實現一些功能.

好比設置環境變量,修改另外一個類的屬性等等.這種狀況下,咱們也可使用一個函數,同樣會將代碼擴散到類以外(難以維護)

下面是一個例子:

IND = 'ON'
 
def checkind():
    return (IND == 'ON')
 
class Kls(object):
    def __init__(self,data):
        self.data = data
 
    def do_reset(self):
        if checkind():
            print('Reset done for:', self.data)
 
    def set_db(self):
        if checkind():
            self.db = 'new db connection'
            print('DB connection made for:',self.data)
 
ik1 = Kls(12)
ik1.do_reset()
ik1.set_db()

Reset done for: 12
DB connection made for: 12
 

如今咱們使用@staticmethod, 咱們能夠將全部代碼放到類中

IND = 'ON'
 
class Kls(object):
    def __init__(self, data):
        self.data = data
 
    @staticmethod
    def checkind():
        return (IND == 'ON')
 
    def do_reset(self):
        if self.checkind():
            print('Reset done for:', self.data)
 
    def set_db(self):
        if self.checkind():
            self.db = 'New db connection'
        print('DB connection made for: ', self.data)
 
ik1 = Kls(12)
ik1.do_reset()
ik1.set_db()

Reset done for: 12
DB connection made for: 12
 

@staticmethod and @classmethod   的不一樣

class Kls(object):
    def __init__(self, data):
        self.data = data
 
    def printd(self):
        print(self.data)
 
    @staticmethod
    def smethod(*arg):
        print('Static:', arg)
 
    @classmethod
    def cmethod(*arg):
        print('Class:', arg)

調用

>>> ik = Kls(23)
>>> ik.printd()
23
>>> ik.smethod()
Static: ()
>>> ik.cmethod()
Class: (,)
>>> Kls.printd()
TypeError: unbound method printd() must be called with Kls instance as first argument (got nothing instead)
>>> Kls.smethod()
Static: ()
>>> Kls.cmethod()
Class: (,)

 

十一 cookie和session的區別

1. 因爲HTTP協議是無狀態的協議,因此服務端須要記錄用戶的狀態時,就須要用某種機制來識具體的用戶。這個機制就是Session.典型的場景好比購物車,當你點擊下單按鈕時,因爲HTTP協議無狀態,因此並不知道是哪一個用戶操做的,因此服務端要爲特定的用戶建立了特定的Session,用用於標識這個用戶,而且跟蹤用戶。這樣才知道購物車裏面有幾本書。這個Session是保存在服務端的,有一個惟一標識。     在服務端保存Session的方法不少,內存、數據庫、文件都有。集羣的時候也要考慮Session的轉移,在大型的網站,通常會有專門的Session服務器集羣,用來保存用戶會話,這個時候 Session 信息都是放在內存的,使用一些緩存服務好比Memcached之類的來放 Session。2. 思考一下服務端如何識別特定的客戶?這個時候Cookie就登場了。每次HTTP請求的時候,客戶端都會發送相應的Cookie信息到服務端。實際上大多數的應用都是用 Cookie 來實現Session跟蹤的,第一次建立Session的時候,服務端會在HTTP協議中告訴客戶端,須要在 Cookie 裏面記錄一個Session ID,之後每次請求把這個會話ID發送到服務器,我就知道你是誰了。有人問,若是客戶端的瀏覽器禁用了 Cookie 怎麼辦?通常這種狀況下,會使用一種叫作URL重寫的技術來進行會話跟蹤,即每次HTTP交互,URL後面都會被附加上一個諸如 sid=xxxxx 這樣的參數,服務端據此來識別用戶。3. Cookie其實還能夠用在一些方便用戶的場景下,設想你某次登錄過一個網站,下次登陸的時候不想再次輸入帳號了,怎麼辦?這個信息能夠寫到Cookie裏面,訪問網站的時候,網站頁面的腳本能夠讀取這個信息,就自動幫你把用戶名給填了,可以方便一下用戶。這也是Cookie名稱的由來,給用戶的一點甜頭。因此,總結一下:Session是在服務端保存的一個數據結構,用來跟蹤用戶的狀態,這個數據能夠保存在集羣、數據庫、文件中;Cookie是客戶端保存用戶信息的一種機制,用來記錄用戶的一些信息,也是實現Session的一種方式。
相關文章
相關標籤/搜索