看兩個例子:html
a = 1
def fun(a):
a = 2
fun(a)
print a # 1
複製代碼
a = []
def fun(a):
a.append(1)
fun(a)
print a # [1]
複製代碼
全部的變量均可以理解是內存中一個對象的「引用」,或者,也能夠看似c中void*的感受。前端
經過id
來看引用a
的內存地址能夠比較理解:python
a = 1
def fun(a):
print "func_in",id(a) # func_in 41322472
a = 2
print "re-point",id(a), id(2) # re-point 41322448 41322448
print "func_out",id(a), id(1) # func_out 41322472 41322472
fun(a)
print a # 1
複製代碼
注:具體的值在不一樣電腦上運行時可能不一樣。mysql
能夠看到,在執行完a = 2
以後,a
引用中保存的值,即內存地址發生變化,由原來1
對象的所在的地址變成了2
這個實體對象的內存地址。linux
而第2個例子a
引用保存的內存值就不會發生變化:nginx
a = []
def fun(a):
print "func_in",id(a) # func_in 53629256
a.append(1)
print "func_out",id(a) # func_out 53629256
fun(a)
print a # [1]
複製代碼
這裏記住的是類型是屬於對象的,而不是變量。而對象有兩種,「可更改」(mutable)與「不可更改」(immutable)對象。在python中,strings, tuples, 和numbers是不可更改的對象,而 list, dict, set 等則是能夠修改的對象。(這就是這個問題的重點)git
當一個引用傳遞給函數的時候,函數自動複製一份引用,這個函數裏的引用和外邊的引用沒有半毛關係了.因此第一個例子裏函數把引用指向了一個不可變對象,當函數返回的時候,外面的引用沒半毛感受.而第二個例子就不同了,函數內的引用指向的是可變對象,對它的操做就和定位了指針地址同樣,在內存裏進行修改.程序員
若是還不明白的話,這裏有更好的解釋: stackoverflow.com/questions/9…github
這個很是的不經常使用,可是像ORM這種複雜的結構仍是會須要的,詳情請看:stackoverflow.com/questions/1…web
Python其實有3個方法,即靜態方法(staticmethod),類方法(classmethod)和實例方法,以下:
def foo(x):
print "executing foo(%s)"%(x)
class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)
@classmethod
def class_foo(cls,x):
print "executing class_foo(%s,%s)"%(cls,x)
@staticmethod
def static_foo(x):
print "executing static_foo(%s)"%x
a=A()
複製代碼
這裏先理解下函數參數裏面的self和cls.這個self和cls是對類或者實例的綁定,對於通常的函數來講咱們能夠這麼調用foo(x)
,這個函數就是最經常使用的,它的工做跟任何東西(類,實例)無關.對於實例方法,咱們知道在類裏每次定義方法的時候都須要綁定這個實例,就是foo(self, x)
,爲何要這麼作呢?由於實例方法的調用離不開實例,咱們須要把實例本身傳給函數,調用的時候是這樣的a.foo(x)
(實際上是foo(a, x)
).類方法同樣,只不過它傳遞的是類而不是實例,A.class_foo(x)
.注意這裏的self和cls能夠替換別的參數,可是python的約定是這倆,仍是不要改的好.
對於靜態方法其實和普通的方法同樣,不須要對誰進行綁定,惟一的區別是調用的時候須要使用a.static_foo(x)
或者A.static_foo(x)
來調用.
\ | 實例方法 | 類方法 | 靜態方法 |
---|---|---|---|
a = A() | a.foo(x) | a.class_foo(x) | a.static_foo(x) |
A | 不可用 | A.class_foo(x) | A.static_foo(x) |
類變量:
是可在類的全部實例之間共享的值(也就是說,它們不是單獨分配給每一個實例的)。例以下例中,num_of_instance 就是類變量,用於跟蹤存在着多少個Test 的實例。
實例變量:
實例化以後,每一個實例單獨擁有的變量。
class Test(object):
num_of_instance = 0
def __init__(self, name):
self.name = name
Test.num_of_instance += 1
if __name__ == '__main__':
print Test.num_of_instance # 0
t1 = Test('jack')
print Test.num_of_instance # 1
t2 = Test('lucy')
print t1.name , t1.num_of_instance # jack 2
print t2.name , t2.num_of_instance # lucy 2
複製代碼
補充的例子
class Person:
name="aaa"
p1=Person()
p2=Person()
p1.name="bbb"
print p1.name # bbb
print p2.name # aaa
print Person.name # aaa
複製代碼
這裏p1.name="bbb"
是實例調用了類變量,這其實和上面第一個問題同樣,就是函數傳參的問題,p1.name
一開始是指向的類變量name="aaa"
,可是在實例的做用域裏把類變量的引用改變了,就變成了一個實例變量,self.name再也不引用Person的類變量name了.
能夠看看下面的例子:
class Person:
name=[]
p1=Person()
p2=Person()
p1.name.append(1)
print p1.name # [1]
print p2.name # [1]
print Person.name # [1]
複製代碼
這個也是python彪悍的特性.
自省就是面向對象的語言所寫的程序在運行時,所能知道對象的類型.簡單一句就是運行時可以得到對象的類型.好比type(),dir(),getattr(),hasattr(),isinstance().
a = [1,2,3]
b = {'a':1,'b':2,'c':3}
c = True
print type(a),type(b),type(c) # <type 'list'> <type 'dict'> <type 'bool'>
print isinstance(a,list) # True
複製代碼
可能你見過列表推導時,卻沒有見過字典推導式,在2.7中才加入的:
d = {key: value for (key, value) in iterable}
複製代碼
>>> class MyClass():
... def __init__(self):
... self.__superprivate = "Hello"
... self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}
複製代碼
__foo__
:一種約定,Python內部的名字,用來區別其餘用戶自定義的命名,以防衝突,就是例如__init__()
,__del__()
,__call__()
這些特殊方法
_foo
:一種約定,用來指定變量私有.程序員用來指定私有變量的一種方式.不能用from module import * 導入,其餘方面和公有同樣訪問;
__foo
:這個有真正的意義:解析器用_classname__foo
來代替這個名字,以區別和其餘類相同的命名,它沒法直接像公有成員同樣隨便訪問,經過對象名._類名__xxx這樣的方式能夠訪問.
詳情見:這裏
.format在許多方面看起來更便利.對於%
最煩人的是它沒法同時傳遞一個變量和元組.你可能會想下面的代碼不會有什麼問題:
"hi there %s" % name
複製代碼
可是,若是name剛好是(1,2,3),它將會拋出一個TypeError異常.爲了保證它老是正確的,你必須這樣作:
"hi there %s" % (name,) # 提供一個單元素的數組而不是一個參數
複製代碼
可是有點醜..format就沒有這些問題.你給的第二個問題也是這樣,.format好看多了.
你爲何不用它?
%
(issue #4))stackoverflow.com/questions/5…
這個是stackoverflow裏python排名第一的問題,值得一看
這是中文版
這裏有個關於生成器的建立問題面試官有考: 問: 將列表生成式中[]改爲() 以後數據結構是否改變? 答案:是,從列表變爲生成器
>>> L = [x*x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x0000028F8B774200>
複製代碼
經過列表生成式,能夠直接建立一個列表。可是,受到內存限制,列表容量確定是有限的。並且,建立一個包含百萬元素的列表,不只是佔用很大的內存空間,如:咱們只須要訪問前面的幾個元素,後面大部分元素所佔的空間都是浪費的。所以,沒有必要建立完整的列表(節省大量內存空間)。在Python中,咱們能夠採用生成器:邊循環,邊計算的機制—>generator
*args
and **kwargs
用*args
和**kwargs
只是爲了方便並無強制使用它們.
當你不肯定你的函數裏將要傳遞多少參數時你能夠用*args
.例如,它能夠傳遞任意數量的參數:
>>> def print_everything(*args):
for count, thing in enumerate(args):
... print '{0}. {1}'.format(count, thing)
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage
複製代碼
類似的,**kwargs
容許你使用沒有事先定義的參數名:
>>> def table_things(**kwargs):
... for name, value in kwargs.items():
... print '{0} = {1}'.format(name, value)
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit
複製代碼
你也能夠混着用.命名參數首先得到參數值而後全部的其餘參數都傳遞給*args
和**kwargs
.命名參數在列表的最前端.例如:
def table_things(titlestring, **kwargs)
複製代碼
*args
和**kwargs
能夠同時在函數的定義中,可是*args
必須在**kwargs
前面.
當調用函數時你也能夠用*
和**
語法.例如:
>>> def print_three_things(a, b, c):
... print 'a = {0}, b = {1}, c = {2}'.format(a,b,c)
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat
複製代碼
就像你看到的同樣,它能夠傳遞列表(或者元組)的每一項並把它們解包.注意必須與它們在函數裏的參數相吻合.固然,你也能夠在函數定義或者函數調用時用*.
引自知乎
函數重載主要是爲了解決兩個問題。
另外,一個基本的設計原則是,僅僅當兩個函數除了參數類型和參數個數不一樣之外,其功能是徹底相同的,此時才使用函數重載,若是兩個函數的功能其實不一樣,那麼不該當使用重載,而應當使用一個名字不一樣的函數。
好吧,那麼對於狀況 1 ,函數功能相同,可是參數類型不一樣,python 如何處理?答案是根本不須要處理,由於 python 能夠接受任何類型的參數,若是函數的功能相同,那麼不一樣的參數類型在 python 中極可能是相同的代碼,沒有必要作成兩個不一樣函數。
那麼對於狀況 2 ,函數功能相同,但參數個數不一樣,python 如何處理?你們知道,答案就是缺省參數。對那些缺乏的參數設定爲缺省參數便可解決問題。由於你假設函數功能相同,那麼那些缺乏的參數終歸是須要用的。
好了,鑑於狀況 1 跟 狀況 2 都有了解決方案,python 天然就不須要函數重載了。
這個面試官問了,我說了老半天,不知道他問的真正意圖是什麼.
這篇文章很好的介紹了新式類的特性:
新式類很早在2.2就出現了,因此舊式類徹底是兼容的問題,Python3裏的類所有都是新式類.這裏有一個MRO問題能夠了解下(新式類繼承是根據C3算法,舊式類是深度優先),<Python核心編程>裏講的也不少.
一箇舊式類的深度優先的例子
class A():
def foo1(self):
print "A"
class B(A):
def foo2(self):
pass
class C(A):
def foo1(self):
print "C"
class D(B, C):
pass
d = D()
d.foo1()
# A
複製代碼
按照經典類的查找順序從左到右深度優先
的規則,在訪問d.foo1()
的時候,D這個類是沒有的..那麼往上查找,先找到B,裏面沒有,深度優先,訪問A,找到了foo1(),因此這時候調用的是A的foo1(),從而致使C重寫的foo1()被繞過
__new__
和__init__
的區別這個__new__
確實不多見到,先作了解吧.
__new__
是一個靜態方法,而__init__
是一個實例方法.__new__
方法會返回一個建立的實例,而__init__
什麼都不返回.__new__
返回一個cls的實例時後面的__init__
才能被調用.__new__
,初始化一個實例時用__init__
.ps: __metaclass__
是建立類時起做用.因此咱們能夠分別使用__metaclass__
,__new__
和__init__
來分別在類建立,實例建立和實例初始化的時候作一些小手腳.
單例模式是一種經常使用的軟件設計模式。在它的核心結構中只包含一個被稱爲單例類的特殊類。經過單例模式能夠保證系統中一個類只有一個實例並且該實例易於外界訪問,從而方便對實例個數的控制並節約系統資源。若是但願在系統中某個類的對象只能存在一個,單例模式是最好的解決方案。
__new__()
在__init__()
以前被調用,用於生成實例對象。利用這個方法和類的屬性的特色能夠實現設計模式的單例模式。單例模式是指建立惟一對象,單例模式設計的類只能實例 這個絕對常考啊.絕對要記住1~2個方法,當時面試官是讓手寫的.
__new__
方法class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
class MyClass(Singleton):
a = 1
複製代碼
建立實例時把全部實例的__dict__
指向同一個字典,這樣它們具備相同的屬性和方法.
class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob
class MyClass2(Borg):
a = 1
複製代碼
def singleton(cls):
instances = {}
def getinstance(*args, **kw):
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance
@singleton
class MyClass:
...
複製代碼
做爲python的模塊是自然的單例模式
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton()
# to use
from mysingleton import my_singleton
my_singleton.foo()
複製代碼
Python 中,一個變量的做用域老是由在代碼中被賦值的地方所決定的。
當 Python 遇到一個變量的話他會按照這樣的順序進行搜索:
本地做用域(Local)→當前做用域被嵌入的本地做用域(Enclosing locals)→全局/模塊做用域(Global)→內置做用域(Built-in)
線程全局鎖(Global Interpreter Lock),即Python爲了保證線程安全而採起的獨立線程運行的限制,說白了就是一個核只能在同一時間運行一個線程.對於io密集型任務,python的多線程起到做用,但對於cpu密集型任務,python的多線程幾乎佔不到任何優點,還有可能由於爭奪資源而變慢。
解決辦法就是多進程和下面的協程(協程也只是單CPU,可是能減少切換代價提高性能).
簡單點說協程是進程和線程的升級版,進程和線程都面臨着內核態和用戶態的切換問題而耗費許多切換時間,而協程就是用戶本身控制切換的時機,再也不須要陷入系統的內核態.
Python裏最多見的yield就是協程的思想!能夠查看第九個問題.
閉包(closure)是函數式編程的重要的語法結構。閉包也是一種組織代碼的結構,它一樣提升了代碼的可重複使用性。
當一個內嵌函數引用其外部做做用域的變量,咱們就會獲得一個閉包. 總結一下,建立一個閉包必須知足如下幾點:
感受閉包仍是有難度的,幾句話是說不明白的,仍是查查相關資料.
重點是函數運行後並不會被撤銷,就像16題的instance字典同樣,當函數運行完後,instance並不被銷燬,而是繼續留在內存空間裏.這個功能相似類裏的類變量,只不過遷移到了函數上.
閉包就像個空心球同樣,你知道外面和裏面,但你不知道中間是什麼樣.
其實就是一個匿名函數,爲何叫lambda?由於和後面的函數式編程有關.
推薦: 知乎
這個須要適當的瞭解一下吧,畢竟函數式編程在Python中也作了引用.
推薦: 酷殼
python中函數式編程支持:
filter 函數的功能至關於過濾器。調用一個布爾函數bool_func
來迭代遍歷每一個seq中的元素;返回一個使bool_seq
返回值爲true的元素的序列。
>>>a = [1,2,3,4,5,6,7]
>>>b = filter(lambda x: x > 5, a)
>>>print b
>>>[6,7]
複製代碼
map函數是對一個序列的每一個項依次執行函數,下面是對一個序列每一個項都乘以2:
>>> a = map(lambda x:x*2,[1,2,3])
>>> list(a)
[2, 4, 6]
複製代碼
reduce函數是對一個序列的每一個項迭代調用函數,下面是求3的階乘:
>>> reduce(lambda x,y:x*y,range(1,4))
6
複製代碼
引用和copy(),deepcopy()的區別
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始對象
b = a #賦值,傳對象的引用
c = copy.copy(a) #對象拷貝,淺拷貝
d = copy.deepcopy(a) #對象拷貝,深拷貝
a.append(5) #修改對象a
a[4].append('c') #修改對象a中的['a', 'b']數組對象
print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
輸出結果:
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]
複製代碼
Python垃圾回收機制:Python GC主要使用引用計數(reference counting)來跟蹤和回收垃圾。在引用計數的基礎上,經過「標記-清除」(mark and sweep)解決容器對象可能產生的循環引用問題,經過「分代回收」(generation collection)以空間換時間的方法提升垃圾回收效率。
PyObject是每一個對象必有的內容,其中ob_refcnt
就是作爲引用計數。當一個對象有新的引用時,它的ob_refcnt
就會增長,當引用它的對象被刪除,它的ob_refcnt
就會減小.引用計數爲0時,該對象生命就結束了。
優勢:
缺點:
基本思路是先按需分配,等到沒有空閒內存的時候從寄存器和程序棧上的引用出發,遍歷以對象爲節點、以引用爲邊構成的圖,把全部能夠訪問到的對象打上標記,而後清掃一遍內存空間,把全部沒標記的對象釋放。
分代回收的總體思想是:將系統中的全部內存塊根據其存活時間劃分爲不一樣的集合,每一個集合就成爲一個「代」,垃圾收集頻率隨着「代」的存活時間的增大而減少,存活時間一般利用通過幾回垃圾回收來度量。
Python默認定義了三代對象集合,索引數越大,對象存活時間越長。
舉例: 當某些內存塊M通過了3次垃圾收集的清洗以後還存活時,咱們就將內存塊M劃到一個集合A中去,而新分配的內存都劃分到集合B中去。當垃圾收集開始工做時,大多數狀況都只對集合B進行垃圾回收,而對集合A進行垃圾回收要隔至關長一段時間後才進行,這就使得垃圾收集機制須要處理的內存少了,效率天然就提升了。在這個過程當中,集合B中的某些內存塊因爲存活時間長而會被轉移到集合A中,固然,集合A中實際上也存在一些垃圾,這些垃圾的回收會由於這種分代的機制而被延遲。
都在循環時使用,xrange內存性能更好。 for i in range(0, 20): for i in xrange(0, 20): What is the difference between range and xrange functions in Python 2.X? range creates a list, so if you do range(1, 10000000) it creates a list in memory with 9999999 elements. xrange is a sequence object that evaluates lazily.
數據庫事務(Database Transaction) ,是指做爲單個邏輯工做單元執行的一系列操做,要麼徹底地執行,要麼徹底地不執行。 完全理解數據庫事務: www.hollischuang.com/archives/89…
彙集索引,非彙集索引,B-Tree,B+Tree,最左前綴原理
一般侷限點來講,Redis也以消息隊列的形式存在,做爲內嵌的List存在,知足實時的高併發需求。在使用緩存的時候,redis比memcached具備更多的優點,而且支持更多的數據類型,把redis看成一箇中間存儲系統,用來處理高併發的數據庫操做
悲觀鎖:假定會發生併發衝突,屏蔽一切可能違反數據完整性的操做
樂觀鎖:假設不會發生併發衝突,只在提交操做時檢查是否違反數據完整性。
全稱是Multi-Version Concurrent Control,即多版本併發控制,在MVCC協議下,每一個讀操做會看到一個一致性的snapshot,而且能夠實現非阻塞的讀。MVCC容許數據具備多個版本,這個版本能夠是時間戳或者是全局遞增的事務ID,在同一個時間點,不一樣的事務看到的數據是不一樣的。
innodb會爲每一行添加兩個字段,分別表示該行建立的版本和刪除的版本,填入的是事務的版本號,這個版本號隨着事務的建立不斷遞增。在repeated read的隔離級別(事務的隔離級別請看這篇文章)下,具體各類數據庫操做的實現:
其中,寫操做(insert、delete和update)執行時,須要將系統版本號遞增。
因爲舊數據並不真正的刪除,因此必須對這些數據進行清理,innodb會開啓一個後臺線程執行清理工做,具體的規則是將刪除版本號小於當前系統版本的行刪除,這個過程叫作purge。
經過MVCC很好的實現了事務的隔離性,能夠達到repeated read級別,要實現serializable還必須加鎖。
參考:MVCC淺析
MyISAM 適合於一些須要大量查詢的應用,但其對於有大量寫操做並非很好。甚至你只是須要update一個字段,整個表都會被鎖起來,而別的進程,就算是讀進程都沒法操做直到讀操做完成。另外,MyISAM 對於 SELECT COUNT(*) 這類的計算是超快無比的。
InnoDB 的趨勢會是一個很是複雜的存儲引擎,對於一些小的應用,它會比 MyISAM 還慢。他是它支持「行鎖」 ,因而在寫操做比較多的時候,會更優秀。而且,他還支持更多的高級應用,好比:事務。
mysql 數據庫引擎: MySQL存儲引擎--MyISAM與InnoDB區別:
注意: 中斷鏈接端能夠是客戶端,也能夠是服務器端. 下面僅以客戶端斷開鏈接舉例, 反之亦然.
地址解析協議(Address Resolution Protocol),其基本功能爲透過目標設備的IP地址,查詢目標的MAC地址,以保證通訊的順利進行。它是IPv4網絡層必不可少的協議,不過在IPv6中已再也不適用,並被鄰居發現協議(NDP)所替代。
這個面試官確實問過,當時答的urllib2能夠Post而urllib不能夠.
GET和POST有什麼區別?及爲何網上的多數答案都是錯的 知乎回答
get: RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1 post: RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1
Cookie | Session | |
---|---|---|
儲存位置 | 客戶端 | 服務器端 |
目的 | 跟蹤會話,也能夠保存用戶偏好設置或者保存用戶名密碼等 | 跟蹤會話 |
安全性 | 不安全 | 安全 |
session技術是要使用到cookie的,之因此出現session技術,主要是爲了安全。
nginx 相對 apache 的優勢:
apache 相對nginx 的優勢:
狀態碼 | 定義 |
---|---|
1xx 報告 | 接收到請求,繼續進程 |
2xx 成功 | 步驟成功接收,被理解,並被接受 |
3xx 重定向 | 爲了完成請求,必須採起進一步措施 |
4xx 客戶端出錯 | 請求包括錯的順序或不能完成 |
5xx 服務器出錯 | 服務器沒法完成顯然有效的請求 |
403: Forbidden 404: Not Found
HTTPS握手,對稱加密,非對稱加密,TLS/SSL,RSA
CSRF重點在請求,XSS重點在腳本
HTTP方法的冪等性是指一次和屢次請求某一個資源應該具備一樣的反作用。(注意是反作用)
GET http://www.bank.com/account/123456
,不會改變資源的狀態,不論調用一次仍是N次都沒有反作用。請注意,這裏強調的是一次和N次具備相同的反作用,而不是每次GET的結果相同。GET http://www.news.com/latest-news
這個HTTP請求可能會每次獲得不一樣的結果,但它自己並無產生任何反作用,於是是知足冪等性的。
DELETE方法用於刪除資源,有反作用,但它應該知足冪等性。好比:DELETE http://www.forum.com/article/4231
,調用一次和N次對系統產生的反作用是相同的,即刪掉id爲4231的帖子;所以,調用者能夠屢次調用或刷新頁面而沒必要擔憂引發錯誤。
POST所對應的URI並不是建立的資源自己,而是資源的接收者。好比:POST http://www.forum.com/articles
的語義是在http://www.forum.com/articles
下建立一篇帖子,HTTP響應中應包含帖子的建立狀態以及帖子的URI。兩次相同的POST請求會在服務器端建立兩份資源,它們具備不一樣的URI;因此,POST方法不具有冪等性。
PUT所對應的URI是要建立或更新的資源自己。好比:PUT http://www.forum/articles/4231
的語義是建立或更新ID爲4231的帖子。對同一URI進行屢次PUT的反作用和一次PUT是相同的;所以,PUT方法具備冪等性。
SOAP(原爲Simple Object Access Protocol的首字母縮寫,即簡單對象訪問協議)是交換數據的一種協議規範,使用在計算機網絡Web服務(web service)中,交換帶結構信息。SOAP爲了簡化網頁服務器(Web Server)從XML數據庫中提取數據時,節省去格式化頁面時間,以及不一樣應用程序之間按照HTTP通訊協議,聽從XML格式執行資料互換,使其抽象於語言實現、平臺和硬件。
RPC(Remote Procedure Call Protocol)——遠程過程調用協議,它是一種經過網絡從遠程計算機程序上請求服務,而不須要了解底層網絡技術的協議。RPC協議假定某些傳輸協議的存在,如TCP或UDP,爲通訊程序之間攜帶信息數據。在OSI網絡通訊模型中,RPC跨越了傳輸層和應用層。RPC使得開發包括網絡分佈式多程序在內的應用程序更加容易。
總結:服務提供的兩大流派.傳統意義以方法調用爲導向通稱RPC。爲了企業SOA,若干廠商聯合推出webservice,制定了wsdl接口定義,傳輸soap.當互聯網時代,臃腫SOA被簡化爲http+xml/json.可是簡化出現各類混亂。以資源爲導向,任何操做無非是對資源的增刪改查,因而統一的REST出現了.
進化的順序: RPC -> SOAP -> RESTful
CGI是通用網關接口,是鏈接web服務器和應用程序的接口,用戶經過CGI來獲取動態數據或文件等。 CGI程序是一個獨立的程序,它能夠用幾乎全部語言來寫,包括perl,c,lua,python等等。
WSGI, Web Server Gateway Interface,是Python應用程序或框架和Web服務器之間的一種接口,WSGI的其中一個目的就是讓用戶能夠用統一的語言(Python)編寫先後端。
官方說明:PEP-3333
在GFW裏家常便飯的,呵呵.
中間人攻擊(Man-in-the-middle attack,一般縮寫爲MITM)是指攻擊者與通信的兩端分別建立獨立的聯繫,並交換其所收到的數據,使通信的兩端認爲他們正在經過一個私密的鏈接與對方直接對話,但事實上整個會話都被攻擊者徹底控制。
所謂c10k問題,指的是服務器同時支持成千上萬個客戶端的問題,也就是concurrent 10 000 connection(這也是c10k這個名字的由來)。 推薦:
Socket=Ip address+ TCP/UDP + port
304 Not Modified
HTTP請求8種方法介紹 HTTP/1.1協議中共定義了8種HTTP請求方法,HTTP請求方法也被叫作「請求動做」,不一樣的方法規定了不一樣的操做指定的資源方式。服務端也會根據不一樣的請求方法作不一樣的響應。
GET GET請求會顯示請求指定的資源。通常來講GET方法應該只用於數據的讀取,而不該當用於會產生反作用的非冪等的操做中。 GET會方法請求指定的頁面信息,並返回響應主體,GET被認爲是不安全的方法,由於GET方法會被網絡蜘蛛等任意的訪問。
HEAD HEAD方法與GET方法同樣,都是向服務器發出指定資源的請求。可是,服務器在響應HEAD請求時不會回傳資源的內容部分,即:響應主體。這樣,咱們能夠不傳輸所有內容的狀況下,就能夠獲取服務器的響應頭信息。HEAD方法常被用於客戶端查看服務器的性能。
POST POST請求會 向指定資源提交數據,請求服務器進行處理,如:表單數據提交、文件上傳等,請求數據會被包含在請求體中。POST方法是非冪等的方法,由於這個請求可能會建立新的資源或/和修改現有資源。
PUT PUT請求會身向指定資源位置上傳其最新內容,PUT方法是冪等的方法。經過該方法客戶端能夠將指定資源的最新數據傳送給服務器取代指定的資源的內容。
DELETE DELETE請求用於請求服務器刪除所請求URI(統一資源標識符,Uniform Resource Identifier)所標識的資源。DELETE請求後指定資源會被刪除,DELETE方法也是冪等的。
CONNECT CONNECT方法是HTTP/1.1協議預留的,可以將鏈接改成管道方式的代理服務器。一般用於SSL加密服務器的連接與非加密的HTTP代理服務器的通訊。
OPTIONS OPTIONS請求與HEAD相似,通常也是用於客戶端查看服務器的性能。 這個方法會請求服務器返回該資源所支持的全部HTTP請求方法,該方法會用’*’來代替資源名稱,向服務器發送OPTIONS請求,能夠測試服務器功能是否正常。JavaScript的XMLHttpRequest對象進行CORS跨域資源共享時,就是使用OPTIONS方法發送嗅探請求,以判斷是否有對指定資源的訪問權限。 容許
TRACE TRACE請求服務器回顯其收到的請求信息,該方法主要用於HTTP請求的測試或診斷。 HTTP/1.1以後增長的方法 在HTTP/1.1標準制定以後,又陸續擴展了一些方法。其中使用中較多的是 PATCH 方法: PATCH PATCH方法出現的較晚,它在2010年的RFC 5789標準中被定義。PATCH請求與PUT請求相似,一樣用於資源的更新。兩者有如下兩點不一樣: 但PATCH通常用於資源的部分更新,而PUT通常用於資源的總體更新。 當資源不存在時,PATCH會建立一個新的資源,而PUT只會對已在資源進行更新。
AJAX,Asynchronous JavaScript and XML(異步的 JavaScript 和 XML), 是與在不從新加載整個頁面的狀況下,與服務器交換數據並更新部分網頁的技術。