面試題總結javascript
一、Python和Java、PHP、C、C#、C++等其餘語言的區別?php
1.python語言,是一種面向對象、直譯式計算機程序設計語言, Python語法簡潔而清晰,具備豐富和強大的類庫。 它常被暱稱爲膠水語言, 它可以很輕鬆的把用其餘語言製做的各類模塊(尤爲是C/C++)輕鬆地聯結在一塊兒。 常見的一種應用情形是,使用python快速生成程序的原型(有時甚至是程序的最終界面),而後對其中有特別要求的部分,用更合適的語言改寫。 Python是徹底面向對象的語言。 函數、模塊、數字、字符串都是對象。 而且徹底支持繼承、重載、派生、多繼承,有益於加強源代碼的複用性。 Python支持重載運算符和動態類型。 相對於Lisp這種傳統的函數式編程語言,Python對函數式設計只提供了有限的支持。 有兩個標準庫(functools, itertools)提供了Haskell和Standard ML中久經考驗的函數式程序設計工具。Python自己被設計爲可擴充的。 並不是全部的特性和功能都集成到語言核心。 Python提供了豐富的API和工具,以便程序員可以輕鬆地使用C語言、C++、Cython來編寫擴充模塊。 Python編譯器自己也能夠被集成到其它須要腳本語言的程序內。 所以,不少人還把Python做爲一種「膠水語言」(glue language)使用。 使用Python將其餘語言編寫的程序進行集成和封裝。 2. Java語言,Java是一種能夠撰寫跨平臺應用軟件的面向對象的程序設計語言, 是由Sun Microsystems公司於1995年5月推出的Java程序設計語言和Java平臺(即JavaSE, JavaEE, JavaME)的總稱。 Java 技術具備卓越的通用性、高效性、平臺移植性和安全性, 普遍應用於我的PC、數據中心、遊戲控制檯、科學超級計算機、移動電話和互聯網, 同時擁有全球最大的開發者專業社羣。 在全球雲計算和移動互聯網的產業環境下,Java更具有了顯著優點和廣闊前景。 Java的優點,與傳統程序不一樣,Sun 公司在推出 Java 之際就將其做爲一種開放的技術。 全球數以萬計的 Java 開發公司被要求所設計的 Java軟件必須相互兼容。 「Java 語言靠羣體的力量而非公司的力量」是Sun公司的口號之一,並得到了廣大軟件開發商的認同。 這與微軟公司所倡導的注重精英和封閉式的模式徹底不一樣。 Sun 公司對 Java 編程語言的解釋是:Java 編程語言是個簡單、面向對象、分佈式、解釋性、健壯、安全與系統無關、可移植、高性能、多線程和動態的語言。 3.php語言,PHP(PHP: Hypertext Preprocessor的縮寫,中文名:「PHP:超文本預處理器」)是一種通用開源腳本語言。 語法吸取了C語言、Java和Perl的特色,入門門檻較低,易於學習,使用普遍,主要適用於Web開發領域。 特性:PHP 獨特的語法混合了 C、Java、Perl 以及 PHP 自創新的語法; PHP能夠比CGI或者Perl更快速的執行動態網頁——動態頁面方面, 與其餘的編程語言相比,PHP是將程序嵌入到HTML文檔中去執行, 執行效率比徹底生成htmL標記的CGI要高許多, PHP具備很是強大的功能,全部的CGI的功能PHP都能實現; PHP支持幾乎全部流行的數據庫以及操做系統; 最重要的是PHP能夠用C、C++進行程序的擴展。 4.C語言,它既有高級語言的特色,又具備彙編語言的特色,它是結構式語言。 C語言應用指針:能夠直接進行靠近硬件的操做, 可是C的指針操做不作保護,也給它帶來了不少不安全的因素。 C++在這方面作了改進,在保留了指針操做的同時又加強了安全性,受到了一些用戶的支持, 可是,因爲這些改進增長語言的複雜度,也爲另外一部分所詬病。 Java則吸收了C++的教訓,取消了指針操做,也取消了C++改進中一些備受爭議的地方,在安全性和適合性方面均取得良好的效果, 但其自己解釋在虛擬機中運行,運行效率低於C++/C。 通常而言,C,C++,java被視爲同一系的語言,它們長期佔據着程序使用榜的前三名。 C語言的優勢:簡潔緊湊、靈活方便; 運算符豐富; 數據類型豐富; 表達方式靈活實用; 容許直接訪問物理地址,對硬件進行操做; 生成目標代碼質量高,程序執行效率高; 可移植性好; 表達力強; C語言的缺點:C語言的缺點主要表如今數據的封裝性上, 這一點使得C在數據的安全性上有很大缺陷,這也是C和C++的一大區別。 C語言的語法限制不太嚴格, 對變量的類型約束不嚴格,影響程序的安全性, 對數組下標越界不做檢查等。 從應用的角度,C語言比其餘高級語言較難掌握。 也就是說,對用C語言的人,要求對程序設計更熟練一些。 5.C++是C語言的繼承, 它既能夠進行C語言的過程化程序設計, 又能夠進行以抽象數據類型爲特色的基於對象的程序設計, 還能夠進行以繼承和多態爲特色的面向對象的程序設計。 C++擅長面向對象程序設計的同時, 還能夠進行基於過程的程序設計, 於是C++就適應的問題規模而論,大小由之。 C++不只擁有計算機高效運行的實用性特徵, 同時還致力於提升大規模程序的編程質量與程序設計語言的問題描述能力。 C++語言的程序由於要體現高性能,因此都是編譯型的。 但其開發環境,爲了方便測試,將調試環境作成解釋型的。 即開發過程當中,以解釋型的逐條語句執行方式來進行調試, 以編譯型的脫離開發環境而啓動運行的方式來生成程序最終的執行代碼。 生成程序是指將源碼(C++語句)轉換成一個能夠運行的應用程序的過程。 若是程序的編寫是正確的,那麼一般只需按一個功能鍵,便可搞定這個過程。 該過程實際上分紅兩個步驟。 第一步是對程序進行編譯,這須要用到編譯器(compiler)。 編譯器將C++語句轉換成機器碼(也稱爲目標碼); 若是這個步驟成功,下一步就是對程序進行連接,這須要用到連接器(linker)。 連接器將編譯得到機器碼與C++庫中的代碼進行合併。 C++庫包含了執行某些常見任務的函數(「函數」是子程序的另外一種稱呼)。 例如,一個C++庫中包含標準的平方根函數sqrt,因此沒必要親自計算平方根。 C++庫中還包含一些子程序,它們把數據發送到顯示器, 並知道如何讀寫硬盤上的數據文件。 6. C#語言,C#是微軟公司發佈的一種面向對象的、運行於.NET Framework之上的高級程序設計語言。 C#看起來與Java有着驚人的類似; 它包括了諸如單一繼承、接口、與Java幾乎一樣的語法和編譯成中間代碼再運行的過程。 可是C#與Java有着明顯的不一樣, 它借鑑了Delphi的一個特色,與COM(組件對象模型)是直接集成的, 並且它是微軟公司 .NET windows網絡框架的主角。 首先,C# 和JAVA同樣,簡直就是照搬了C++的部分語法, 所以,對於數量衆多的C++程序員學習起來很容易上手, 另外,對於新手來講,比C++要簡單一些。 其次,Windows是佔壟斷地位的平臺,而開發Windows應用,固然微軟的聲音是不能忽略的。 最重要的是,相對於C++,用C# 開發應用軟件能夠大大縮短開發週期, 同時能夠利用原來除用戶界面代碼以外的C++代碼。
二、簡述解釋型和編譯型編程語言?css
編譯型(須要編譯器,至關於用谷歌翻譯): 編譯型語言執行速度快,不依賴語言環境運行,跨平臺差,如C,C++執行速度快,調試麻煩 解釋型(須要解釋器,至關於同聲傳譯): 解釋型跨平臺好,一份代碼,處處使用,缺點是執行速度慢,依賴解釋器運行,如python,JAVA執行速度慢,調試方便
三、Python解釋器種類以及特色?html
CPython CPython是使用最廣且被的Python解釋器。本教程以CPython爲準。當咱們從Python官方網站下載並安裝好Python 2.7後,咱們就直接得到了一個官方版本的解釋器:CPython。這個解釋器是用C語言開發的,因此叫CPython。在命令行下運行python就是啓動CPython解釋器。 IPython IPython是基於CPython之上的一個交互式解釋器,也就是說,IPython只是在交互方式上有所加強,可是執行Python代碼的功能和CPython是徹底同樣的。比如不少國產瀏覽器雖然外觀不一樣,但內核其實都是調用了IE。CPython用>>>做爲提示符,而IPython用In [序號]:做爲提示符。 PyPy PyPy是另外一個Python解釋器,它的目標是執行速度。PyPy採用JIT技術,對Python代碼進行動態編譯(注意不是解釋),因此能夠顯著提升Python代碼的執行速度。 絕大部分Python代碼均可以在PyPy下運行,可是PyPy和CPython有一些是不一樣的,這就致使相同的Python代碼在兩種解釋器下執行可能會有不一樣的結果。若是你的代碼要放到PyPy下執行,就須要瞭解PyPy和CPython的不一樣點。 Jython Jython是運行在Java平臺上的Python解釋器,能夠直接把Python代碼編譯成Java字節碼執行。 IronPython IronPython和Jython相似,只不過IronPython是運行在微軟.Net平臺上的Python解釋器,能夠直接把Python代碼編譯成.Net的字節碼。
四、位和字節的關係?前端
1 bytes(字節) = 8 bit(位)
五、b、B、KB、GB 的關係?vue
8bit = 1B 1024B = 1KB 1024KB = 1MB 1024MB = 1GB
六、請至少列舉 5 個 PEP8 規範(越多越好)?java
使用space(空格)來表示縮進,而不要用tab(製表符) 和語法相關的每一層縮進都要用4個空格來表示 每行的字符數不該超過79 對於佔據多行的長表達式來講,除了首行以外的其他各行都應該在一般的縮進級別之上再加上4個空格 文件中函數與類之間應該用兩個空行隔開 在同一個類中,各方法之間應該用一個空行隔開 函數、變量及屬性應該用小寫字母來拼寫,各單詞之間如下劃線相連,例如:`lowercase_underscore` 類中的實例方法(instance method),應該把首個參數命名爲self,以表示該對象自身 類方法(class method)的首個參數,應該命名爲cls,以表示該類自身 不要經過檢測長度的方法(如if len(somelist) == 0)來判斷somelist是否爲[]或「」等空值,而是應該採用if not somelist,它會假定:空值會自動評估爲False
七、求結果:or andnode
v1 = 1 or 3 v2 = 1 and 3 v3 = 0 and 2 and 1 v4 = 0 and 2 or 1 v5 = 0 and 2 or 1 or 4 v6 = 0 or Flase and 1 ==or:只要一個爲真結果爲真 ==and必須同時爲真,結果爲真; ==若是都爲真,取比1大的數字 v1 = 1 or 3 v2 = 1 and 3 v3 = 0 and 2 and 1 v4 = 0 and 2 or 1 v5 = 0 and 2 or 1 or 4 v6 = 0 or False and 1 運行結果: >>>1 3 0 1 1 False
八、ASCII、Unicode、utf-八、bgk區別?python
ascii: 在計算機內部,全部信息最終都是一個二進制值。 每個二進制位(bit),有0和1兩種狀態, 所以,8個二進制位能夠組合出256種狀態,這被稱爲字節(byte)。 上個世紀60年代,美國製定了一套字符編碼,對英文字符與二進制之間作了聯繫,這被稱爲ASCII碼,一直沿用至今。 ASCII碼一共規定了128個字符, 好比SPACE是32,A是65, 這128個符號只用了一個字節的後面七位,最前面的一位統一規定爲0。 unicode: 世界上有多種編碼方法,同一個二進制數字能夠被解釋稱不一樣的符號。 所以,在打開一個文本文件時候,就必須知道它的編碼方式,用錯誤的編碼方式打開,就會出現亂碼。 Unicode編碼,這是一種全部符號的編碼。 Unicode顯然是一個巨大的集合, 如今的規模能夠容納100多萬個符號。 每一個符號的編碼都不同, 好比U+0041表示英語的大寫字母A, U+4e25表示漢字嚴。 在Unicode龐大的字符集的優點下,還存在一個問題, 好比一個漢字,「嚴」的Unicode是十六進制4e25, 轉成二進制足足有15位, 也就是,這個符號須要2個字節, 表示其餘字符還存在3個字節或者更多。 計算機怎麼區別三個字節表示的是同一個符號而不是分開表示三個呢? 若是Unicode統一規定,每一個符號用3個字節表示, 可是某些字母顯然不須要3個,那麼就浪費了空間, 文本文件大小超出了不少,這顯然是不合理的。 直到UTF8字符編碼出現了。 utf-8: UTF8的最大特色是,它是一種變長編碼, 能夠使用1-4個字節表示一個符號, 根據不一樣的符號來變化字節長度。 UTF8編碼規則只有兩條: 1)對於單字節的符號,字節的第一位設爲0,後面的7位爲這個符號的Unicode碼。 所以,對於英文字母,UTF8編碼和ASCII編碼是相同的。 2)對於非單字節(假設字節長度爲N)的符號, 第一個字節的前N位都設爲1,第N+1設爲0, 後面字節的前兩位一概設爲10,剩下的沒有說起的二進制,所有爲這個符號的Unicode碼。 gbk: GBK編碼是對GB2312的擴展,徹底兼容GB2312。 採用雙字節編碼方案, 剔出xx7F碼位,共23940個碼位, 共收錄漢字和圖形符號21886個, GBK編碼方案於1995年12月15日發佈。 它幾乎完美支持漢字, 所以常常會碰見GBK與Unicode的轉換。 一、各個編碼之間的二進制,是不能互相識別的,會產生亂碼。 二、文件的存儲,傳輸,不能是unicode (只能是utf-8 utf-16 gbk gbk2312 ascii等)
九、字節碼和機器碼的區別?mysql
字節碼是一種中間狀態(中間碼)的二進制代碼(文件)。 須要直譯器轉譯後才能成爲機器碼。
十、三元運算編碼格式?
條件成立 if 條件 else 條件不成立
py2 >>> print("hello", "world") ('hello', 'world') py3 >>> print("hello", "world") hello world py2:input_raw() py3:input() 1/2的結果 py2:返回0 py3:返回0.5 py2:默認編碼ascii py3:默認編碼utf-8 字符串 py2:unicode類型表示字符串序列,str類型表示字節序列 py3::str類型表示字符串序列,byte類型表示字節序列 py2中函數用關鍵字global聲明某個變量爲全局變量,可是在嵌套函數中,想要給一個變量聲明爲非局部變量是無法實現的。 py3中,新增了關鍵字nonlocal,使得非局部變量成爲可能
十二、用一行代碼實現數值交換?
a = 1 b = 2 ------------------ a,b = b,a
1三、Python2和Python3中int和long的區別?
python2: int() # 整型 long() # 長整型 python3中沒有long類型,只有int類型
1四、xrange和range的區別?
xrange 用法與 range 徹底相同, 所不一樣的是生成的不是一個list對象,而是一個生成器。 注意:如今的python3中將之前的range取消了,而將xrange從新命名成了range!因此咱們如今看到的range其實本質仍是xrange
name="張全蛋" print(name[::-1]) 蛋全張
readlines()是把文件的所有內容讀到內存,並解析成一個list,當文件的體積很大的時候,須要佔用不少內存 xreadlines()直接返回一個iter(file)迭代器, 在Python2.3之後就不推薦這種表示方法了.直接使用for循環迭代文件對象
1七、列舉布爾值爲False的常見值?
0, (), [] , {} , '' , False , None
is比較的是id ==比較的是值
1九、哪些狀況下,y!= x-(x-y)會成立?
x,y是兩個不相等的非空集合
sorted(dict.items(),key=lambda x:x[1])
2一、字典和json的區別?
字典是一種數據結構,字典的key值只要是能hash的就行 json是一種數據的表現形式,json的必須是字符串
可變不可變指的是內存中的值是否能夠被改變, 不可變類型指的是對象所在內存塊裏面的值不能夠改變,有數字、字符串、元組、集合; 可變類型則是能夠改變,主要有列表、字典。
2三、存入字典裏的數據有沒有前後排序?
存入的數據不會自動排序,能夠使用sort函數對字典進行排序
2四、字典推導式?
dict = {key: value for (key, value) in iterable}
2五、描述下dict的item()方法與iteritems()的不一樣
字典的items方法做用:是能夠將字典中的全部項,以列表方式返回。 由於字典是無序的,因此用items方法返回字典的全部項,也是沒有順序的。 字典的iteritems方法做用:與items方法相比做用大體相同,只是它的返回值不是列表,而是一個迭代器。 """ 在Python2.x中,iteritems() 用於返回自己字典列表操做後的迭代器【Returns an iterator on all items(key/value pairs) 】,不佔用額外的內存。 在Python 3.x 裏面,iteritems()方法已經廢除了。 在3.x裏用 items()替換iteritems() ,能夠用於 for 來循環遍歷。 """
2六、請反轉字符串"aStr"
print("aStr"[::-1])
list1 = [{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}] print(sorted(list1,key=lambda x:x['age'],reverse=True))
2八、經常使用的字符串格式化有哪幾種
name = '張三' 1)佔位符 s1 = "%s DSB 你好"%name 2)format s2 = '{} DSB 你好'.format(name) 3)f-string(python3.6以後纔有的特性) s3 = f'{name} DSB 你好'
2九、簡述字符串駐留機制
對於短字符串,將其賦值給多個不一樣的對象時, 內存中只有一個副本,多個對象共享該副本。 長字符串不遵照駐留機制。 駐留適用範圍: 由數字,字符和下劃線(_)組成的python標識符以及整數[-5,256]。
list = ['a', 'b', 'c', 'd', 'e'] print(list[10:]) ''' 下面的代碼將輸出[],不會產生IndexError錯誤。就像所指望的那樣,嘗試用超出成員的個數的index 來獲取某個列表的成員。例如,嘗試獲取list[10]和以後的成員,會致使IndexError。 '''
print([x*11 for x in range(10)])
list1 = [1,2,3] list2 = [3,4,5] set1 = set(list1) set2 = set(list2) print(set1&set2) print(set1^set2)
函數內置的set l1 = ['b','c','d','b','c','a','a'] l2 = list(set(l1)) print(l2) 若是想要保持他們原來的排序,用list類的sort方法 l1 = ['b','c','d','b','c','a','a'] l2 = sorted(set(l1),key=l1.index) print(l2) 遍歷的方法 l1 = ['b', 'c', 'd', 'b', 'c', 'a', 'a'] l2 = [] for i in l1: if not i in l2: l2.append(i) print(l2)
3四、下面結果是什麼?解釋一下
def extendlist(val, list=[]): list.append(val) return list list1 = extendlist(10) list2 = extendlist(123, [] list3 = extendlist('a') print("list1 = %s" %list1) print("list2 = %s" %list2) print("list3 = %s" %list3) 輸出結果: list1 = [10, 'a'] list2 = [123] list3 = [10, 'a'] 新的默認列表只在函數被定義的那一刻建立一次。當extendList被沒有指定特定參數list調用時,這組list的值 隨後將被使用。這是由於帶有默認參數的表達式在函數被定義的時候被計算,不是在調用的時候被計算。
3五、將如下3個函數按照執行效率高低排序
def f1(lIn): l1 = sorted(lIn) l2 = [i for i in l1 if i<0.5] return [i*i for i in l2] def f2(lIn): l1 = [i for i in l1 if i<0.5] l2 = sorted(l1) return [i*i for i in l2] def f3(lIn): l1 = [i*i for i in lIn] l2 = sorted(l1) return [i for i in l1 if i<(0.5*0.5)] 按執行效率從高到低排列:f二、f1和f3。 要證實這個答案是正確的,你應該知道如何分析本身代碼的性能。 Python中有一個很好的程序分析包,能夠知足這個需求 import random import cProfile lIn = [random.random() for i in range(100000)] cProfile.run('f1(lIn)') cProfile.run('f2(lIn)') cProfile.run('f3(lIn)')
l1 = ['This','is','a','Boy','!'] print(sorted(l1))
字符串:repleace,strip,split,reverse,upper,lower,join..... 列表:append,pop,insert,remove,sort,count,index..... 元組:index,count,len(),dir() 字典:get,keys,values,pop,popitems,clear,update,items.....
在絕大多數語言當中都有反射機制的存在, 能夠用字符串的方式去訪問對象的屬性,調用對象的方法(可是不能去訪問方法), Python中一切皆對象,均可以使用反射 1)、反射機制是不少框架的基石。 2)、setattr,getattr,hasattr
copy():淺copy,淺拷貝指僅僅拷貝數據集合的第一層數據 deepcopy():深copy,深拷貝指拷貝數據集合的全部層
垃圾回收機制是自動幫助咱們管理內存,清理垃圾的一種工具 1)、引用計數 當一個對象的引用被建立或者複製時,對象的引用計數加1; 當一個對象的引用被銷燬時,對象的引用計數減1; 當對象的引用計數減小爲0時,就意味着對象已經沒有被任何人使用了,能夠將其所佔用的內存釋放了。 優勢: 簡單、直觀 實時性,只要沒有了引用就釋放資源。 缺點: 維護引用計數須要消耗必定的資源 循環應用時,沒法回收。也正是由於這個緣由,才須要經過標記-清理和分代收集機制來輔助引用計數機制。 2)、標記-清除 「標記-清除」不改動真實的引用計數,而是將 集合中對象的引用計數複製一份副本,改動該對象引用的副本。對於副 本作任何的改動,都不會影響到對象生命走起的維護。 3)、分代回收 將系統中的全部內存塊根據其存活時間劃分爲不一樣的集合, 每個集合就成爲一個「代」,垃圾收集的頻率隨着「代」的存活時間的增大而減少。 也就是說,活得越長的對象,就越不多是垃圾,就應該減小對它的垃圾收集頻率。 那麼如何來衡量這個存活時間:一般是利用幾回垃圾收集動做來衡量, 若是一個對象通過的垃圾收集次數越多,能夠得出:該對象存活時間就越長。
4一、獲取Python解釋器版本的方法是
import sys print(sys.version)
4二、Python中,哪一個語句能直接顯示的釋放內存資源
import gc gc.collect()
4三、lambda表達式格式以及應用場景
匿名就是沒有名字 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)
4四、*arg和**kwargs做用
*args用來接收溢出的位置參數,將接收的參數組織成元祖 **kwargs用來接收溢出的關鍵字參數,將接受的參數組織成字典
4五、求結果
v = dict.fromkeys(['k1','k2'],[]) v['k1'].append(666) print(v)#輸出結果{'k1': [666], 'k2': [666]} v['k1'] = 777 print(v)#{'k1': 777, 'k2': [666]} #第一次字典的兩個k指向的是同一塊內存地址,因此k1的內存地址追加666, k2的值也一樣會是666, 而當給k1賦值時,改變了k1指向的內存地址,因此這個時候,k2不會隨之發生變化
4六、一行代碼實現99乘法表
print("\n".join("\t".join(["%s*%s=%s" %(x,y,x*y) for y in range(1, x+1)]) # 遞歸 def f(i): if i>=1: f(i-1) print(['%dx%d=%d'%(j,i,i*j) for j in range(1,i+1)]) if __name__=='__main__': f(9)
4七、比較a=[1,2,3]和b=[(1),(2),(3)]以及c=[(1,),(2,),(3,)]的區別
a與b二者值相等,而c中列表的每一個元素是一個個的元組形式 a,b元素均爲數字,b中括號內沒有加逗號,因此仍然是數字
4八、1<(2==2)和 1<2等於2的結果分別是什麼,爲何
print(1 < (2 == 2)) --> False #先執行括號內的 print(1 < 2 == 2) --> True #true==2爲true
4九、如何打亂一個排好序的list對象alist
import random random.shuffle(alist)
50、如何查找一個字符串特定的字符find和index的差別
find()方法:查找子字符串,若找到返回從0開始的下標值,若找不到返回-1 index()方法:在字符串裏查找子串第一次出現的位置,相似字符串的find方法, 若是查找不到字符串,會拋出異常,而不是返回-1 rfind和rindex方法用法和上面同樣,只是從字符串的末尾開始查找
5一、把aaabbcccd這種形式的字符串壓縮成a3b2c3d1這種形式
b={} c="" a="aaabbcccd" for i in a: b[i]=b.get(i,0)+1 for i,t in b.items(): c+=str(i) c+=str(t) print(c)
5二、Python一個數若是剛好等於它的因子之和,這個數就稱爲"完數"。例如6=1+2+3編程找出1000之內的全部完數。
from functools import reduce def sum(a, b): return a + b for i in range(2, 1001): l = [1] for j in range(2, int(i / 2 + 1)): if i % j == 0: l.append(j) if i == reduce(sum, l): print(i) print(l)
5三、給你一個字符串,好比'abc',請打印出該字符串的全部排列組合
def perm(s=''): if len(s) <= 1: return [s] sl = [] for i in range(len(s)): for j in perm(s[0:i] + s[i + 1:]): sl.append(s[i] + j) return sl def main(): perm_nums = perm('abb') no_repeat_nums = list(set(perm_nums)) # 去重 print('perm_nums', len(perm_nums), perm_nums) print('no_repeat_nums', len(no_repeat_nums), no_repeat_nums) pass if __name__ == '__main__': main()
5四、結果x的值爲
x = 10 x += x x -= x - x print(x) """ 20 """
5五、對於一個非空字符串,判斷其是否能夠有一個子字符串重複屢次組成,字符串只包含小寫字母且長度不超過10000
示例 1: \1. 輸入"abab" \2. 輸出True \3. 樣例解釋: 輸入可由"ab"重複兩次組成 示例 2: \1. 輸入"abcabcabc" \2. 輸出True \3. 樣例解釋: 輸入可由"abc"重複三次組成 示例 3: \1. 輸入"aba" \2. 輸出False class Solution(object): def repeatedSubstringPattern(self, s): """ :type s: str :rtype: bool """ n = len(s) for i in range(1, n // 2 + 1): if n % i == 0: a = s[:i] j = i while j < n and s[j:j + i] == a: j += i if j == n: return True return False
5六、從0-99這100個數中隨機取出10個,要求不能重複,能夠本身設計數據結構
print([x * x for x in range(1, 11)])
5七、介紹一下try except的用法和做用?
Python的except用來捕獲全部異常, 由於Python裏面的每次錯誤都會拋出 一個異常,因此每一個程序的錯誤都被看成一個運行時錯誤。 try: pass except BaseException as e: print(e) finally: pass
5八、在Python中如何拋出,捕獲,處理異常?
raise Exception 觸發拋出異常 用try和except語句來捕獲異常 處理異常的方法有: try ... except...else語句 finally子句, with語句
5九、enumerate的做用是什麼?
enumerate函數是將一個可迭代對象中 元素, 按元素順序 每一個 增長一個索引值, 將其組成一個索引序列, 利用它能夠同時得到索引和值,這樣作的目的是爲了將一個可迭代對象中元素組成一個「索引,值」對便於後續操做。
60、lambda表達式格式以及應用場景?
# 匿名就是沒有名字 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) # 讓其有名字就沒有意義,與內置函數配合一塊兒使用
6一、Python遞歸的最大層數?
最大數爲 998
print([i % 2 for i in range(10)]) print((i % 2 for i in range(10))) ------------------------------------ [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] <generator object <genexpr> at 0x0000014DB67BE150>
6三、列舉常見的內置函數?
# 答案 ''' 數學類型 abs(a) : 求取絕對值。abs(-1) max(list) : 求取list最大值。max([1,2,3]) min(list) : 求取list最小值。min([1,2,3]) sum(list) : 求取list元素的和。 sum([1,2,3]) >>> 6 sorted(list) : 排序,返回排序後的list。 len(list) : list長度,len([1,2,3]) divmod(a,b): 獲取商和餘數。 divmod(5,2) >>> (2,1) pow(a,b) : 獲取乘方數。pow(2,3) >>> 8 round(a,b) : 獲取指定位數的小數。a表明浮點數,b表明要保留的位數。round(3.1415926,2) >>> 3.14 range(a[,b]) : 生成一個a到b的數組,左閉右開。 range(1,10) >>> [1,2,3,4,5,6,7,8,9] 類型轉換 int(str) : 轉換爲int型。int('1') >>> 1 float(int/str) : 將int型或字符型轉換爲浮點型。float('1') >>> 1.0 str(int) : 轉換爲字符型。str(1) >>> '1' bool(int) : 轉換爲布爾類型。 str(0) >>> False str(None) >>> False bytes(str,code) : 接收一個字符串,與所要編碼的格式,返回一個字節流類型。bytes('abc', 'utf-8') >>> b'abc' bytes(u'爬蟲', 'utf-8') >>> b'\xe7\x88\xac\xe8\x99\xab' list(iterable) : 轉換爲list。 list((1,2,3)) >>> [1,2,3] iter(iterable): 返回一個可迭代的對象。 iter([1,2,3]) >>> <list_iterator object at 0x0000000003813B00> dict(iterable) : 轉換爲dict。 dict([('a', 1), ('b', 2), ('c', 3)]) >>> {'a':1, 'b':2, 'c':3} enumerate(iterable) : 返回一個枚舉對象。 tuple(iterable) : 轉換爲tuple。 tuple([1,2,3]) >>>(1,2,3) set(iterable) : 轉換爲set。 set([1,4,2,4,3,5]) >>> {1,2,3,4,5} set({1:'a',2:'b',3:'c'}) >>> {1,2,3} hex(int) : 轉換爲16進制。hex(1024) >>> '0x400' oct(int) : 轉換爲8進制。 oct(1024) >>> '0o2000' bin(int) : 轉換爲2進制。 bin(1024) >>> '0b10000000000' chr(int) : 轉換數字爲相應ASCI碼字符。 chr(65) >>> 'A' ord(str) : 轉換ASCI字符 爲相應的數字。 ord('A') >>> 65 相關操做 eval() : 執行一個表達式,或字符串做爲運算。 eval('1+1') >>> 2 exec() : 執行python語句。 exec('print("Python")') >>> Python filter(func, iterable) : 經過判斷函數fun,篩選符合條件的元素。 filter(lambda x: x>3, [1,2,3,4,5,6]) >>> <filter object at 0x0000000003813828> map(func, *iterable) : 將func用於每一個iterable對象。 map(lambda a,b: a+b, [1,2,3,4], [5,6,7]) >>> [6,8,10] zip(*iterable) : 將iterable分組合並。返回一個zip對象。 list(zip([1,2,3],[4,5,6])) >>> [(1, 4), (2, 5), (3, 6)] type():返回一個對象的類型。 id(): 返回一個對象的惟一標識值。 hash(object):返回一個對象的hash值,具備相同值的object具備相同的hash值。 hash('python') >>> 7070808359261009780 help():調用系統內置的幫助系統。 isinstance():判斷一個對象是否爲該類的一個實例。 issubclass():判斷一個類是否爲另外一個類的子類。 globals() : 返回當前全局變量的字典。 next(iterator[, default]) : 接收一個迭代器,返回迭代器中的數值,若是設置了default,則當迭代器中的元素遍歷後,輸出default內容。 reversed(sequence) : 生成一個反轉序列的迭代器。 reversed('abc') >>> ['c','b','a'] '''
# 答案 filter(func, iterable) : 經過判斷函數fun,篩選符合條件的元素。 filter(lambda x: x>3, [1,2,3,4,5,6]) >>> <filter object at 0x0000000003813828> map(func, *iterable) : 將func用於每一個iterable(迭代)對象。 map(lambda a,b: a+b, map(lambda a,b: a+b, [1,2,3,4], [5,6,7]) # map將兩個列表中的元素分別依次映射到a,b中 >>> [6,8,10] reduce(): 函數會對參數序列中元素進行累積。 reduce(lambda x, y: x+y, [1,2,3,4,5]) # 使用 lambda 匿名函數 >>> 15
6五、一行代碼實現九九乘法表
print('\n'.join(['\t'.join(["%2s*%2s=%2s"%(j,i,i*j) for j in range(1,i+1)]) for i in range(1,10)]))
閉包函數(closure function)指的是定義在一個函數內部的函數,被外層函數包裹着,其特色是能夠訪問到外層函數中的名字,以下inner函數就是一個閉包函數。 def outer(): num = 1 def inner(): print(num) # 內層函數中不存在num 但能夠訪問到外層的num return inner # 基於函數對象的概念咱們能夠將內層函數返回到外界使用,從而打破函數調用的層級限制,但不管在何處調用,做用域的嵌套關係都是以定義階段爲準的,因此外界獲得的不只僅是一個函數對象(inner),在該函數外還包裹了一層做用域,這使得該函數不管在何處調用,都是訪問本身外層包裹的做用域中的名字num func = outer() # func == inner func指向的是inner的內存地址,可是func自己確實一個全局變量,能夠在任意位置調用func,但不管在何處調用func,都須要按照定義階段做用域的嵌套關係去查找名字 num=1000 func() #輸出結果:1
6七、使用生成器編寫fib函數,函數聲明爲fib(max),輸入一個參數max值,使得該函數能夠這樣調用。
for i in range(0,100): print fib(1000) # 併產生以下結果(斐波那契數列),1,1,2,3,5,8,13,21... # 答案 def fib(): i,k=1,0 while 1: j=i+k yield j i=k k=j for fn in fib(): if fn>1000: break else: print(fn)
6八、一行代碼,經過 filter 和 lambda 函數輸出如下列表索引爲基數對應的元素
list_a=[12,213,22,2,2,2,22,2,2,32] # 答案 l = filter(lambda x:x in list_a,[i for i in range(len(list_a))]) print(list(l))
6九、寫一個base62encode函數,62進制
# 即:0123456789AB..Zab..z(10 個數字+26 個大寫字母+26 個小寫字母)。 # 答案 def base62Encode(n): s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" lst = [] while n > 0: lst.append(n % 62) # 58 n = n // 62 lst = lst[::-1] result = "" for item in lst: # 58 result += s[item] return result print(base62Encode(58)) # 結果 w
# 答案 import time def time_pay(func): def inner(*args, **kwargs): for line in range(10): print(line + 1) time.sleep(1) res = func(*args, **kwargs) return res return inner @time_pay def func1(): print('from func1...') func1()
# 答案 def again_func(func): def inner(*args, **kwargs): for line in range(5): func(*args, **kwargs) return inner @again_func def func1(): print('from func1...') func1()
7二、python一行 print 出 1~100偶數的列表,(列表推導式,filter都可)
# 答案 print([i for i in range(1, 101) if i % 2 == 0]) print(list(filter(lambda x: x % 2 == 0, range(1, 101))))
# 答案 ''' 生成器和函數的主要區別在於函數return avalue,生成器yield a value,同事標記或記憶point of the yield 以便在下次調用時從標記點恢復執行,yield使用函數轉換成生成器,而生成器反過來有返回迭代器。 ''' ------------------------ 生成器和迭代器的區別 一、共同點 生成器是一種特殊的迭代器 二、不一樣點 a、語法上 生成器是經過函數的形式中調用 yield 或()的形式建立的 迭代器能夠經過 iter() 內置函數建立 b、用法上 生成器在調用next()函數或for循環中,全部過程被執行,且返回值 迭代器在調用next()函數或for循環中,全部值被返回,沒有其餘過程或說動做。
7四、請寫出打印結果
# 例 1 def func(a,b=[]): b.append(a) print(b) func(1) func(1) func(1) func(1) # 例 2 def func(a,b={}): b[a] = 'v' print(b) func(1) func(2) # 答案: ''' 例1: [1] [1, 1] [1, 1, 1] [1, 1, 1, 1] 例2: {1: 'v'} {1: 'v', 2: 'v'} '''
7五、簡述 yeild 和 yield from 關鍵字
# 答案: ''' yield: 當一個函數中出現yield關鍵字的時候,那麼這個函數就是一個生成器。能夠用for循環或者next()函數來迭代。 yield from: 簡單地說,yield from generator 。實際上就是返回另一個生成器 ''
7六、如下代碼輸出結果爲:
# 調用上下文以下 collapse = True processFunc = collapse and (lambda s:" ".join(s.split())) or (lambda s:s) print(processFunc("i\tam\ntest\tobject !")) collapse = False processFunc = collapse and (lambda s:" ".join(s.split())) or (lambda s:s) print(processFunc("i\tam\ntest\tobject !")) # 以上代碼會在控制檯輸出什麼? # 答案: ''' i am test object ! i am test object ! '''
7七、請給出下面代碼的輸出結果
a = 1 def fun(a): a=2 fun(a) print(a) a = [] def fun(a): a.append(1) fun(a) print(a) # 答案 1 [1]
7八、什麼是lambda函數,下面這段代碼的輸出是什麼
nums = range(2,20) for i in nums: nums = filter(lambda x:x==i or x % i, nums) print(list(nums)) # 答案: ''' [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] '''
7九、指出下面程序存在的問題
def Lastllindextem(src, index): '''請返回傳入 src 使用空格或者"\"切分後的倒數第 index 個子串''' return src.split('\')[-index] # 答案 \會是轉義符的,會有問題,須要\\
def func(l): res = [] sum_s = 0 for i in l: if i not in res: res.append(i) sum_s += i return sum_s list1 = [3, 4, 1, 2, 5, 6, 6, 5, 4, 3, 3] print(func(list1)) # 21
8一、求打印結果
arr = [1,2,3] def bar(): arr+=[5] bar() print(arr) ''' A. error B. [5] C. [1,2,3] D. [1,2,3,5] ''' # 答案 A
8二、請給出下面代碼片斷的輸出
def say_hi(func): def wrapper(*args, **kwargs): print("HI") ret = func(*args, **kwargs) print("BYE") return re return wrapper def say_yo(func): def wrapper(*args, **kwargs): print("YO") return func(*args, **kwargs) return wrapper @say_hi @say_yo def func(): print("ROCK & ROLL") func() # 答案 ''' HI YO ROCK & ROLL BYE '''
8三、map(str,[1,2,3,4,5,6,7,8,9])輸出是什麼?
print(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])) # <map object at 0x101f59748>
8四、請簡述標準庫中functools.wraps的做用
# 答案 ''' Python裝飾器(decorator)在實現的時候,有一些細節須要被注意。例如,被裝飾後的函數其實已是另一個函數了(函數名等函數屬性會發生改變)。這樣有時候會對程序形成一些不便,例如筆者想對flask框架中的一些函數添加自定義的decorator,添加後因爲函數名和函數的doc發生了改變,對測試結果有一些影響。 因此,Python的functools包中提供了一個叫wraps的decorator來消除這樣的反作用。寫一個decorator的時候,最好在實現以前加上functools的wrap,它能保留原有函數的名稱和docstring。 '''
8五、請給出下面代碼片斷的輸出
def test(): try: raise ValueError("something wrong") except ValueError as e: print("Error occurred") return finally: print("Done") test() # 答案 # Error occurred # Done
8六、下面的函數,哪些會輸出1,2,3三個數字
def func1(): for i in range(3): print(i) a_list = [0, 1, 2] for i in a_list: print(i + 1) def func2(): i = 1 while i < 3: print(i) i += 1 def func3(): for i in range(3): print(i + 1) # 答案 func3()
8七、如下函數須要在其中引用一個全局變量k,請填寫語句
def fun(): ________ k=k+1 # 答案: global k
8八、請把如下函數轉化爲Python lambda匿名函數
def add(x,y): return x+y # 答案 print(lambda x, y: x + y)
8九、閱讀如下代碼,並寫出程序的輸出結果
my_dict = {"a":0,"b":1} 2. def func(d): d["a"]=1 return d func(my_dict) my_dict["c"]=2 print(my_dict) # 答案 {'a': 1, 'b': 1, 'c': 2}
90、填空題
# 有函數定義以下 def calc(a,b,c,d=1,e=2): return (a+b)*(c-d)+e # 請分別寫出如下標號代碼的輸出結果, 若是出錯請寫出 Error print(calc(1,2,3,4,5)) # ____2 print(calc(1,2,3)) # ____8 print(calc(1,2)) # ____報錯 missing 1 required positional argument: 'c' print(calc(1,2,3,e=4)) # ____10 print(calc(e=4, c=5, a=2,b=3)) # ____24 print(calc(1,2,3, d=5, 4)) # ____SyntaxError
9一、下列函數的輸出結果
def add_end(l=[]): l.append("end") return l print(add_end()) # 輸出什麼 print(add_end()) # 再次調用輸出什麼? 爲何 # 答案 ''' ['end'] ['end', 'end'] # 函數在定義階段參數l就指向了[]的內存地址 '''
9二、可變參數定義*args,**kwargs的區別是什麼?而且寫出下邊代碼的輸入內容
def foo(*args, **kwargs): print("args=", args) print("kwargs=", kwargs) print("-----------------") if __name__ == '__main__': foo(1, 2, 3, 4) foo(a=1, b=2, c=3) foo(1, 2, 3, 4, a=1, b=2, c=3) foo("a", 1, None, a=1, b='2', c=3) # 答案: ''' args= (1, 2, 3, 4) kwargs= {} ----------------- args= () kwargs= {'a': 1, 'b': 2, 'c': 3} ----------------- args= (1, 2, 3, 4) kwargs= {'a': 1, 'b': 2, 'c': 3} ----------------- args= ('a', 1, None) kwargs= {'a': 1, 'b': '2', 'c': 3} '''
9三、請寫出log實現(主要功能是打印函數名)
@log def now(): print("2019-07-25") now() # 輸出 ''' call now() 2019-07-25 ''' --------------打印日誌的裝飾器---------------- import datetime import functools def log(text): def decorator(func): @functools.wraps(func) #內置函數使新建的函數屬性不變 def wrapper(*args, **kw): print('%s %s() %s:' % (text, func.__name__, datetime.datetime.now())) return func(*args, **kw) return wrapper return decorator @log('執行方法') def now(i): sum = i+1 return sum print(now(5)) print(now.__name__)
9四、Python如何定義一個函數
A. class <name>(<Type> arg1, <type> arg2, ...) B. function <name>(arg1,arg2,...) C. def <name>(arg1, arg2,...) D. def <name>(<type> arg1, <type> arg2...) # 答案: C
9五、選擇代碼運行結果
country_counter = {} def addone(country): if country in country_counter: country_counter[country] += 1 else: country_counter[country] = 1 addone("Japan") addone("china") print(len(country_counter))
9六、選擇輸出結果
def doff(arg1, *args): print(type(args)) doff("applea", "bananas", "cherry") A.str B.int C.tuple D.list E.dict # 答案: C
9七、下面程序的輸出結果是
d = lambda p:p*2 t = lambda p:p*3 x = 2 x = d(x) x = t(x) x = d(x) print(x) # 答案 24
9八、如下代碼輸出是什麼,請給出答案並解釋
def multipliers(): return [lambda x: x * i for i in range(4)] print([m(2) for m in multipliers()]) # 答案: [6, 6, 6, 6] [0, 2, 4, 6] # 閉包函數延遲綁定問題。 # 請修改 multipliers 的定義來產生指望的結果 def multipliers(): return [lambda x, i=i: x * i for i in range(4)] print([m(2) for m in multipliers()])
9九、寫函數
''' 有一個數據結構以下所示,請編寫⼀個函數從該結構數據中返回由指定的字段和對應的值組成的字典。若是指定字段不存在,則跳過該字段。 ''' data:{ "time":"2016-08-05T13:13:05", "some_id":"ID1234", "grp1":{"fld1":1, "fld2":2,}, "xxx2":{"fld3":0, "fld4":0.4,}, "fld6":11, "fld7": 7, "fld46":8 } # fields:由"|"鏈接的以 fld 開頭的字符串, 如 fld2|fld7|fld29 # 答案一: def select(data, fields): result = {} field_lst = fields.split('|') for key in data: if key in field_lst: result[key] = data[key] elif type(data[key]) == dict: res = select(data[key], fields) result.update(res) return result data = {"time": "2016-08-05T13:13:05", "some_id": "ID1234", "grp1": {"fld1": 1, "fld2": 2}, "xxx2": {"fld3": 0, "fld5": 0.4}, "fld6": 11, "fld7": 7, "fld46": 8} fields = 'fld2|fld3|fld7|fld19' print(select(data, fields)) # 答案二: def select(data,fields,result = {}): field_lst = fields.split('|') for key in data: if key in field_lst: result[key] = data[key] elif type(data[key]) == dict: select(data[key], fields) return result data={"time":"2016-08-05T13:13:05", "some_id":"ID1234", "grp1":{ "fld1":1,"fld2":2}, "xxx2":{ "fld3":0,"fld5":0.4}, "fld6":11, "fld7":7, "fld46":8} fields = 'fld2|fld3|fld7|fld19' select(data,fields) print(select(data,fields)) ------------------- {'fld2': 2, 'fld3': 0, 'fld7': 7} {'fld2': 2, 'fld3': 0, 'fld7': 7}
閉包(closure)是函數式編程的重要的語法結構。 閉包也是一種組織代碼的結構,它一樣提升了代碼的可重複使用性。 當一個內嵌函數引用其外部 做 做用域的變量,咱們就會獲得一個閉包. 總結一下,建立一個閉包必須知足如下幾點: 必須有一個內嵌函數 內嵌函數必須引用外部函數中的變量 外部函數的返回值必須是內嵌函數
10一、Python函數調用的時候參數的傳遞方式是值傳遞仍是引用傳遞?
Python的參數傳遞有:位置參數、默認參數、可變參數、關鍵字參數。 函數的傳值究竟是值傳遞仍是引用傳遞,要分狀況: 不可變參數值傳遞: 像整數和字符串這樣的不可變對象,是經過拷貝進行傳遞的,由於你不管如何都不可能在原處改變 可變對象: 可變參數是引用傳遞的: 好比像列表,字典這樣的對象是經過引用傳遞、和C語言裏面的用指針傳遞數組很類似, 可變對象能在函數內部改變。
10二、對缺省參數的理解?
缺省參數指在調用函數的時候沒有傳入參數的狀況下,調用默認的參數, 在調用函數的同時賦值時,所傳入的參數會替代默認參數。 *args 是不定長參數,他能夠表示輸入參數是不肯定的,能夠是任意多個。 **kwargs 是關鍵字參數,賦值的時候是以鍵 = 值的方式,參數是能夠任意多對在定義函數的時候 不肯定會有多少參數會傳入時,就能夠使用兩個參數。
Python中一切皆對象,函數名是函數在內存中的空間,也是一個對象。
10四、Python中pass語句的做用是什麼?
在編寫代碼時只寫框架思路,具體實現還未編寫就能夠用 pass 進行佔位,使程序不報錯,不會進 行任何操做。
10五、有這樣一段代碼,print c會輸出什麼,爲何?
a = 10 b = 20 c = [a] a = 15 print(a) print(b) print(c) --------------- # 15 # 20 # [10] 答:[10]對於字符串、數字,傳遞是相應的值
10六、map函數和reduce函數?
①從參數方面來說: map()包含兩個參數,第一個參數是一個函數,第二個是序列(列表 或元組)。其中,函數(即 map 的第一個參數位置的函數)能夠接收一個或多個參數。 reduce()第一個參數是函數,第二個是序列(列表或元組)。可是,其函數必須接收兩個參數。 ②從對傳進去的數值做用來說: map()是將傳入的函數依次做用到序列的每一個元素,每一個元素都是獨自被函數「做用」一次 。 reduce()是將傳人的函數做用在序列的第一個元素獲得結果後,把這個結果繼續與下一個元素做用 (累積計算)。
遞歸的終止條件通常定義在遞歸函數內部,在遞歸調用前要作一個條件判斷,根據判斷的結果選擇 是繼續調用自身,仍是 return;返回終止遞歸。 終止的條件: 1.判斷遞歸的次數是否達到某一限定值 最大遞歸層數998 2.判斷運算的結果是否達到某個範圍等,根據設計的目的來選擇
10八、回調函數,如何通訊的?
回調函數是把函數的地址做爲參數傳遞給另外一個函數,將整個函數看成一個對象,賦值給調用的函數。
10九、Python主要的內置數據類型都有哪些?print dir ( 'a' )的輸出?
內建類型:布爾類型、數字、字符串、列表、元組、字典、集合; 輸出字符串‘a’的內建方法;
1十、print(list(map(lambda x:x*x,[y for y in range(3)])))的輸出?
[0, 1, 4]
判斷一個對象裏面是否有name屬性或者name方法,返回bool值, 有name屬性(方法)返回True,不然返回False 注意:name要使用引號括起來 class function_demo(object): name = 'demo' def run(self): return "hello function" functiondemo = function_demo() res = hasattr(functiondemo, 'name') # 判斷對象是否有name 屬性,True res = hasattr(functiondemo, "run") # 判斷對象是否有run方法,True res = hasattr(functiondemo, "age") # 判斷對象是否有age屬性,False print(res)
獲取對象object的屬性或者方法, 若是存在則打印出來,若是不存在,打印默認值,默認值可選。 注意:若是返回值是對象的方法,則打印結果是:方法的內存地址, 若是須要運行這個方法,能夠在後面添加括號() 1. functiondemo = function_demo() 2. getattr(functiondemo, 'name') #獲取name屬性,存在就打印出來--- demo 3. getattr(functiondemo, "run") #獲取run方法,存在打印出 方法的內存地址---<bound method function_demo.run of <__main__.function_demo object at 0x10244f320>> 4. getattr(functiondemo, "age") #獲取不存在的屬性,報錯以下: 5. Traceback (most recent call last): 6. File "/Users/liuhuiling/Desktop/MT_code/OpAPIDemo/conf/OPCommUtil.py", line 39, in <module> 7. res = getattr(functiondemo, "age") 8. AttributeError: 'function_demo' object has no attribute 'age' 9. getattr(functiondemo, "age", 18) #獲取不存在的屬性,返回一個默認值
給對象的屬性賦值,若屬性不存在,先建立再賦值 class function_demo(object): name = 'demo' def run(self): return "hello function" functiondemo = function_demo() res = hasattr(functiondemo, 'age') # 判斷age屬性是否存在,False print(res) setattr(functiondemo, 'age', 18 ) #對age屬性進行賦值,無返回值 res1 = hasattr(functiondemo, 'age') #再次判斷屬性是否存在,True print(res1)
11四、綜合使用:
class function_demo(object): name = 'demo' def run(self): return "hello function" functiondemo = function_demo() res = hasattr(functiondemo, 'addr') # 先判斷是否存在if res: addr = getattr(functiondemo, 'addr') print(addr)else: addr = getattr(functiondemo, 'addr', setattr(functiondemo, 'addr', '北京首都')) # addr = getattr(functiondemo, 'addr', '美國紐約') print(addr) reduce(lambda x,y:x*y,range(1,n+1))注意:Python3中取消了該函數
lambda函數是一個能夠接受任意多個參數(包括可選參數) 而且返回單個表達式值的函數 一、lambda函數比較輕便,即用即扔,很適合須要完成一項功能, 可是此功能只在此一處使用,連名字都很隨意的狀況下 二、匿名函數,通常用來給filter,map這樣的函數式編程服務 三、做爲回調函數,傳遞給某些應用,好比消息處理
11六、下面代碼輸出結果是什麼?請解釋
def multipliers(): return [lambda x : i * x for i in range(4)] print [m(2) for m in multipliers()] 上面代碼輸出的結果是[6, 6, 6, 6] (不是咱們想的[0, 2, 4, 6])。 上述問題產生的緣由是Python閉包的延遲綁定。 這意味着內部函數被調用時,參數的值在閉包內進行查找。 所以,當任何由multipliers()返回的函數被調用時, i的值將在附近的範圍進行查找。 那時,無論返回的函數是否被調用,for循環已經完成,i被賦予了最終的值3。 所以,每次返回的函數乘以傳遞過來的值3,由於上段代碼傳過來的值是2,它們最終返回的都是6。 下面是解決這一問題的一些方法: 一種解決方法就是用Python生成器。 def multipliers(): for i in range(4): yield lambda x : i * x 另外一種解決方案是創造一個閉包,利用默認函數當即綁定 def multipliers(): return [lambda x, i=i : i * x for i in range(4)]
11七、什麼是lambda函數?好處?寫一個匿名函數求兩個數的和?
""" lambda 函數是匿名函數; 使用 lambda 函數能建立小型匿名函數。 這種函數得名於省略了用def聲明函數的標準步驟; """ # 答案 f = lambda x,y:x+y print(f(2017,2018))
11八、Python中裝飾器、迭代器的用法;描述dict的items()方法與iteritems()方法的不一樣
裝飾器是指對函數執行過程,作一些擴展, 甚至能夠更改自己函數的執行 迭代器是指遵循迭代器協議的對象, 這類對象在被for循環時, 每次迭代生成下一個項, 不用一開始就生成整個列表, 在python3中不存在iteritems, items方法返回可迭代對象 在python2中items()返回[(key,value)]的列表對象, iteritems()返回迭代器對象, iteritems()循環時不能夠增刪dict的內容
11九、def( a , b = [ ] ) 這種寫法有什麼陷阱?
函數的第二個默認參數是一個list, 當第一次執行的時候 實例化 了一個list, 第二次執行仍是用第一次執行的時候實例化的地址存儲, 因此三次執行的結果就是 [1, 1, 1] , 想每次執行只輸出[1] , 默認參數應該設置爲None。
120、如何判斷一個值是函數仍是方法?
from types import MethodType,FunctionType print(isinstance('1', FunctionType)) # False print(isinstance(lambda x:x, FunctionType)) # True ------------------ False True
一、簡述面向對象的三大特性
封裝: 把一堆數據屬性與方法數據放在一個容器中,這個容器就是對象。 讓對象能夠經過 "." 來調用對象中的數據屬性與方法屬性。 繼承: 繼承指的是子類能夠繼承父類的數據屬性與方法屬性, 並能夠對其進行修改或使用。 多態: 在python中的多態指的是讓多種類若具有 相似的數據屬性 與 方法屬性, 都統一好命名規範,這樣能夠提升開發者的代碼統一性,使得調用者更方便去理解。
二、什麼是鴨子模型?
在python中不會強制性要求全部人的代碼都統一規範,不統一也不會報錯, 若使用抽象類就會使python代碼強制統一規範, 這樣不符合python動態語言的特性。 因此讓你們都自覺統一好規範, 若你們的對象方法都相似的話就一種規範, 只要長得像鴨子,就稱之爲鴨子類型。
三、super的做用?
使用super()能夠在 子類中調用 父類的方法或屬性, 可能你會說, 子類原本就能夠調用父類中全部非私有的屬性或方法,而我如今說的是, 當子類中實現了某個方法, 父類中也有這個方法, 當你調用這個方法時, 既想執行子類的又想執行父類的, 在這種狀況下就能夠使用super()
mro全稱Method Resolution Order,指的是方法解析順序。 方法調用時就須要對當前類和基類進行搜索以肯定方法所在的位置。 而搜索的順序就是所謂的「方法解析順序」
C3算法最先被提出是用於Lisp的, 應用在Python中是爲了解決 原來基於深度優先搜索算法不知足本地優先級,和單調性的問題。 本地優先級:指聲明時父類的順序,好比C(A,B), 若是訪問C類對象屬性時,應該根據聲明順序,優先查找A類,而後再查找B類。 單調性:若是在C的解析順序中,A排在B的前面,那麼在C的全部子類裏,也必須知足這個順序。
__setattr__: 添加/修改屬性會觸發它的執行 __delattr__: 刪除屬性的時候會觸發 __getattr__: 只有在使用點調用屬性且屬性不存在的時候纔會觸發 __getattribute__: 無論是否存在,我都會執行
七、雙下劃線和單下劃線的區別?
單下劃線: 開始的成員變量叫作保護變量,意思是隻有類對象和子類對象本身能訪問到這些變量。 雙下劃線: 開始的是私有成員,意思是隻有類對象本身能訪問,連子類對象也不能訪問到這個數據。
八、實例變量和類變量的區別?
類變量是全部對象共有, 其中一個對象將它值改變, 其餘對象獲得的就是改變後的結果; 而實例變量則屬對象私有, 某一個對象將其值改變, 不影響其餘對象;
九、靜態方法和類方法區別?
Python的類就是個語法糖。 一個函數寫在類裏面和寫在類外面沒有區別, 惟一的區別就是參數, 所謂實例方法就是第一個參數是self, 所謂類方法就是第一個參數是class, 而靜態方法不須要額外的參數,因此必須區分。
十、isinstance 和 type的做用?
type和isinstance均可以判斷變量是否屬於某個內建類型 type只接收一個參數, 不但能夠判斷變量是否屬於某個類型, 並且能夠獲得參數變量 未知的 所屬的類型; 而isinstance只能判斷是否屬於某個已知類型, 不能直接獲得 變量 未知的 所屬的類型
with語句會在嵌套的代碼執行以後,自動關閉文件。 這種作法的還有另外一個優點就是, 不管嵌套的代碼是以何種方式結束的, 它都關閉文件。 若是在嵌套的代碼中發生異常, 它可以在外部exception handler catch異常前關閉文件。 若是嵌套代碼有return/continue/break語句, 它一樣可以關閉文件。
十二、下列數據結構中,哪種是不可迭代的
A. dict B. object C. set D. str # 答案: B
# 答案: 1.__new__方法 class Borg(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): ob = super(Borg, cls) cls._instance = ob.__new__(cls, *args, **kwargs) return cls._instance class MyClass(Borg): def __init__(self): self.a = 1 2.共享屬性 class Borg2(object): _state = {} def __new__(cls, *args, **kwargs): ob = super(Borg2, cls).__new__(cls, *args, **kwargs) ob.__dict__ = cls._state return ob class MyClass(Borg2): def __init__(self): self.a = 1 3.裝飾器 def singleton(cls, *args, **kwargs): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return getinstance @singleton class MyClass(object): def __init__(self): self.a = 1 4.import方法 # mysingleton .py class MyClass(object): def __init__(self): self.a = 1 s_myclass = MyClass() from mysingleton import s_myclass s_myclass.a
基本格式 with context_expression [as target(s)]: with-body 這裏 context_expression 要返回一個上下文管理器對象, 該對象並不賦值給 as 子句中的 target(s) , 若是指定了 as 子句的話, 會將上下文管理器的 __enter__() 方法的返回值賦值給 target(s)。 target(s) 能夠是單個變量, 或者由「()」括起來的元組(不能是僅僅由「,」分隔的變量列表,必須加「()」)。 自定義的上下文管理器要實現上下文管理協議所須要的 __enter__() 和 __exit__() 兩個方法 context_manager.__enter__() :進入上下文管理器的運行時上下文,在語句體執行前調用。 with 語句將該方法的返回值賦值給 as 子句中的 target, 若是指定了 as 子句的話 context_manager.__exit__(exc_type, exc_value, exc_traceback) :退出與上下文管理器相關的運行時上下文,返回一個布爾值表示是否對發生的異常進行處理。
1五、Python中如何判斷一個對象是不是可調用?哪些對象能夠是可調用對象?如何定義一個類,使其對象自己就是可調用對象?
# python 中如何判斷一個對象是否可調用 def func(): pass print(callable(func)) # True # 哪些對象能夠是可調用對象 1.類對象 2.全部帶有_call_()方法的對象 # 如何定義一個類,使其對象自己就是可調用對象 一個類實例也能夠變成一個可調用對象,只須要實現一個特殊方法call()。
1六、請實現一個棧
class Stack(object) : def __init__(self,size): #類的構造函數 self.size = size self.stack = [] def __str__(self): #類的字符串輸出方法,相似於java的.toString()方法 return str(self.stack) def getSize(self) : #獲取棧當前大小 return len(self.stack) def push(self, x) : #入棧,棧滿拋異常 if self.isfull() : #return -1 raise Exception("Stack is full") self.stack.append(x) def pop(self) : #出棧,棧空拋異常 if self.isempty() : #return -1 raise Exception("Stack is empty") topElement = self.stack[-1] self.stack.remove(topElement) return topElement def isempty(self) : #判斷棧空 if len(self.stack) == 0 : return True return False def isfull(self) : #判斷棧滿 if len(self.stack) == self.size : return True return False
17關於Python類的繼承不正確的說法是?(多選)
A. Python類沒法繼承 B. 能夠繼承, 沒法執行父類的構造函數 C. 能夠有多個父類 D. 只能有一個父類 # 答案 ''' A D '''
1八、實現一個hashtable類,對外暴露的有add和get方法,知足如下測試代碼
def test(): import uuid names = {"name", "web", "python"} ht = HashTable() for key in names: value = uuid.uuid4() ht.add(key, value) print("add 元素", key, value) for key in names: v = ht.get(key) print("get 元素", key, v) # 答案: class HashMap(object): def __init__(self): # 初始化總表爲,容量爲2的表格(含兩個子表) self.maps = BetterMap(2) self.num = 0 # 表中數據個數 def get(self,k): return self.maps.get(k) def add(self, k, v): # 若當前元素數量達到臨界值(子表總數)時,進行重排操做 # 對總表進行擴張,增長子表的個數爲當前元素個數的兩倍! if self.num == len(self.maps.maps): self.resize() # 往重排事後的 self.map 添加新的元素 self.maps.add(k, v) self.num += 1 def resize(self): """ 重排操做,添加新表, 注意重排鬚要線性的時間 """ # 先創建一個新的表,子表數 = 2 * 元素個數 new_maps = BetterMap(self.num * 2) for m in self.maps.maps: # 檢索每一箇舊的子表 for k,v in m.items: # 將子表的元素複製到新子表 new_maps.add(k, v) self.maps = new_maps # 令當前的表爲新表
1九、請用兩個隊列來實現一個棧(給出代碼便可)
# 答案: class StackWithTwoQueues(object): #定義兩個空隊列 def __init__(self): self.queue1 = [] self.queue2 = [] #入棧 def push(self, item): self.queue1.append(item) #出棧 def pop(self): if len(self.queue1) == 0: return(None) while(len(self.queue1) != 1): self.queue2.append(self.queue1.pop(0)) self.queue1, self.queue2 = self.queue2, self.queue1 return (self.queue2.pop()) #test if __name__ == '__main__': ss = StackWithTwoQueues() list = [0, 1, 2, 3, 4] for i in range(5): ss.push(list[i]) print(list) for i in range(5): print(ss.pop(), ',', end = '') #output #[0, 1, 2, 3, 4] #4, 3, 2, 1, 0
20、已知以下鏈表類,請實現單鏈表逆置
class Node: def __init__(self, value, next): self.value = value self.next = next # 答案: class Solution: def ReverseList(self, pHead): if not pHead or not pHead.next: return pHead last = None while pHead: tmp = pHead.next pHead.next = last last = pHead pHead = tmp return last
2一、類的加載順序(類中有繼承有構造有靜態)?
一、 類對象 二、 實例對象 三、 self變量名稱問題 四、 類屬性、實例變量、局部變量 五、 類方法 六、 實例方法 七、 類方法與實例方法相互調用 八、 靜態方法 九、 繼承時三類方法的影響
2二、參考下面代碼片斷
class Context: pass with Context as ctx: ctx.do_something() # 請在 Context 類下添加代碼完成該類的實現 # 答案: class Context(object): def __enter__(self): pass def __exit__(self, exc_type, exc_val, exc_tb): if all([exc_type, exc_val, exc_tb]): print 'handler except' print 'exception {}'.format(exc_val) return True def main(): with tornado.stack_context.StackContext(Contextor): async_task()
2三、如下代碼輸出是什麼?請給出答案並解釋
class Parent: x = 1 class Child1(Parent): pass class Child2(Parent): pass print(Parent.x, Child1.x, Child2.x) Child1.x = 2 print(Parent.x, Child1.x, Child2.x) Child1.x = 3 print(Parent.x, Child1.x, Child2.x) # 答案 ''' 1 1 1 1 2 1 1 3 1 '''
2四、函數del_node(self,data)的功能;在根節點指針爲root的二叉樹(又稱二叉 排序樹)上排序除數值爲K的節點,若刪除成功,返回 0 ,不然返回-1,概述節點的 定義類型爲
class Node(object): def __init__(self, data): self.data = data # 節點的數值 self.left_child = Node # 指向左右子樹的指針 self.right_child = Node def set_data(self, data): self.data = data # 答案:
2五、請給出下面代碼片斷的輸出,請簡述上面代碼須要改進的地方?
class Singleton: _instance = None def __new__(cls, *args, **kwargs): print("New") if cls._instance is None: print("Create") cls._instance = super().__new__(cls,*args, **kwargs) return cls._instance def __init__(self): print("Initalize") self.prop = None s1 = Singleton() s2 = Singleton() # 答案:
2六、請簡述解釋Python中的staticmethod(靜態方法)和classmethod(類方法),並將如下代碼填寫完整
class A: def foo(self, x): print('executing class_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() # 調用 foo 函數,參數傳入 1 # ____________________ # 調用 class_foo 函數,參數傳入 1 # ____________________ # 調用 static_foo 函數,參數傳入 1 # ____________________ # 答案: a.foo(1) A.class_foo(1) a.static_foo(1) A.static_foo(1)
2七、已知一個訂單對象(tradeOrder)有以下字段:
字段英文名 中文名 字段類型 取值 Id 主鍵 Long 123456789 Name 姓名 String 張三 Items 商品列表集合 List<商品> (關聯商 品) 查找商品對象,一個訂單有兩個商品. 商品字段任意取值。 IsMember 是不是會員 Boolean True CouponAmount 優惠券金額 Bigdecimal Null 商品對象 字段英文名稱 中文名 字段類型 取值 Id 主鍵 Long 987654321 Name 商品名稱 String 手機 問題: 若將訂單對象轉成 JSON 格式,請書寫出轉換後的 JSON 字符串。
2八、寫代碼(棧與隊列)
編程實現一個先進先出的隊列類, 能指定初始化時的隊列大小, 以及 enqueue,dequeue,isempty, is full 四種方法 使用方法以下: s = Queue(2) # 初始化一個大小爲 2 的隊列 s.is_empty() # 初始化後, 隊列爲空, 返回 True s.enqueue(1) # 將 1 加入隊列 s.enqueue(2) # 將 2 加入隊列 s.isfull() # 加入了兩個元素, 隊列已滿, 返回 True 6. s.dequeue() # 移除一個元素, 返回 1 s.dequeue() # 移除一個元素, 返回 2 s.is_empty() # 隊列已經爲空, 返回 True
一、Python的底層網絡交互模塊有哪些?
socket, urllib , urllib3 , requests, grab, pycurl
應用層:HTTP,FTP,NFS 表示層:Telnet,SNMP 會話層:SMTP,DNS 傳輸層:TCP,UDP 網絡層:IP,ICMP,ARP, 數據鏈路層:Ethernet,PPP,PDN,SLIP,FDDI 物理層:IEEE 802.1A,IEEE 802.11
三、什麼是C/S和B/S架構?
軟件系統體系結構: C/S體系結構: 指的是客戶端/服務端 例如:QQ B(browser)/S體系結構: 指的是瀏覽器/服務端 例如12306(網站);購物網站 二者區別: C/S :優勢:交互性好,對服務器壓力小,安全 ; 缺點:服務器更新時須要同步更新客戶端 B/S :優勢:不須要更新客戶端 缺點:交互性差,安全性低
三次握手過程: 1首先客戶端向服務端發送一個帶有SYN 標誌,以及隨機生成的序號100(0字節)的報文 2服務端收到報文後返回一個報文(SYN200(0字節),ACk1001(字節+1))給客戶端 3客戶端再次發送帶有ACk標誌201(字節+)序號的報文給服務端 至此三次握手過程結束,客戶端開始向服務端發送數據。 1客戶端向服務端發起請求:我想給你通訊,你準備好了麼? 2服務端收到請求後迴應客戶端:I'ok,你準備好了麼 3客戶端禮貌的再次回一下客戶端:準備就緒,我們開始通訊吧! 整個過程跟打電話的過程如出一轍:1喂,你在嗎2在,我說的你聽獲得不3恩,聽獲得(接下來請 開始你的表演) 補充:SYN:請求詢問,ACk:回覆,迴應。 四次揮手過程: 因爲TCP鏈接是能夠雙向通訊的(全雙工),所以每一個方向都必須單獨進行關閉(這句話纔是 精闢,後面四個揮手過程都是其具體實現的語言描述) 四次揮手過程,客戶端和服務端均可以先開始斷開鏈接 1客戶端發送帶有fin標識的報文給服務端,請求通訊關閉 2服務端收到信息後,回覆ACK答應關閉客戶端通訊(鏈接)請求 3服務端發送帶有fin標識的報文給客戶端,也請求關閉通訊 4客戶端迴應ack給服務端,答應關閉服務端的通訊(鏈接)請求
五、什麼是arp協議?
ARP協議,全稱「Address Resolution Protocol」,中文名是地址解析協議, 使用ARP協議可實現經過IP地址得到對應主機的物理地址(MAC地址)。
# TCP和UDP的區別? ''' 一、TCP面向鏈接(如打電話要先撥號創建鏈接);UDP是無鏈接的,即發送數據以前不須要創建鏈接 二、TCP提供可靠的服務。也就是說,經過TCP鏈接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付 三、TCP面向字節流,其實是TCP把數據當作一連串無結構的字節流;UDP是面向報文的 UDP沒有擁塞控制,所以網絡出現擁塞不會使源主機的發送速率下降(對實時應用頗有用,如IP電話,實時視頻會議等) 四、每一條TCP鏈接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通訊 五、TCP首部開銷20字節;UDP的首部開銷小,只有8個字節 六、TCP的邏輯通訊信道是全雙工的可靠信道,UDP則是不可靠信道 ''' # 爲什麼基於tcp協議的通訊比基於udp協議的通訊更可靠? ''' tcp:可靠 對方給了確認收到信息,才發下一個,若是沒收到確認信息就重發 udp:不可靠 一直髮數據,不須要對方迴應 '''
七、什麼是局域網和廣域網?
二者範圍不同: 局域網就是在固定的一個地理區域內由2臺以上的電腦用網線和其餘網絡設備搭建而成的 一個封閉的計算機組,範圍在幾公里之內; 廣域網是一種地域跨度很是大的網絡集合,範圍在幾十千米到幾千千米。 二者的IP地址設置不同: 局域網裏面,必須在網絡上有一個惟一的IP地址,這個IP地址是惟一的, 在另一個局域網,這個IP地址仍然可以使用。 廣域網上的每一臺電腦(或其餘網絡設備)都有一個或多個廣域網IP地址,並且不能重複。
Socket是應用層與TCP/IP協議族通訊的中間軟件抽象層,它是一組接口。 在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面, 對用戶來講,一組簡單的接口就是所有。 服務端: 建立socket對象,綁定ip端口bind(), 設置最大連接數listen(), accept()與客戶端的connect()建立雙向管道, send(), recv(),close() 客戶端: 建立socket對象,connect()與服務端accept()建立雙向管道, send(),recv(),close()
粘包: 數據粘在一塊兒,主要由於:接收方不知道消息之間的界限,不知道一次性提取多少字節的數據形成的數據量比較小,時間間隔比較短,就合併成了一個包,這是底層的一個優化算法(Nagle算法)
十、IO多路複用的做用?
I/O多路複用是用於提高效率,單個進程能夠同時監聽多個網絡鏈接IO。 舉例: 經過一種機制,能夠監視多個文件描述符,一旦描述符就緒(讀就緒和寫就緒),能通知程序進行相應的讀寫操做,I/O多路複用避免阻塞在io上,本來爲多進程或多線程來接收多個鏈接的消息變爲單進程或單線程保存多個socket的狀態後輪詢處理。
十一、什麼是防火牆以及做用?
在互聯網上防火牆是一種很是有效的網絡安全模型,經過它能夠隔離風險區域(即Internet或有必定風險的網絡)與安全區域(局域網)的鏈接,同時不會妨礙人們對風險區域的訪問。因此它通常鏈接在覈心交換機與外網之間。 過濾進出網絡的數據 管理進出訪問網絡的行爲 封堵某些禁止業務 記錄經過防火牆信息內容和活動 對網絡攻擊檢測和告警
I/O多路複用的本質就是用select/poll/epoll,去監聽多個socket對象, 若是其中的socket對象有變化,只要有變化,用戶進程就知道了。 select是不斷輪詢去監聽的socket,socket個數有限制,通常爲1024個; poll仍是採用輪詢方式監聽,只不過沒有個數限制; epoll並非採用輪詢方式去監聽了,而是當socket有變化時經過回調的方式主動告知用戶進程。 nginx爲啥這麼厲害: 底層網絡模型,複用
進程:操做系統資源分配的最小單位,擁有獨立的資源和地址空間 線程:CPU調度的單位 統一進程中的線程是資源共享的。 協程是用戶級別的,程序之間的切換由用戶自行處理,節省了CPU的調度時間。
全局解釋鎖, 每次只能一個線程得到cpu的使用權: 爲了線程安全, 也就是爲了解決多線程之間的數據完整性和狀態同步而加的鎖, 由於咱們知道線程之間的數據是共享的。
# 線程池 import threadpool, time with open(r'../uoko_house_id.txt', 'r', encoding='utf-8') as f: # with open語句表示通用的打開文件的方式,此處用來獲取須要爬取參數的列表 roomIdLi = f.readlines() roomIdList = [x.replace('\n', '').replace(' ', '') for x in roomIdLi] print(roomIdList) li = [[i, item] for i, item in enumerate(roomIdList)] # enumerate()將列表中元素和其下標從新組合輸出 def run(roomId): """對傳入參數進行處理""" print('傳入參數爲:', roomId) time.sleep(1) def main(): roomList = li # 房間信息 start_time = time.time() print('啓動時間爲:', start_time) pool = threadpool.ThreadPool(10) requests = threadpool.makeRequests(run, roomList) [pool.putRequest(req) for req in requests] pool.wait() print("共用時:", time.time() - start_time) if __name__ == '__main__': main() # 進程池 from multiprocessing.pool import Pool from time import sleep def fun(a): sleep(5) print(a) if __name__ == '__main__': p = Pool() for i in range(10): p.apply_async(fun, args=(i,)) p.close() p.join() print("end")
1六、threading.local的做用?
爲每一個線程建立一個獨立的空間,使得線程對本身的空間中的數據進行操做(數據隔離)。 import threading from threading import local import time obj = local() def task(i): obj.xxxxx = i time.sleep(2) print(obj.xxxxx, i) for i in range(10): # 開啓了10個線程 t = threading.Thread(target=task, args=(i,)) t.start()
python提供了多種進程通訊的方式,主要Queue和Pipe這兩種方式,Queue用於多個進程間實現通訊,Pipe是兩個進程的通訊。 # Queue from multiprocessing import Process, Queue import os,time,random #寫數據進程執行的代碼 def proc_write(q,urls): print 'Process is write....' for url in urls: q.put(url) print 'put %s to queue... ' %url time.sleep(random.random()) #讀數據進程的代碼 def proc_read(q): print('Process is reading...') while True: url = q.get(True) print('Get %s from queue' %url) if __name__ == '__main__': #父進程建立Queue,並傳給各個子進程 q = Queue() proc_write1 = Process(target=proc_write,args=(q,['url_1','url_2','url_3'])) proc_write2 = Process(target=proc_write,args=(q,['url_4','url_5','url_6'])) proc_reader = Process(target=proc_read,args=(q,)) #啓動子進程,寫入 proc_write1.start() proc_write2.start() proc_reader.start() #等待proc_write1結束 proc_write1.join() proc_write2.join() #proc_raader進程是死循環,強制結束 proc_reader.terminate() # PIPE import multiprocessing import os,time,random #寫數據進程執行的代碼 def proc_send(pipe,urls): #print 'Process is write....' for url in urls: print 'Process is send :%s' %url pipe.send(url) time.sleep(random.random()) #讀數據進程的代碼 def proc_recv(pipe): while True: print('Process rev:%s' %pipe.recv()) time.sleep(random.random()) if __name__ == '__main__': #父進程建立pipe,並傳給各個子進程 pipe = multiprocessing.Pipe() p1 = multiprocessing.Process(target=proc_send,args=(pipe[0],['url_'+str(i) for i in range(10) ])) p2 = multiprocessing.Process(target=proc_recv,args=(pipe[1],)) #啓動子進程,寫入 p1.start() p2.start() p1.join() p2.terminate()
1八、什麼是併發和並行?
併發:同一時刻只能處理一個任務, 但能夠交替處理多個任務。(一個處理器同時處理多個任務) 並行:同一時刻能夠處理多個任務。(多個處理器或者是多核的處理器同時處理多個不一樣的任務) 類比:併發是一我的同時吃三個饅頭,而並行是三我的同時吃三個饅頭。
1九、同步和異步,阻塞和非阻塞的區別?
同步:執行一個操做以後,須要主動等待返回結果; 異步:執行一個操做以後,不須要主動等待返回結果,若接收到結果通知,再回來執行剛纔沒執行完的操做。 同步和異步關心的問題是:要不要主動等待結果。 阻塞:在執行一個操做時,不能作其餘操做; 非阻塞:在執行一個操做時,能作其餘操做。 阻塞和非阻塞關心的問題是:能不能作其餘操做。
20、路由器和交換機的區別?
交換機:是負責內網裏面的數據傳遞(arp協議)根據MAC地址尋址。 路由器:在網絡層,路由器根據路由表,尋找該ip的網段。 路由器:能夠把一個IP分配給不少個主機使用,這些主機對外只表現出一個IP。 交換機:能夠把不少主機連起來,這些主機對外各有各的IP。 交換機:是作端口擴展的,也就是讓局域網能夠連進來更多的電腦。 路由器:是用來作網絡鏈接,也就是鏈接不一樣的網絡。
在互聯網上,全部的地址都是ip地址,現階段主要是IPv4(好比:110.110.110.110)。 可是這些ip地址太難記了,因此就出現了域名(好比http://baidu.com)。 域名解析就是將域名,轉換爲ip地址的這樣一種行爲。
2二、如何修改本地hosts文件?
Hosts是一個沒有擴展名的系統文件, 能夠用記事本等工具打開, 其做用就是將一些經常使用的網址域名與其對應的IP地址創建一個關聯「數據庫」, 當用戶在瀏覽器中輸入一個須要登陸的網址時, 系統會首先自動從Hosts文件中尋找對應的IP地址, 一旦找到, 系統會當即打開對應網頁, 若是沒有找到, 則系統會再將網址提交給DNS域名解析服務器進行IP地址的解析。 文件路徑:C:\WINDOWS\system32\drivers\etc。 將127.0.0.1 www.163.com 添加在最下面 修改後用瀏覽器訪問「www.163.com」會被解析到127.0.0.1,致使沒法顯示該網頁。
生產者與消費者模式是經過一個容器來解決生產者與消費者的強耦合關係, 生產者與消費者之間不直接進行通信, 而是利用阻塞隊列來進行通信, 生產者生成數據後直接丟給阻塞隊列, 消費者須要數據則從阻塞隊列獲取, 實際應用中, 生產者與消費者模式則主要解決生產者與消費者的 生產與消費的速率不一致的問題, 達到平衡生產者與消費者的處理能力,而阻塞隊列則至關於緩衝區。 應用場景:用戶提交訂單,訂單進入引擎的阻塞隊列中,由專門的線程從阻塞隊列中獲取數據並處理。 優點: 1:解耦 假設生產者和消費者分別是兩個類。 若是讓生產者直接調用消費者的某個方法, 那麼生產者對於消費者就會產生依賴(也就是耦合)。 未來若是消費者的代碼發生變化, 可能會影響到生產者。 而若是二者都依賴於某個緩衝區, 二者之間不直接依賴, 耦合也就相應下降了。 2:支持併發 生產者直接調用消費者的某個方法,還有另外一個弊端。 因爲函數調用是同步的(或者叫阻塞的), 在消費者的方法沒有返回以前, 生產者只能一直等着 而使用這個模型, 生產者把製造出來的數據只須要放在緩衝區便可, 不須要等待消費者來取。 3:支持忙閒不均 緩衝區還有另外一個好處。 若是製造數據的速度時快時慢,緩衝區的好處就體現出來了。 當數據製造快的時候,消費者來不及處理, 未處理的數據能夠暫時存在緩衝區中。 等生產者的製造速度慢下來, 消費者再慢慢處理掉。
2四、什麼是cdn?
cdn:內容分發網絡 目的: 使用戶能夠就近到服務器取得所需內容,解決 Internet網絡擁擠的情況,提升用戶訪問網站的響應速度。
2五、程序從FlagA執行到FlagB的時間大體爲多少秒
import threading import time def _wait(): time.sleep(60) # FlagA t = threading.Thead(target=_wait, daemon=False) t.start() # FlagB # 答案: # 60s 由於沒有設置守護線程,須要等子線程跑完主線程才結束
2六、有A.txt 和 B.txt兩個文件,使用多進程和進程池的方式分別讀取兩個文件
# 多進程 """經過多進程加速讀取excel的測試""" __author__ = "hanyaning@deri.energy" import os.path import time from service import logger import pandas as pd from multiprocessing import Process, Manager startTime = time.time() logger = logger.MyLogger("multi_process").getLogger() def getExcelData(path, return_data=None, file_name=""): global startTime logger.info("開始讀取Excel文件,當前進程pid:" + str(os.getpid())) if not os.path.exists(path): raise FileNotFoundError() if os.path.isfile(path): return_data[file_name] = pd.read_excel(path, skiprows=1, skipfooter=1) logger.info("讀取Excel文件完畢,當前進程pid:" + str(os.getpid())) if __name__ == "__main__": excel_path = os.path.join(os.getcwd(), "../excels") xls_names = [x for x in os.listdir(excel_path) if x.endswith(".xls")] first = str(time.time() - startTime) logger.info("進入程序用時:" + first) p_list = [] # Manager相似於同步數據管理工具,可在多進程時實現各進程操做同一個數據,好比這裏經過它組織返回值 manager = Manager() # Manager.dict()相似於共享變量,各個進程能夠修改它,經過每次添加不一樣的key值,能夠實現方法返回值的獲取 return_data = manager.dict() first = time.time() - startTime # 手動建立多個進程讀取,可能存在建立進程過多致使系統崩潰的狀況 for file_name in xls_names: p = Process(target=getExcelData, args=(os.path.join(excel_path, file_name), return_data, file_name)) p.start() p_list.append(p) print(p_list) """ 經測試,直到這裏都還會延遲數秒才執行進程的target方法,儘管前面已經調用了start(),但進程並無當即執行 寡人認爲是系統建立進程須要時間,而且是建立好全部進程後才各進程纔開始工做,這裏要建立120個進程花費了大多數的時間 後面在採用進程池時,當設置最大進程數爲120時,依然花費了大把的時間,而設置爲10時,大大縮小了建立進程到執行target方法所要等待的時間 這也證實了寡人的觀點,至於正確與否,寡人先跟代碼去了,且等下回分解 """ for p in p_list: # 若是有子進程沒有執行完,須要先阻塞主進程 p.join() logger.info("各進程執行完畢") # 獲取返回值字典爲列表 data_frames = return_data.values() # 合併列表爲一個dataFrame data = pd.DataFrame() for da in data_frames: data = data.append(da) endTime = time.time() print(endTime - startTime) print(len(data)) # 進程池 """經過多進程加速讀取excel的測試""" __author__ = "hanyaning@deri.energy" import os.path import time from service import logger import pandas as pd from multiprocessing import Pool logger = logger.MyLogger("multi_process").getLogger() def getExcelData(path): logger.info("開始讀取excel,當前進程pid:" + str(os.getpid())) data = pd.DataFrame() if not os.path.exists(path): raise FileNotFoundError() if os.path.isfile(path): logger.info("讀取Excel文件完畢,當前進程pid:" + str(os.getpid())) return data.append(pd.read_excel(path, skiprows=1, skipfooter=1), sort=False) if __name__ == "__main__": excel_path = os.path.join(os.getcwd(), "../excels") xls_names = [x for x in os.listdir(excel_path) if x.endswith(".xls")] startTime = time.time() p_list = [] # 使用進程池Pool pool = Pool(processes=10) pool_data_list = [] data = pd.DataFrame() for file_name in xls_names: # 須要注意不能直接在這裏調用get方法獲取數據,緣由是apply_async後面 get()等待線程運行結束纔會下一個,這裏多進程會變成阻塞執行 pool_data_list.append(pool.apply_async(getExcelData, (os.path.join(excel_path, file_name),))) pool.close() # 須要阻塞如下,等全部子進程執行完畢後主線程才繼續執行 pool.join() for pool_data in pool_data_list: # 這裏再使用get()方法能夠獲取返回值 data = data.append(pool_data.get()) endTime = time.time() print(endTime - startTime) print(len(data))
2七、如下那些常見的(TCP的報文格式TCPFlags)?(多選)
A.SYN B.RST C.ACK D.URG 答案: A,B,C,D
2八、下面關於網絡七層和四層的口述,錯誤的是?
A.SNMP工做在四層 B.四層是指網絡的傳輸層, 主要包括IP和端口信息 C.七層是指網絡的應用層(協議層), 好比http協議就工做在七層 D.四層主要應用於TCP和UDP的代理, 七層主要應用於HTTP等協議的代理 # 答案: A
2九、tracerroute通常使用的是哪一種網絡協議
A.VRRP B.UDP C.ARP D.ICMP 答案: D
30、iptables知識考察,根據要求寫出防火牆規則?
A.屏蔽192.168.1.5訪問本機dns服務端口 B.容許10.1..0/2訪問本機的udp88889999端口 答案: iptables -A INPUT -p ICMP --icmp-type 8 -m time --timestart 00:00:00 --timestop 23:59:59 --weekdays Mon -j DROP
31.業務服務器192.168.1.2訪問192.168.1.3數據接口, 沒法正常返回數據, 請根據以上信息寫出排查思
路。
首先檢查192.168.1.3能不能ping通, 防火牆有沒有關閉,配 置有沒有成功, nginx服務有沒有啓動, 排查報錯相關的代碼
''' 要求: 1.實現server端的功能便可 2.遵循基本語言編程規範 ''' # 答案: # 服務端: # coding=utf-8 import socket server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(('', 8888)) server.listen(5) #等待客戶端鏈接 while True: (client, address) = server.accept() data = client.recv(4096) print data client.send("hello") client.close() # 客戶端 import socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(('127.0.0.1', 8888)) client.send("My name is client") message = client.recv(4096) print message client.close()
33.談一下對於多線程編程的理解, 對於CPU密集型怎樣使用多線程, 說說線程池, 線程鎖的用法, 有沒有用
過multiprocessing或concurrent.future?
CPU密集型使用多進程 IO密集型使用多線程 加鎖 鎖定 釋放
34.關於守護線程的說法, 正確的是
A.全部非守護線程終止, 即便存在守護線程, 進程運行終止 B.全部守護線程終止, 即便存在非守護線程, 進程運行終止 C.只要有守護線程或者非守護線程其中之一存在, 進程就不會終止 D.只要全部的守護線程和非守護線程中終止運行以後, 進程纔會終止 答案: A
35.TCP協議在每次創建或者拆除鏈接時, 都要在收發雙方之間交換()報文
A.一個 B.兩個 C.三個 D.四個 答案: C
p.join([timeout]):主線程等待p終止(強調:是主線程處於等的狀態,而p是處於運行的狀態)。 timeout是可選的超時時間, 須要強調的是,p.join只能join住start開啓的進程, 而不能join住run開啓的進程 p.daemon:默認值爲False, 若是設爲True,表明p爲後臺運行的守護進程, 當p的父進程終止時,p也隨之終止, 而且設定爲True後,p不能建立本身的新進程,必須在p.start()以前設置
GIL:全局解釋器鎖。 每一個線程在執行的過程都須要先獲取GIL, 保證同一時刻只有一個線程能夠執行字節碼。 線程釋放GIL鎖的狀況: 在IO操做等可能會引發阻塞的system call以前, 能夠暫時釋放GIL, 但在執行完畢後, 必須從新獲取GIL Python 3.x使用計時器(執行時間達到閾值後,當前線程釋放GIL) 或Python 2.x,tickets計數達到100 Python使用多進程是能夠利用多核的CPU資源的。 多線程爬取比單線程性能有提高,由於遇到IO阻塞會自動釋放GIL鎖
38.曾經在哪裏使用過: 線程、進程、協程?
在寫高併發的服務端代碼時。 在寫高性能爬蟲的時候。
39.請使用yield實現一個協程
import time import queue def consumer(name): print("--->starting eating baozi...") while True: new_baozi = yield print("[%s] is eating baozi %s" % (name,new_baozi)) #time.sleep(1) def producer(): r = con.__next__() r = con2.__next__() n = 0 while n < 5: n +=1 con.send(n) con2.send(n) print("\033[32;1m[producer]\033[0m is making baozi %s" %n ) if __name__ == '__main__': con = consumer("c1") con2 = consumer("c2") p = producer()
40.請使用python內置async語法實現一個協程?
from datetime import datetime import asyncio async def add(n): print(datetime.now().strftime('%H:%M:%S.%f')) count = 0 for i in range(n): count += i print(datetime.now().strftime('%H:%M:%S.%f')) return count async def fun(n): res = await add(n) print(f'res = {res}') loop = asyncio.get_event_loop() tasks = [fun(20000000), fun(30000000)] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
41.簡述線程死鎖是如何形成的?如何避免?
加鎖順序(線程按照必定的順序加鎖) 加鎖時限(線程嘗試獲取鎖的時候加上必定的時限,超過期限則放棄對該鎖的請求,並釋放本身佔有的鎖) 死鎖檢測
42.asynio是什麼?
python高併發模塊。
43.gevent模塊是什麼?
gevent是第三方庫,經過greenlet實現協程,其基本思想是: 當一個greenlet遇到IO操做時,好比訪問網絡,就自動切換到其餘的greenlet,等到IO操做完成,再在適當的時候切換回來繼續執行。因爲IO操做很是耗時,常常使程序處於等待狀態,有了gevent爲咱們自動切換協程,就保證總有greenlet在運行,而不是等待IO。
44.什麼是twisted框架
twisted是異步非阻塞框架。爬蟲框架Scrapy依賴twisted。
45.什麼是LVS?
LVS :Linux虛擬服務器 做用:LVS主要用於多服務器的負載均衡。 它工做在網絡層,能夠實現高性能,高可用的服務器集羣技術。 它廉價,可把許多低性能的服務器組合在一塊兒造成一個超級服務器。 它易用,配置很是簡單,且有多種負載均衡的方法。 它穩定可靠,即便在集羣的服務器中某臺服務器沒法正常工做,也不影響總體效果。另外可擴展性也很是好。
46.什麼是Nginx?
Nginx是一款自由的、開源的、高性能的HTTP服務器和反向代理服務器,同時也是一個IMAP、POP三、SMTP代理服務器。能夠用做HTTP服務器、反向代理服務器、負載均衡。 '''
47.什麼是keepalived?
Keepalived起初是爲LVS設計的,專門用來監控集羣系統中各個服務節點的狀態,它根據TCP/IP參考模型的第3、第四層、第五層交換機制檢測每一個服務節點的狀態,若是某個服務器節點出現異常,或者工做出現故障,Keepalived將檢測到,並將出現的故障的服務器節點從集羣系統中剔除,這些工做所有是自動完成的,不須要人工干涉,須要人工完成的只是修復出現故障的服務節點。 後來Keepalived又加入了VRRP的功能,VRRP(Vritrual Router Redundancy Protocol,虛擬路由冗餘協議)出現的目的是解決靜態路由出現的單點故障問題,經過VRRP能夠實現網絡不間斷穩定運行,所以Keepalvied 一方面具備服務器狀態檢測和故障隔離功能,另一方面也有HA cluster功能,下面介紹一下VRRP協議實現的過程。
48.什麼是haproxy?
- TCP 代理:可從監聽 socket 接受 TCP 鏈接,而後本身鏈接到 server,HAProxy 將這些 sockets attach 到一塊兒,使通訊流量可雙向流動。 - HTTP 反向代理(在 HTTP 專用術語中,稱爲 gateway):HAProxy 自身表現得就像一個 server,經過監聽 socket 接受 HTTP 請求,而後與後端服務器創建鏈接,經過鏈接將請求轉發給後端服務器。 - SSL terminator / initiator / offloader: 客戶端 -> HAProxy 的鏈接,以及 HAProxy -> server 端的鏈接均可以使用 SSL/TLS - TCP normalizer: 由於鏈接在本地操做系統處終結,client 和 server 端沒有關聯,因此不正常的 traffic 如 invalid packets, flag combinations, window advertisements, sequence numbers, incomplete connections(SYN floods) 不會傳遞給 server 端。這種機制能夠保護脆弱的 TCP stacks 免遭協議上的攻擊,也使得咱們沒必要修改 server 端的 TCP 協議棧設置就能夠優化與 client 的鏈接參數。 - HTTP normalizer: HAProxy 配置爲 HTTP 模式時,只容許有效的完整的請求轉發給後端。這樣能夠使得後端免遭 protocol-based 攻擊。一些不規範的定義也被修改,以避免在 server 端形成問題(eg: multiple-line headers,會被合併爲一行) - HTTP 修正工具:HAProxy 能夠 modify / fix / add / remove / rewrite URL 及任何 request or response header。 - a content-based switch: 可基於內容進行轉發。可基於請求中的任何元素轉發請求或鏈接。所以可基於一個端口處理多種協議(http,https, ssh) - a server load balancer: 可對 TCP 鏈接 和 HTTP 請求進行負載均衡調度。工做於 TCP 模式時,可對整個鏈接進行負載均衡調度;工做於 HTTP 模式時,可對 HTTP 請求進行調度。 - a traffic regulator: 可在不一樣的方面對流量進行限制,保護 server ,使其不超負荷,基於內容調整 traffic 優先級,甚至能夠經過 marking packets 將這些信息傳遞給下層以及網絡組件。 - 防護 DDos 攻擊及 service abuse: HAProxy 可爲每一個 IP地址,URL,cookie 等維護大量的統計信息,並對其進行檢測,當發生服務濫用的狀況,採起必定的措施如:slow down the offenders, block them, send them to outdated contents, etc - 是 network 的診斷的一個觀察節點:根據精確記錄細節豐富的日誌,對網絡診斷頗有幫助 - an HTTP compression offloader:可自行對響應進行壓縮,而不是讓 server 進行壓縮,所以對於鏈接性能較差的 client,或使用高延遲移動網絡的 client,可減小頁面加載時間。
49.什麼是負載均衡?
系統的擴展可分爲縱向(垂直)擴展和橫向(水平)擴展。縱向擴展,是從單機的角度經過增長硬件處理能力,好比CPU處理能力,內存容量,磁盤等方面,實現服務器處理能力的提高,不能知足大型分佈式系統(網站),大流量,高併發,海量數據的問題。所以須要採用橫向擴展的方式,經過添加機器來知足大型網站服務的處理能力。好比:一臺機器不能知足,則增長兩臺或者多臺機器,共同承擔訪問壓力。這就是典型的集羣和負載均衡架構
50.什麼是rpc及應用場景?
RPC主要用於公司內部的服務調用,性能消耗低,傳輸效率高,服務治理方便。HTTP主要用於對外的異構環境,瀏覽器接口調用,APP接口調用,第三方接口調用等...
51.什麼是反向代理和反向代理?
反向代理,這個詞相信搞網絡的朋友都很熟悉的,可是具體是什麼意思呢?說實話,複雜的我也不懂,就我我的理解而言,反向代理有不少用途,好比說保護真實服務器不被外界攻擊,加速網絡等等。今天咱們要介紹的就是加速網絡的一種。
52.建立進程:
1.首先要導入multiprocessing中的Process; 2.建立一個Process對象; 3.建立Process對象時,能夠傳遞參數; 1.p = Process(target=XXX, args=(元組,) , kwargs={key:value}) 2.target = XXX 指定的任務函數,不用加() 3.args=(元組,) , kwargs={key:value} 給任務函數傳遞的參數 4.使用start()啓動進程; 5.結束進程。
53.給子進程指定函數傳遞參數Demo:
import os from multiprocessing import Process import time def pro_func(name, age, **kwargs): for i in range(5): print("子進程正在運行中,name=%s, age=%d, pid=%d" %(name, age, os.getpid())) print(kwargs) time.sleep(0.2) if __name__ == '__main__': # 建立Process對象 p = Process(target=pro_func, args=('小明',18), kwargs={'m': 20}) # 啓動進程 p.start() time.sleep(1) # 1秒鐘以後,馬上結束子進程 17. p.terminate() p.join() 注意:進程間不共享全局變量。
54.進程之間的通訊-Queue
在初始化Queue()對象時,(例如q=Queue(),若在括號中沒有指定最大可接受的消息數量,或數 量爲負值時,那麼就表明可接受的消息數量沒有上限-直到內存的盡頭)
55.進程間通訊Demo:
from multiprocessing import Process, Queueimport 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())
56.讀數據進程執行的代碼:def read(q):
while True: if not q.empty(): value = q.get(True) print('Get %s from queue.' % value) time.sleep(random.random()) else: break if __name__=='__main__': # 父進程建立Queue,並傳給各個子進程: q = Queue() pw = Process(target=write, args=(q,)) pr = Process(target=read, args=(q,)) # 啓動子進程pw,寫入: pw.start() # 等待pw結束: pw.join() # 啓動子進程pr,讀取: pr.start() pr.join() # pr進程裏是死循環,沒法等待其結束,只能強行終止: print('') print('全部數據都寫入而且讀完') 進程池Pool --------------------------- from multiprocessing import Poolimport os, time, random def worker(msg): t_start = time.time() print("%s開始執行,進程號爲%d" % (msg,os.getpid())) # random.random()隨機生成0~1之間的浮點數 7. time.sleep(random.random()*2) t_stop = time.time() print(msg,"執行完畢,耗時%0.2f" % (t_stop-t_start)) po = Pool(3) # 定義一個進程池,最大進程數3 for i in range(0,10): 13. # Pool().apply_async(要調用的目標,(傳遞給目標的參數元祖,)) # 每次循環將會用空閒出來的子進程去調用目標 po.apply_async(worker,(i,)) print("----start----") po.close() # 關閉進程池,關閉後po再也不接收新的請求 po.join() # 等待po中全部子進程執行完成,必須放在close 語句以後 print("-----end-----")
57.multiprocessing.Pool 經常使用函數解析:
apply_async(func[, args[, kwds]]):使用非阻塞方式調用func(並行執行,堵塞方式必須等待上一個進程退出才能執行下一個進 程),args爲傳遞給func的參數列表,kwds爲傳遞給func的關鍵字參數列表; close():關閉Pool,使其再也不接受新的任務; terminate():無論任務是否完成,當即終止; join():主進程阻塞,等待子進程的退出, 必須在close或terminate以後使用; 進程池中使用Queue 若是要使用Pool建立進程,就須要使用multiprocessing.Manager()中的 Queue(),而不是 multiprocessing.Queue(),不然會獲得一條以下的錯誤信息: RuntimeError: Queue objects should only be shared between processes through inheritance. from multiprocessing import Manager,Poolimport os,time,random def reader(q): print("reader啓動(%s),父進程爲(%s)" % (os.getpid(), os.getppid())) for i in range(q.qsize()): print("reader從Queue獲取到消息:%s" % q.get(True)) def writer(q): print("writer啓動(%s),父進程爲(%s)" % (os.getpid(), os.getppid())) for i in "itcast": q.put(i) if __name__=="__main__": print("(%s) start" % os.getpid()) q = Manager().Queue() # 使用Manager中的Queue po = Pool() po.apply_async(writer, (q,)) time.sleep(1) # 先讓上面的任務向Queue存入數據,而後再讓下面的任務開始從中取數據 po.apply_async(reader, (q,)) po.close() po.join() print("(%s) End" % os.getpid())
這個問題被問的機率至關之大,其實多線程,多進程,在實際開發中用到的不多,除非是那些對項目性能要求特別高的,有的開發工做幾年了,也確實沒用過,你能夠這麼回答,給他扯扯什麼是進程,線程(cpython中是僞多線程)的概念就行,實在不行你就說你以前寫過下載文件時,用過多線程技術,或者業餘時間用過多線程寫爬蟲,提高效率。 ''' 進程:一個運行的程序(代碼)就是一個進程, 沒有運行的代碼叫程序, 進程是系統資源分配的最小單位, 進程擁有本身獨立的內存空間, 因此進程間數據不共享,開銷大。 線程:調度執行的最小單位,也叫執行路徑,不能獨立存在,依賴進程存在 一個進程至少有一個線程,叫主線程, 而多個線程共享內存(數據共享,共享全局變量), 從而極大地提升了程序的運行效率。 協程:是一種用戶態的輕量級線程,協程的調度徹底由用戶控制。協程擁有本身的寄存器上下文和棧。 協程調度切換時, 將寄存器上下文和棧保存到其餘地方, 在切回來的時候, 恢復先前保存的寄存器上下文和棧, 直接操做棧, 則基本沒有內核切換的開銷, 能夠不加鎖的訪問全局變量, 因此上下文的切換很是快。
鎖(Lock)是 Python 提供的對線程控制的對象。 有互斥鎖、遞歸鎖。
若干子線程在系統資源競爭時, 都在等待對方對某部分資源解除佔用狀態, 結果是誰也不肯先解鎖, 互相干等着, 程序沒法執行下去, 這就是死鎖。 GIL鎖(有時候,面試官不問,你本身要主動說,增長b格,儘可能別一問一答的尬聊,否則最後等到的一句話就是:你還有什麼想問的麼?) GIL鎖 全局解釋器鎖(只在cpython裏纔有) 做用:限制多線程同時執行,保證同一時間只有一個線程執行,因此cpython裏的多線程實際上是僞多線程! 因此Python裏經常使用協程技術來代替多線程,協程是一種更輕量級的線程, 進程和線程的切換時由系統決定, 而協程由咱們程序員本身決定, 而模塊gevent下切換是遇到了耗時操做纔會切換。 三者的關係:進程裏有線程,線程裏有協程。
61.什麼是線程安全,什麼是互斥鎖?
每一個對象都對應於一個可稱爲" 互斥鎖"的標記,這個標記用來保證在任一時刻,只能有一個線程訪問該對象。 同一個進程中的多線程之間是共享系統資源的,多個線程同時對一個對象進行操做,一個線程操做還沒有結束, 另外一個線程已經對其進行操做,致使最終結果出現錯誤,此時須要對被操做對象添加互斥鎖,保證每一個線程對該對象的操做都獲得正確的結果。
同步:多個任務之間有前後順序執行,一個執行完下個才能執行。 異步:多個任務之間沒有前後順序,能夠同時執行 有時候一個任務可能要在必要的時候 獲取另外一個同時執行的任務的結果,這個就叫回調! 阻塞:若是卡住了調用者,調用者不能繼續往下執行,就是說調用者阻塞了。 非阻塞:若是不會卡住,能夠繼續執行,就是說非阻塞的。 同步異步相對於多任務而言, 阻塞非阻塞相對於代碼執行而言。
孤兒進程:父進程退出, 子進程還在運行的 這些子進程都是孤兒進程, 孤兒進程將被 init 進程(進程號爲 1)所收養, 並由init進程對它們完成狀態收集工做。 殭屍進程:進程使用fork建立子進程, 若是子進程退出, 而父進程並無調用 wait或waitpid獲取子進程的狀態信息, 那麼子進程的 進程描述符 仍然保存在系統中的這些進程是殭屍進程。 避免殭屍進程的方法: -fork兩次用孫子進程去完成子進程的任務; -用wait()函數使父進程阻塞; -使用信號量,在 signal handler 中調用waitpid,這樣父進程不用阻塞。
多進程適合在 CPU 密集型操做(cpu 操做指令比較多,如位數多的浮點運算)。 多線程適合在 IO 密集型操做(讀寫數據操做較多的,好比爬蟲)。
65.線程是併發仍是並行,進程是併發仍是並行?
線程是併發,進程是並行; 進程之間相互獨立,是系統分配資源的最小單位,同一個線程中的全部線程共享資源。
66.並行(parallel)和併發(concurrency)?
並行:同一時刻多個任務同時在運行。 併發:在同一時間間隔內多個任務都在運行,可是並不會在同一時刻同時運行,存在交替執行的狀況。 實現並行的庫有:multiprocessing 實現併發的庫有:threading 程序須要執行較多的讀寫、請求和回覆任務的須要大量的 IO 操做,IO密集型操做使用併發更好。 CPU運算量大的程序程序,使用並行會更好。 IO密集型和CPU密集型區別? IO密集型:系統運做,大部分的情況是CPU在等 I/O (硬盤/內存)的讀/寫。 CPU密集型:大部份時間用來作計算、邏輯判斷等 CPU動做的程序稱之CPU密集型。
67.使用udp發送/接收數據步驟:
1.建立客戶端套接字 2.發送/接收數據 3.關閉套接字 import socket def main(): # 一、建立udp套接字 # socket.AF_INET 表示IPv4協議 AF_INET6 表示IPv6協議 # socket.SOCK_DGRAM 數據報套接字,只要用於udp協議 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 二、準備接收方的地址 # 元組類型 ip是字符串類型 端口號是整型 dest_addr = ('192.168.113.111', 8888) # 要發送的數據 send_data = "我是要發送的數據" # 三、發送數據 udp_socket.sendto(send_data.encode("utf-8"), dest_addr) # 四、等待接收方發送的數據 若是沒有收到數據則會阻塞等待,直到收到數據 # 接收到的數據是一個元組 (接收到的數據, 發送方的ip和端口) # 1024 表示本次接收的最大字節數 recv_data, addr = udp_socket.recvfrom(1024) # 五、關閉套接字 udp_socket.close() if __name__ == '__main__': 22. main() 編碼的轉換 str -->bytes: encode編碼 bytes--> str: decode()解碼
68.UDP綁定端口號:
1.建立socket套接字 2.綁定端口號 3.接收/發送數據 4.關閉套接字 import socket def main(): # 一、建立udp套接字 # socket.AF_INET 表示IPv4協議 AF_INET6 表示IPv6協議 # socket.SOCK_DGRAM 數據報套接字,只要用於udp協議 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 二、綁定端口 # 元組類型 ip通常不寫 表示本機的任何的一個ip local_addr = ('', 7777) udp_socket.bind(local_addr) # 三、準備接收方的地址 # 元組類型 ip是字符串類型 端口號是整型 dest_addr = ('192.168.113.111', 8888) # 要發送的數據 send_data = "我是要發送的數據" # 四、發送數據 udp_socket.sendto(send_data.encode("utf-8"), dest_addr) # 五、等待接收方發送的數據 若是沒有收到數據則會阻塞等待,直到收到數據 # 接收到的數據是一個元組 (接收到的數據, 發送方的ip和端口) # 1024 表示本次接收的最大字節數 recv_data, addr = udp_socket.recvfrom(1024) # 六、關閉套接字 udp_socket.close() if __name__ == '__main__': main() 注意點:綁定端口要在發送數據以前進行綁定。
69.TCP客戶端的建立流程:
1.建立TCP的socket套接字 2.鏈接服務器 3.發送數據給服務器端 4.接收服務器端發送來的消息 5.關閉套接字 import socket def main(): # 一、建立客戶端的socket # socket.AF_INET 表示IPv4協議 AF_INET6 表示IPv6協議 # socket.SOCK_STREAM 流式套接字,只要用於TCP 協議 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 二、構建目標地址 server_ip = input("請輸入服務器端的IP地址:") server_port = int(input("請輸入服務器端的端口號:")) # 三、鏈接服務器 # 參數:元組類型 ip 是字符串類型 端口號是整型 client_socket.connect((server_ip, server_port)) # 要發送給服務器端的數據 send_data = "我是要發送給服務器端的數據" # 四、發送數據 client_socket.send(send_data.encode("gbk")) # 五、接收服務器端恢復的消息, 沒有消息會阻塞 # 1024表示接收的最大字節數 recv_date= client_socket.recv(1024) print("接收到的數據是:", recv_date.decode('gbk')) # 六、關閉套接字 client_socket.close() if __name__ == '__main__': main()
70.TCP服務器端的建立流程
1.建立TCP服務端的socket 2.bing綁定ip地址和端口號 3.listen使套接字變爲被動套接字 4.accept取出一個客戶端鏈接,用於服務 5.recv/send接收和發送消息 6.關閉套接字 import socket def main(): # 一、建立tcp服務端的socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 二、綁定 server_socket.bind(('', 8888)) # 三、listen使套接字變爲被動套接字 server_socket.listen(128) # 四、若是有新的客戶端來連接服務器,那麼就產生一個新的套接字專門爲這個客戶端服務 # client_socket用來爲這個客戶端服務 # tcp_server_socket就能夠省下來專門等待其餘新客戶端的連接 client_socket, client_addr = server_socket.accept() # 五、接收客戶端發來的消息 recv_data = client_socket.recv(1024) print("接收到客戶端%s的數據:%s" % (str(client_addr), recv_data.decode('gbk'))) # 六、回覆數據給客戶端 client_socket.send("收到消息".encode('gbk')) # 七、關閉套接字 client_socket.close() server_socket.close() if __name__ == '__main__': main()
71.TCP是面向鏈接的通信協議,經過三次握手創建鏈接,通信完成時四次揮手
優勢:TCP在數據傳遞時,有確認、窗口、重傳、阻塞等控制機制,能保證數據正確性,較爲可靠。 缺點:TCP相對於UDP速度慢一點,要求系統資源較多。
72.簡述瀏覽器經過WSGI請求動態資源的過程?
1.發送http請求動態資源給web服務器 2.web服務器收到請求後經過WSGI調用一個屬性給應用程序框架 3.應用程序框架經過引用WSGI調用web服務器的方法,設置返回的狀態和頭信息。 4.調用後返回,此時web服務器保存了剛剛設置的信息 5.應用程序框架查詢數據庫,生成動態頁面的body的信息 6.把生成的body信息返回給web服務器 7.web服務器吧數據返回給瀏覽器
先要解析出baidu.com對應的ip地址 - 要先使用arp獲取默認網關的mac地址 - 組織數據發送給默認網關(ip仍是dns服務器的ip,可是mac地址是默認網關的mac地址) - 默認網關擁有轉發數據的能力,把數據轉發給路由器 - 路由器根據本身的路由協議,來選擇一個合適的較快的路徑轉發數據給目的網關 - 目的網關(dns服務器所在的網關),把數據轉發給dns服務器 - dns服務器查詢解析出baidu.com對應的ip地址,並原路返回請求這個域名的client 獲得了baidu.com對應的ip地址以後,會發送tcp的3次握手,進行鏈接 使用http協議發送請求數據給web服務器 - web服務器收到數據請求以後,經過查詢本身的服務器獲得相應的結果,原路返回給瀏覽器。 - 瀏覽器接收到數據以後經過瀏覽器本身的渲染功能來顯示這個網頁。 - 瀏覽器關閉tcp鏈接,即4次揮手結束,完成整個訪問過程
GET請求: 請求的數據會附加在URL以後,以?分割URL和傳輸數據,多個參數用&鏈接。 URL的編碼格式採用的是ASCII編碼, 而不是uniclde, 便是說全部的非ASCII字符都要編碼以後再傳輸。 POST請求: POST請求會把請求的數據放置在HTTP請求包的包體中。 上面的item=bandsaw就是實際的傳輸數據。 所以,GET請求的數據會暴露在地址欄中,而POST請求則不會。 傳輸數據的大小: - 在HTTP規範中,沒有對URL的長度和傳輸的數據大小進行限制。 可是在實際開發過程當中,對於GET,特定的瀏覽器和服務器對URL的長度有限制。 所以,在使用GET請求時,傳輸數據會受到URL長度的限制。 - 對於POST,因爲不是URL傳值,理論上是不會受限制的, 可是實際上各個服務器會規定對POST提交數據大小進行限制, Apache、IIS都有各自的配置。 安全性: - POST的安全性比GET的高。 這裏的安全是指真正的安全, 而不一樣於上面GET提到的安全方法中的安全, 上面提到的安全僅僅是不修改服務器的數據。 好比,在進行登陸操做,經過GET請求, 用戶名和密碼都會暴露再URL上, 由於登陸頁面有可能被瀏覽器緩存 以及其餘人查看瀏覽器的歷史記錄的緣由, 此時的用戶名和密碼就很容易被他人拿到了。 除此以外, GET請求提交的數據 還可能會形成Cross-site request frogery攻擊。 效率:GET比POST效率高。 POST請求的過程: 1.瀏覽器請求tcp鏈接(第一次握手) 2.服務器答應進行tcp鏈接(第二次握手) 3.瀏覽器確認,併發送post請求頭(第三次握手,這個報文比較小,因此http會在此時進行 第一次數據發送) 4.服務器返回100 continue響應 5.瀏覽器開始發送數據 6.服務器返回200 ok響應 GET請求的過程: 1.瀏覽器請求tcp鏈接(第一次握手) 2.服務器答應進行tcp鏈接(第二次握手) 3.瀏覽器確認,併發送get請求頭和數據(第三次握手,這個報文比較小,因此http會在此時 進行第一次數據發送) 4.服務器返回200 OK響應
cookie數據存放在客戶的瀏覽器上, session數據放在服務器上。 cookie不是很安全,別人能夠分析存放在本地的cookie並進行cookie欺騙 考慮到安全應當使用session。 session會在必定時間內保存在服務器上。 當訪問增多,會比較佔用服務器的性能 考慮到減輕服務器性能方面,應當使用cookie。 單個cookie保存的數據不能超過4K, 不少瀏覽器都限制一個站點最多保存20個cookie。 建議:將登錄信息等重要信息存放爲SESSION 其餘信息若是須要保留,能夠放在cookie中
經過狀態碼告訴客戶端服務器的執行狀態,以判斷下一步該執行什麼操做。 常見的狀態機器碼有: 100-199:表示服務器成功接收部分請求,要求客戶端繼續提交其他請求才能完成整個處理過程。 200-299:表示服務器成功接收請求並已完成處理過程,經常使用200(OK請求成功)。 300-399:爲完成請求,客戶須要進一步細化請求。302(全部請求頁面已經臨時轉移到新的url)。 30四、307(使用緩存資源)。 400-499:客戶端請求有錯誤,經常使用404(服務器沒法找到被請求頁面),403(服務器拒絕訪問, 權限不夠)。 500-599:服務器端出現錯誤,經常使用500(請求未完成,服務器遇到不可預知的狀況)。
77.說一下什麼是tcp的2MSL?
主動發送fin關閉的一方,在4次揮手最後一次要等待一段時間咱們稱這段時間爲2MSL TIME_WAIT狀態的存在有兩個理由: 1.讓4次揮手關閉流程更加可靠 2.防止丟包後對後續新建的正常鏈接的傳輸形成破壞
78.爲何客戶端在TIME-WAIT狀態必須等待2MSL的時間?
一、爲了保證客戶端發送的最後一個ACK報文段可以達到服務器。 這個ACK報文段可能丟失, 於是使處在LAST-ACK狀態的服務器收不到確認。服務器會超時重傳FIN+ACK報文段,客戶端就 能在2MSL時間內收到這個重傳的FIN+ACK報文段,接着客戶端重傳一次確認,重啓計時器。最 後,客戶端和服務器都正常進入到CLOSED狀態。若是客戶端在TIME-WAIT狀態不等待一段時間, 而是再發送完ACK報文後當即釋放鏈接,那麼就沒法收到服務器重傳的FIN+ACK報文段,於是也 不會再發送一次確認報文。這樣,服務器就沒法按照正常步驟進入CLOSED狀態。 二、防止已失效的鏈接請求報文段出如今本鏈接中。客戶端在發送完最後一個ACK確認報文段 後,再通過時間2MSL,就能夠使本鏈接持續的時間內所產生的全部報文段都從網絡中消失。這樣 就能夠使下一個新的鏈接中不會出現這種舊的鏈接請求報文段。
HTTP協議傳輸的數據都是未加密的,也就是明文的,所以使用HTTP協議傳輸隱私信息很是不安 全,爲了保證這些隱私數據能加密傳輸,因而網景公司設計了SSL(Secure Sockets Layer)協議用於 對HTTP協議傳輸的數據進行加密,從而就誕生了HTTPS。簡單來講,HTTPS協議是由SSL+HTTP協 議構建的可進行加密傳輸、身份認證的網絡協議,要比http協議安全。 HTTPS和HTTP的區別主要以下: 一、https協議須要到ca申請證書,通常免費證書較少,於是須要必定費用。 二、http是超文本傳輸協議,信息是明文傳輸,https則是具備安全性的ssl加密傳輸協議。 三、http和https使用的是徹底不一樣的鏈接方式,用的端口也不同,前者是80,後者是443。 四、http的鏈接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、 身份認證的網絡協議,比http協議安全。
80.談一下HTTP協議以及協議頭部中表示數據類型的字段?
HTTP 協議是 Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用於從萬維網 (WWW:World Wide Web)服務器傳輸超文本到本地瀏覽器的傳送協議。 HTTP 是一個基於 TCP/IP 通訊協議來傳遞數據(HTML 文件, 圖片文件, 查詢結果等)。 HTTP 是一個屬於應用層的面向對象的協議,因爲其簡捷、快速的方式,適用於分佈式超媒體 信息系統。它於 1990 年提出,通過幾年的使用與發展,獲得不斷地完善和擴展。目前在 WWW 中 使用的是 HTTP/1.0 的第六版,HTTP/1.1 的規範化工做正在進行之中,並且 HTTP-NG(Next Generation of HTTP)的建議已經提出。 HTTP 協議工做於客戶端-服務端架構爲上。瀏覽器做爲 HTTP 客戶端經過URL 向 HTTP 服 務端即 WEB 服務器發送全部請求。Web 服務器根據接收到的請求後,向客戶端發送響應信息。 表示數據類型字段: Content-Type
根據HTTP標準,HTTP請求能夠使用多種請求方法。 HTTP1.0定義了三種請求方法: GET, POST 和 HEAD方法。 HTTP1.1新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。 一、GET 請求指定的頁面信息,並返回實體主體。 二、HEAD 相似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭 三、POST 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在 請求體中。POST請求可能會致使新的資源的創建和/或已有資源的修改。 四、PUT 從客戶端向服務器傳送的數據取代指定的文檔的內容。 五、DELETE 請求服務器刪除指定的頁面。 六、CONNECT HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。 七、OPTIONS 容許客戶端查看服務器的性能。 八、TRACE 回顯服務器收到的請求,主要用於測試或診斷。
Address Family 和 Type,分別表示套接字應用場景和類型。 family的值能夠是AF_UNIX(Unix域,用於同一臺機器上的進程間通信),也能夠是AF_INET (對於IPV4協議的TCP和 UDP),至於type參數,SOCK_STREAM(流套接字)或者 SOCK_DGRAM(數據報文套接字),SOCK_RAW(raw套接字)。
1. Host (主機和端口號) 2. Connection (連接類型) 3. Upgrade-Insecure-Requests (升級爲 HTTPS 請求) 4. User-Agent (瀏覽器名稱) 5. Accept (傳輸文件類型) 6. Referer (頁面跳轉處) 7. Accept-Encoding(文件編解碼格式) 8. Cookie (Cookie) 9. x-requested-with :XMLHttpRequest (是 Ajax 異步請求)
IP: 網絡層 TCP/UDP: 傳輸層 HTTP、RTSP、FTP: 應用層協議
形式: scheme://host[:port#]/path/…/[?query-string][#anchor] scheme:協議(例如:http, https, ftp) host:服務器的IP地址或者域名 port:服務器的端口(若是是走協議默認端口,80 or 443) path:訪問資源的路徑 query-string:參數,發送給http服務器的數據 anchor:錨(跳轉到網頁的指定錨點位置) http://localhost:8000/file/part01/1.2.html
基礎: os,sys,time,datetime,json,pickle,randon,hashlib,re,math,logging 爬蟲: requests,BeautifulSoup,xpath,gevent,asyncio,twisted 數據分析: pandas,numpy,scipy,matplotlib,seaborn 等。。。
2.如何安裝第三方模塊?
pip3 install 模塊名稱
match()函數只檢測字符串開頭位置是否匹配,匹配成功纔會返回結果,不然返回none import re s1 = 'abcabcabc' print(re.match('abc', s1)) print(re.match('abc', s1).group()) print(re.match('abc', s1).span()) search()函數會在整個字符串內查找模式匹配,只到找到第一個匹配而後返回一個包含匹配信息的對象,該對象能夠經過調用group()方法獲得匹配的字符串,若是字符串沒有匹配,則返回None。
貪婪模式:能匹配的最大部分 「.+」中的+會一直查找到最後一個符合條件的字符 非貪婪模式:匹配越少越好 「.+?"會匹配到第一個符合條件的字符就中止
5.如何生成一個隨機數?
import random random.randint(1,9)
6.如何使用 python 刪除一個文件?
import os os.remove('文件名')
7.logging 模塊的做用?以及應用場景?
在咱們平時編寫的程序,基本上都會有記錄日誌的需求,而且日誌當中包含的內容既有正常的程序訪問,又有錯誤,警告等信息輸出,在python的logging模塊當中就提供了標準的日誌接口,能夠經過它來存儲各類格式的日誌. logging模塊也分爲五個等級: debug(), info(), warning(), error(), critical() 其中默認級別爲warning,默認打印到終端 """ 開發應用程序或部署開發環境時,能夠使用DEBUG或INFO級別的日誌獲取儘量詳細的日誌信息來進行開發或部署調試;應用上線或部署生產環境時,應該使用WARNING或ERROR或CRITICAL級別的日誌來下降機器的I/O壓力和提升獲取錯誤日誌信息的效率。 """
8.json 序列化時,能夠處理的數據類型有哪些?如何定製支持 datetime 類 型?
能夠處理的數據類型是 string、int、list、tuple、dict、bool、null # 自定義時間序列化轉換器 import json from json import JSONEncoder from datetime import datetime class ComplexEncoder(JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.strftime('%Y-%m-%d %H:%M:%S') else: return super(ComplexEncoder,self).default(obj) d = { 'name':'alex','data':datetime.now()} print(json.dumps(d,cls=ComplexEncoder))
import json a=json.dumps({"ddf":"你好"},ensure_ascii=False) print(a) #{"ddf": "你好"}
10.寫代碼實現查看一個目錄下的全部文件。
import os print(os.listdir(path))
11.用Python匹配HTMLtag的時候, <.> 和 <.?> 有什麼區別?
<.*>:貪婪匹配,會匹配到符合條件的全部標籤 <.*?>:非貪婪匹配,匹配到符合條件的第一個標籤
import re if re.match(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$', email): print('right') else: print('wrong')
13.sys.path.append("/root/mods")的做用?
將/root/mods文件添加到環境變量
14.下面那些是Python開發網絡應用的框架
1. Django 2. Yii 3. Struts 4. Rails 5. Uliweb 6. CodeIgniter 7. gevent 8. Flask 9. web2py 10. Pylons 11. Tornado 12. Twisted 13. TurboGears 1,8,9,11,12,13
requests:請求庫 BeautifulSoup:解析庫 selenium:自動化測試工具 pyquery:網頁解析庫 pymysql:存儲庫。操做mysql數據庫的 pymongo:操做mongodb數據庫的 urllib.request 請求模塊 模擬瀏覽器 urllib.error 異常處理模塊 urllib.parse url解析模塊 工具模塊,如:拆分、合併 urllib.robotparser robots.txt 解析模塊
16.列舉出Python中比較熟知的爬蟲框架
1.Scrapy Scrapy是一個爲了爬取網站數據,提取結構性數據而編寫的應用框架。 能夠應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。用這個框架能夠輕鬆爬下來如亞馬遜商品信息之類的數據。 2.PySpider pyspider 是一個用python實現的功能強大的網絡爬蟲系統,能在瀏覽器界面上進行腳本的編寫,功能的調度和爬取結果的實時查看,後端使用經常使用的數據庫進行爬取結果的存儲,還能定時設置任務與任務優先級等。 3.Crawley Crawley能夠高速爬取對應網站的內容,支持關係和非關係數據庫,數據能夠導出爲JSON、XML等。 4.Portia Portia是一個開源可視化爬蟲工具,可以讓您在不須要任何編程知識的狀況下爬取網站!簡單地註釋您感興趣的頁面,Portia將建立一個蜘蛛來從相似的頁面提取數據。 5.Newspaper Newspaper能夠用來提取新聞、文章和內容分析。使用多線程,支持10多種語言等。 6.Cola Cola是一個分佈式的爬蟲框架,對於用戶來講,只需編寫幾個特定的函數,而無需關注分佈式運行的細節。任務會自動分配到多臺機器上,整個過程對用戶是透明的。 7.Grab Grab是一個用於構建Web刮板的Python框架。藉助Grab,您能夠構建各類複雜的網頁抓取工具,從簡單的5行腳本處處理數百萬個網頁的複雜異步網站抓取工具。Grab提供一個API用於執行網絡請求和處理接收到的內容,例如與HTML文檔的DOM樹進行交互。
17.輸入某年某日,判斷這是這一年的第幾天?(能夠用Python的內置模塊)
import datetime y = int(input('請輸入4位數字的年份:')) # 獲取年份 m = int(input('請輸入月份:')) # 獲取月份 d = int(input('請輸入是哪一天:')) # 獲取「日」 targetDay = datetime.date(y, m, d) # 將輸入的日期格式化成標準的日期 dayCount = targetDay - datetime.date(targetDay.year - 1, 12, 31) # 減去上一年最後一天 print('%s是%s年的第%s天。' % (targetDay, y, dayCount.days))
1、建立型模式之單例模式
一、請手寫一個單例
#encoding=utf8 import threading import time #這裏使用方法__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 Bus(Singleton): lock = threading.RLock() def sendData(self,data): self.lock.acquire() time.sleep(3) print "Sending Signal Data...",data self.lock.release() #線程對象,爲更加說明單例的含義,這裏將Bus對象實例化寫在了run裏 class VisitEntity(threading.Thread): my_bus="" name="" def getName(self): return self.name def setName(self, name): self.name=name def run(self): self.my_bus=Bus() self.my_bus.sendData(self.name) if __name__=="__main__": for i in range(3): print "Entity %d begin to run..."%i my_entity=VisitEntity() my_entity.setName("Entity_"+str(i)) my_entity.start()
二、單例模式的優勢和應用?
單例模式的優勢: 一、因爲單例模式要求在全局內只有一個實例,於是能夠節省比較多的內存空間; 二、全局只有一個接入點,能夠更好地進行數據同步控制,避免多重佔用; 三、單例可長駐內存,減小系統開銷。 單例模式的應用舉例: 一、生成全局唯一的序列號; 二、訪問全局複用的唯一資源,如磁盤、總線等; 三、單個對象佔用的資源過多,如數據庫等; 四、系統全局統一管理,如Windows下的Task Manager; 五、網站計數器。 六、數據庫配置,數據庫鏈接池 七、應用程序的日誌應用
一、單例模式的擴展是比較困難的; 二、賦於了單例以太多的職責,某種程度上違反單一職責原則(六大原則後面會講到); 三、單例模式是併發協做軟件模塊中須要最早完成的,於是其不利於測試; 四、單例模式在某種狀況下會致使「資源瓶頸」。
2、建立型模式之工廠模式
工廠類相關模式:
一、工廠模式、簡單工廠模式、抽象工廠模式
工廠模式的定義以下: 定義一個用於建立對象的接口,讓子類決定實例化哪一個類。 工廠方法使一個類的實例化延遲到其子類。其通用類圖以下。 其產品類定義產品的公共屬性和接口,工廠類定義產品實例化的「方式」 import random class PetShop(object): def __init__(self,animal_factory=None): # pet 寵物 factory 工廠 self.pet_factory = animal_factory def show_pet(self): pet = self.pet_factory.get_pet() print("this is a lovely", pet) print("it says",pet.speak()) print("it eats",self.pet_factory.get_food()) class Dog: def speak(self): return "Dog" def __str__(self): return "this is Dog" class Cat: def speak(self): return "Cat" def __str__(self): return "this is Cat" class CatFactory: def get_pet(self): return Cat() def get_food(self): return "cat food" class DogFactory: def get_pet(self): return Dog() def get_food(self): return "dog food" def get_factory(): return random.choice([DogFactory,CatFactory]) if __name__ == '__main__': shop = PetShop() # pet_factory 默認爲None,後面延遲加載 shop.pet_factory = get_factory()() # 延遲加載,隨機選擇一個工廠而後實例出來一個對象給商店 shop.show_pet()
二、工廠模式的優勢和應用
工廠模式、抽象工廠模式的優勢: 一、工廠模式巨有很是好的封裝性,代碼結構清晰; 在抽象工廠模式中,其結構還能夠隨着須要進行更深或者更淺的抽象層級調整,很是靈活; 二、屏蔽產品類,使產品的被使用業務場景和產品的功能細節能夠分而開發進行,是比較典型的解耦框架。 工廠模式、抽象工廠模式的使用場景: 一、當系統實例要求比較靈活和可擴展時,能夠考慮工廠模式或者抽象工廠模式實現。好比, 在通訊系統中,高層通訊協議會不少樣化,同時,上層協議依賴於下層協議,那麼就能夠對應創建對應層級的抽象工廠,根據不一樣的「產品需求」去生產定製的實例。
三、工廠模式的不足
一、工廠模式相對於直接生成實例過程要複雜一些,因此,在小項目中,能夠不使用工廠模式; 二、抽象工廠模式中,產品類的擴展比較麻煩。 畢竟,每個工廠對應每一類產品,產品擴展,就意味着相應的抽象工廠也要擴展
1.JavaScript(或 jQuery)如何選擇一個 id 爲 main 的容器
#main
2.JavaScript(或 jQuery)如何選擇一個 class 爲 menu 的容器
.menu
3.簡述什麼是瀏覽器事件流
DOM2級事件規定的事件流包括三個階段: 一、事件捕獲階段 二、處於目標階段 三、事件冒泡階段 事件捕獲階段(Event Capturing): 按照事件捕獲的思想,在此過程(click頁面某元素)中,document對象會首先接收到click事件,而後事件沿着dom樹依次向下,一直傳播到實際目標,即div元素。但在事件流中的捕獲階段,實際目標div元素是不會接收到事件的,這就意味着沒在捕獲階段,事件從document到再到後就中止了。(但IE九、Safari、Chrome、Firefox 和 Opera9.5 以及更高版本都會在捕獲階段觸發事件對象上的事件);下一個階段是"處於目標"階段,因而事件在發生,並在事件處理中被堪稱冒泡階段的一部分,最後,冒泡事件發生,事件又傳播迴文檔。 冒泡階段(Event Bubbling): 事件開始時由最具體的元素(文檔中嵌套層次最深的那個節點)接收,而後逐級向上傳播到較爲不具體的節點,即document對象。 DOM2 與 DOM0區別 DOM2級事件定義了兩個方法,用於處理指定和刪除事件處理程序的操做: ①.addEventListener() ②.removeEventListener() 全部的DOM節點都包含這兩個方法,並且接受三個參數: ①.要處理的事件名; ②.做爲事件處理程序的函數; ③.一個 boolean 的值,若是值爲true,表示在捕獲階段調用事件處理程序;若是是false,表示在冒泡階段調用此事件處理程序。
4.用 css 如何隱藏一個元素
1.opacity opacity:0將元素自己及其子元素都置爲不可見的,而元素自己依然佔據它本身的位置並對網頁的佈局起做用,它會響應用戶交互 .hide { opacity:0 } 2 .visibility visibility:hidden將元素自己及其子元素都置爲不可見的, 而元素自己依然佔據它本身的位置並對網頁的佈局起做用,它不會響應用戶交互.若是想讓子元素顯示,則設置子元素的visibility:visible; .hide { visibility:hidden } 3.display display:none使用這個屬性,被隱藏的元素對網頁的佈局不起做用。不只如此,一旦display設爲none任何對該元素直接的用戶交互操做都不可能生效。此外,讀屏軟件也不會讀到元素的內容。這種方式產生的效果就像元素徹底不存在。經過DOM依然能夠訪問到這個元素。所以你能夠經過DOM來操做它。 .hide { display:none } 4.position position:absolute 將top和left設置成足夠大的負數,至關於把元素放到可視區域外,它不會影響佈局,可以讓元素保持可操做性,在讀屏軟件上能夠被識別。 .hide { position:absolute; top:-9999px; left:-9999px; } 總結一下:visibility影響佈局,影響交互; opacity影響佈局,不影響交互 display不影響佈局,影響交互; position 不影響佈局,不影響交互;
5.一行 css 實現 padding 上下左右分別爲 1px, 2px,3px, 4px
.padding-test { padding:1px 4px 2px 3px; }
6.先後端分離的基本原理。
先後端分離並不僅是開發模式,而是web應用的一種架構模式。在開發階段,先後端工程師約定好數據交互接口,實現並行開發和測試;在運行階段先後端分離模式須要對web應用進行分離部署,先後端以前使用HTTP或者其餘協議進行交互請求。
2. 先後端代碼庫分離
在傳統架構模式中,先後端代碼存放於同一個代碼庫中,甚至是同一工程目錄下。頁面中還夾雜着後端代碼。先後端工程師進行開發時,都必須把整個項目導入到開發工具中。 先後端代碼庫分離,前端代碼中有能夠進行Mock測試(經過架構虛擬測試對象以簡化測試環境的方法)的僞後端,能支持前端的獨立開發和測試。然後端代碼中除了功能實現外,還有着詳細的測試用例,以保證API的可用性,下降集成風險。
3.並行開發
分離後,開發模式是這樣的
七、先後端分離的優勢
1.爲優質產品打造精益團隊 經過將開發團隊先後端分離化,讓先後端工程師只須要專一於前端或後端的開發工做,是的先後端工程師實現自治,培養其獨特的技術特性,而後構建出一個全棧式的精益開發團隊。 2.提高開發效率 先後端分離之後,能夠實現先後端代碼的解耦,只要先後端溝通約定好應用所需接口以及接口參數,即可以開始並行開發,無需等待對方的開發工做結束。與此同時,即便需求發生變動,只要接口與數據格式不變,後端開發人員就不須要修改代碼,只要前端進行變更便可。如此一來整個應用的開發效率必然會有質的提高。 3.完美應對複雜多變的前端需求 若是開發團隊能完成先後端分離的轉型,打造優秀的先後端團隊,開發獨立化,讓開發人員作到專一專精,開發能力必然會有所提高,可以完美應對各類複雜多變的前端需求。 4.加強代碼可維護性 先後端分離後,應用的代碼再也不是先後端混合,只有在運行期纔會有調用依賴關係。應用代碼將會變得整潔清晰,不管是代碼閱讀仍是代碼維護都會比之前輕鬆。
八、給url設置樣式爲:背景色黑色,給ul下的ui設置樣式爲:寬度30px,背景紅色
ul { background-color:black; } ul>ui { width:30px; background-color:red; }
9.寫一個正則表達式獲取HTML源碼中的編碼,以下的編碼是;utf-8怎麼經過Python的re模塊得到?
<!DOCTYPE html> <html lang="en"> <head> <title>404</title> </head>
十、如何建立響應式佈局?
建立響應式佈局,意在實現不一樣屏幕分辨率的終端上瀏覽網頁的不一樣展現方式。經過響應式設計能使網站在手機和平板電腦上有更好的瀏覽閱讀體驗。 一、設置 Meta 標籤 大多數移動瀏覽器將HTML頁面放大爲寬的視圖(viewport)以符合屏幕分辨率。你能夠使用視圖的meta標籤來進行重置。下面的視圖標籤告訴瀏覽器,使用設備的寬度做爲視圖寬度並禁止初始的縮放。在<head>標籤里加入這個meta標籤。 二、經過媒介查詢來設置樣式 Media Queries Media Queries 是響應式設計的核心。 它根據條件告訴瀏覽器如何爲指定視圖寬度渲染頁面。假如一個終端的分辨率小於 980px,那麼能夠這樣寫: @media screen and (max-width: 980px) { #head { … } #content { … } #footer { … } } 這裏的樣式就會覆蓋上面已經定義好的樣式。 三、設置多種試圖寬度 假如咱們要設定兼容 iPad 和 iphone 的視圖,那麼能夠這樣設置: /** iPad **/ @media only screen and (min-width: 768px) and (max-width: 1024px) {} /** iPhone **/ @media only screen and (min-width: 320px) and (max-width: 767px) {} 注意問題: 一、寬度須要使用百分比 #head { width: 100% } #content { width: 50%; } 二、處理圖片縮放的方法 簡單的解決方法能夠使用百分比,但這樣不友好,會放大或者縮小圖片。那麼能夠嘗試給圖片指定的最大寬度爲百分比。假如圖片超過了,就縮小。假如圖片小了,就原尺寸輸出。 img { width: auto; max-width: 100%; } - 用::before和::after僞元素 +content 屬性來動態顯示一些內容或者作其它很酷的事情,在 css3 中,任何元素均可以使用 content 屬性了,這個方法就是結合 css3 的 attr 屬性和 HTML 自定義屬性的功能: HTML 結構: 著做權歸做者全部。 商業轉載請聯繫做者得到受權,非商業轉載請註明出處。 連接:http://caibaojian.com/356.html 來源:http://caibaojian.com <img src="image.jpg" data-src-600px="image-600px.jpg" data-src-800px="image-800px.jpg" alt=""> CSS 控制: @media (min-device-width:600px) { img[data-src-600px] { content: attr(data-src-600px, url); } } @media (min-device-width:800px) { img[data-src-800px] { content: attr(data-src-800px, url); } } 3. 其餘屬性 例如 pre ,iframe,video 等,都須要和img同樣控制好寬度。對於table,建議不要增長 padding 屬性,低分辨率下使用內容居中: table th, table td { padding: 0 0; text-align: center; }
html框架: Bootstarp js框架: jQuery Vue
十二、什麼是ajax請求?並使用jQuery和XMLHttpRequest對象實現一個ajax請求
""" AJAX(Asynchronous Javascript And XML)翻譯成中文就是「異步的Javascript和XML」。即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML)。 AJAX 不是新的編程語言,而是一種使用現有標準的新方法。 AJAX 最大的優勢是在不從新加載整個頁面的狀況下,能夠與服務器交換數據並更新部分網頁內容。(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程) """ ########## jQuery. ########### $ajax({ url:"/test/", type:'post', data:{'n1':$("#num1").val(), 'n2':$("#num2").val() }, success:function (data){ $("#num3").val(data) } }) ######### XMLHttpRequest ######## function getXhr(){ if (typeof XMLHttpRequest != 'undefined') { return new XMLHttpRequest(); } } var xhr = getXhr(); var stringData = { uname: '123', password: '123', code: '' } stringData = JSON.stringify(stringData); //POST請求 xhr.open('POST', '/user/login'); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.send(stringData) xhr.onreadystatechange = function(res) { if (xhr.readyState == 4) { if (xhr.status == 200) { console.log(JSON.parse(xhr.responseText)) } } }
1三、如何在前端實現輪詢?
輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP request,而後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的HTTP request 的模式帶來很明顯的缺點 – 瀏覽器須要不斷的向服務器發出請求,然而HTTP request 的header是很是長的,裏面包含的有用數據可能只是一個很小的值,這樣會佔用不少的帶寬。 var xhr = new XMLHttpRequest(); setInterval(function(){ xhr.open('GET','/user'); xhr.onreadystatechange = function(){ }; xhr.send(); },1000)
1四、如何在前端實現長輪詢?
ajax實現:在發送ajax後,服務器端會阻塞請求直到有數據傳遞或超時才返回。 客戶端JavaScript響應處理函數會在處理完服務器返回的信息後,再次發出請求,從新創建鏈接。 function ajax(){ var xhr = new XMLHttpRequest(); xhr.open('GET','/user'); xhr.onreadystatechange = function(){ ajax(); }; xhr.send(); }
1五、vuex的做用?
Vuex是一個狀態管理的插件,能夠解決不一樣組件之間的數據共享和數據持久化。
1六、vue中的路由的攔截器的做用?
判斷是否有token值或是否to登陸頁,是則next(),不然跳轉到登陸頁
1七、axios的做用?
axios是基於promise的用於瀏覽器和nodejs的HTTP客戶端,自己有如下特徵: 從瀏覽器中建立XMLHttpRequest; 從nodejs發出http請求 支持promiseAPI 攔截 請求和響應 轉換請求和響應數據 取消請求 自動轉換JSON數據 客戶端支持防止CSRF/XSRF攻擊
1八、列舉vue的常見指令
v-text v-html v-show v-if v-else v-else-if v-for v-on v-bind v-model v-pre v-cloak v-once
爲了保證用戶訪問的安全,現代瀏覽器使用了同源策略,即不容許訪問非同源的頁面,詳細的概念你們能夠自行百度。這裏你們只要知道,在ajax中,不容許請求非同源的URL就能夠了,好比www.a.com下的一個頁面,其中的ajax請求是不容許訪問www.b.com/c.php這樣一個頁面的。 JSONP就是用來解決跨域請求問題的 JSONP原理: ajax請求受同源策略影響,不容許進行跨域請求,而script標籤src屬性中的連接卻能夠訪問跨域的js腳本,利用這個特性,服務端再也不返回JSON格式的數據,而是返回一段調用某個函數的js代碼,在src中進行了調用,這樣實現了跨域。
CORS:全稱"跨域資源共享"(Cross-origin resource sharing) CORS須要瀏覽器和服務器同時支持,才能夠實現跨域請求,目前幾乎全部瀏覽器都支持CORS,IE則不能低於IE10。CORS的整個過程都由瀏覽器自動完成,前端無需作任何設置,跟平時發送ajax請求並沒有差別。so,實現CORS的關鍵在於服務器,只要服務器實現CORS接口,就能夠實現跨域通訊。 django裏面跨域CORS的設置 安裝 pip install django-cors-headers 添加應用 在settings裏面配置: INSTALLED_APPS = ( ... 'corsheaders', ... ) 中間層設置 MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', ... ] 添加白名單 # CORS CORS_ORIGIN_WHITELIST = ( '127.0.0.1:8080', 'localhost:8080', #凡是出如今白名單中的域名,均可以訪問後端接口 ) CORS_ALLOW_CREDENTIALS = True # 指明在跨域訪問中,後端是否支持對cookie的操做
2一、看JavaScript代碼寫結果:
var name = '張三'; function func(){ var name = '李四'; function inner(){ console.log(name) } return inner; } var ret = func(); ret() 結果:李四
2二、看JavaScript代碼寫結果:
function main(){ if(1==1){ var name = "張三"; } console.log(name); } 結果:undefined
2三、看JavaScript代碼寫結果
var name = "張三"; function func(){ var name = "李四"; function inner(){ var name = "王五"; console.log(name); } return inner(); } func(); 結果:王五
2四、看JavaScript代碼寫結果:
function func(){ console.log(name); var name = "DSB"; } 結果:undefined
2五、看JavaScript代碼寫結果:
var name = "張三"; function Foo(){ this.name = "李四"; this.func = function(){ console.log(this.name); } } var obj = new Foo(); obj.func(); 結果:李四
def select_related(self, *fields) 性能相關:表之間進行join連表操做,一次性獲取關聯的數據。 總結: 1. select_related主要針一對一和多對一關係進行優化。 2. select_related使用SQL的JOIN語句進行優化,經過減小SQL查詢的次數來進行優化、提升性能。 def prefetch_related(self, *lookups) 性能相關:多表連表操做時速度會慢,使用其執行屢次SQL查詢在Python代碼中實現連表操做。 總結: 1. 對於多對多字段(ManyToManyField)和一對多字段,能夠使用prefetch_related()來進行優化。 2. prefetch_related()的優化方式是分別查詢每一個表,而後用Python處理他們之間的關係。
二、Django ORM是什麼?
對象關係映射,經過models中的類來對應數據庫中的一個表,一個對象對應一個數據行,一個屬性對應數據庫中的一個字段
三、Django建立項目的命令?
django-admin startproject 項目名稱 python manage.py startapp 應用app名
四、Django建立項目後,項目文件夾下的組成部分(對mvt的理解)?
項目文件夾下的組成部分: manage.py 是項目運行的入口,執行配置文件路徑 與項目同名的目錄,包含項目的配置文件 __init__.py是一個空文件,做用是這個目錄能夠被看成包使用,也能夠作一些初始化操做 settings.py是項目的總體配置文件 urls.py是項目的URL配置文件 wsgi.py是項目與WSGI兼容的Web服務器
五、對MVC,MTV解讀的理解?
M:Model,模型,和數據進行交互 V:View,視圖,負責產生Html頁面 C:Controller,控制器,接收請求,進行處理,與M和V進行交互,返回應答 MVC的流程: 1.用戶點擊註冊按鈕,將要註冊的信息發送給網站服務器 2.Controller控制器接收用戶的註冊信息,Controller會告訴Model層將用戶的註冊信息保存到數據庫 3.Model層將用戶的註冊信息保存到數據庫 4.數據保存以後將保存的結果返回給Model模型 5.Model層將保存的結果返回Controller控制器 6.Controller控制器接收保存的結果以後,或告訴View視圖,View視圖產生一個HTML頁面 7.View將產生的HTML頁面的內容給了Controller控制器 8.Controller將HTML頁面的內容返回給瀏覽器 9.瀏覽器接收到服務器Controller控制器返回的HTML頁面進行解析展現 M:Model,模型,和MVC中的M功能相同,和數據庫進行交互 T:Template,模板,和MVC中的V功能相同,產生Html頁面 V:View,視圖,和MVC中的C功能相同,接收請求,進行處理,與M和T進行交互,返回應答 MTV的流程: 一、 用戶點擊註冊按鈕,將要註冊的內容發送給網站的服務器。 二、 View視圖,接收到用戶發來的註冊數據,View告訴Model將用戶的註冊信息保存進數據庫。 三、 Model層將用戶的註冊信息保存到數據庫中。 四、 數據庫將保存的結果返回給Model 五、 Model將保存的結果給View視圖。 六、 View視圖告訴Template模板去產生一個Html頁面。 七、 Template生成html內容返回給View視圖。 八、 View將html頁面內容返回給瀏覽器。 九、 瀏覽器拿到view返回的html頁面內容進行解析,展現。
六、Django中models利用ORM對Mysql進行查表的語句(多個語句)?
字段查詢 all():返回模型類對應表中的全部數據 get():返回表格中知足條件的一條數據, 若是查到多條數據,則拋異常:MultipleObjectsReturned 查詢不到數據,則拋異常:DoesNotExist filter():參數寫查詢條件,返回知足條件QuerySet集合數據 條件格式: 模型類屬性名_條件名=值 注意:此處是模型類屬性名,不是表中的字段名 關於filter具體案例以下: 判等exact BookInfo.object.filter(id=1) BookInfo.object.filter(id__exact=1)此處的__exact 能夠省略 模糊查詢like 例:查詢書名包含'傳'的圖書。contains contains BookInfo.objects.filter(btitle__contains='傳') 空查詢where字段名isnull BookInfo.objects.filter(btitle__isnull=False) 範圍查詢where id in (1,3,5) BookInfo.objects.filter(id__in=[1,3,5]) 比較查詢gt lt(less than) gte(equal) lte BookInfo.objects.filter(id__gte=3) 日期查詢 BookInfo.objects.filter(bpub_date__year = 1980) BookInfo.objects.filter(bpub_date__get = date(1980,1,1)) exclude:返回不知足條件的數據 BookInfo.objects.exclude(id = 3) F對象 做用:用於類屬性之間的比較條件 1. from django.db.models import F 2. 例:where bread > bcomment BookInfo.objects.filter(bread__gt =F(‘bcomment’)) 3. 例:BookInfo.objects.filter(bread__gt=F(‘bcomment’)*2) Q對象 做用:用於查詢時的邏輯條件。能夠對Q對象進行&|~操做 BookInfo.objects.filter(id__gt=3,bread__gt=30) BookInfo.objects.filter(Q(id__gt=3) & Q(bread__gt=3)) BookInfo.objects.filter(Q(id__gt=3) | Q(bread__gt=3)) BookInfo.objects.filter(~Q(id=3)) order_by返回QuerySet 做用:對查詢結果進行排序 BookInfo.objects.all().order_by('id') BookInfo.objects.all().order_by('-id') BookInfo.objects.filter(id__gt=3).order_by('-bread') 聚合函數 做用:對查詢結果進行聚合操做 sum count max min avg aggregate:調用這個函數來使用聚合 from django.db.models import Sum,Count,Max,Min,Avg BookInfo.objects.aggregate(Count('id')) {'bread_sum':120}注意返回值類型及鍵名 count函數 做用:統計知足條件數據的數目 例1:統計全部圖書的數目 BookInfo.objects.all().count() 例2:統計id大於3的全部圖書的數目 BookInfo.objects.filter(id__gt = 3).count() 模型類關係 一對多關係 例:圖書類-英雄類 models.ForeifnKey()定義在多的類中 多對多關係 例:新聞類-新聞類型類 models.ManyToManyField()定義在哪一個類中均可以 一對一關係 例:員工基本信息類-員工詳細信息類 models.OneToOneField()定義在哪一個類中均可以
面試官問你Django中間件的時候,咱們不該該只是侷限於面試官的問題,而應作到觸類旁通。 面試以前準備一些白紙,在問到一些問題的時候應該用畫圖的形式展現出來 好比這裏問到Django的中間件,咱們應該給面試官畫出Django的生命週期總體流程圖,把中間件做爲一部分的回答內容, 這樣的好處在於,即展現了你對Django從前到後的流程都很熟悉又回答了面試官的問題,還順帶秀了一把其餘技能,一箭雙鵰。 中間件介紹:做爲Django的門戶,一切請求都會先通過中間件纔會到達Django後端,因此中間件能夠用來作全局方面的一些功能 詳細:給咱們定義了五個方法 def process_request(request): pass def process_view(request): pass def process_template_response(request): pass def process_exception(request): pass def process_response(request): pass 這些內容應該作到快速回答,不要"慢條斯理"的,搞IT的都很忙好吧,知識點必定要掌握牢固,脫口而出必定要記住你是須要在有限的時間內將本身的看家本領竭盡全力的傾囊而出 Django生命週期:下圖
八、談一下你對uWSGL和nginx的理解?
1.uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http等協議。Nginx中HttpUwsgiModule的做用是與uWSGI服務器進行交換。WSGI是一種Web服務器網關接口。它是一個Web服務器(如nginx,uWSGI等服務器)與web應用(如用Flask框架寫的程序)通訊的一種規範。 要注意 WSGI / uwsgi / uWSGI 這三個概念的區分。 WSGI是一種通訊協議。 uwsgi是一種線路協議而不是通訊協議,在此經常使用於在uWSGI服務器與其餘網絡服務器的數據通訊。 uWSGI是實現了uwsgi和WSGI兩種協議的Web服務器。 2. nginx是一個開源的高性能的HTTP服務器和反向代理: 1.做爲web服務器,它處理靜態文件和索引文件效果很是高; 2.它的設計很是注重效率,最大支持5萬個併發鏈接,但只佔用不多的內存空間; 3.穩定性高,配置簡潔; 4.強大的反向代理和負載均衡功能,平衡集羣中各個服務器的負載壓力應用。
首先瀏覽器發起http請求到nginx服務器,Nginx根據接收到請求包,進行url分析,判斷訪問的資源類型,若是是靜態資源,直接讀取靜態資源返回給瀏覽器,若是請求的是動態資源就轉交給uwsgi服務器,uwsgi服務器根據自身的uwsgi和WSGI協議,找到對應的Django框架,Django框架下的應用進行邏輯處理後,將返回值發送uwsgi服務器,而後uwsgi服務器再返回給nginx,最後nginx將返回值返回給瀏覽器進行渲染顯示給用戶。 若是能夠,畫圖講解效果更佳,能夠 將下面的圖畫給面試官。
1.設計表時,儘可能少使用外鍵,由於外鍵約束會影響插入和刪除性能; 2.使用緩存,減小對數據庫的訪問; 5.Django orm框架下的Querysets 原本就有緩存的; 6.若是一個頁面須要屢次鏈接數據庫,最好一次性取出全部須要的數據,減小對數據庫的查詢次數; 7.若頁面只須要數據庫裏某一個兩個字段時,能夠用QuerySet.values(); 8.在模板標籤裏使用with標籤能夠緩存Qset的查詢結果。
十一、驗證碼過時時間怎麼設置?
將驗證碼保存到數據庫或session,設置過時時間爲1分鐘,而後頁面設置一個倒計時(通常是前端js實現這個計時)的展現,一分鐘事後再次點擊獲取新的信息
十二、Python中三大框架各自的應用場景?
django:主要是用來搞快速開發的,它的亮點就是快速開發,節約成本,正常的併發量不過10000,若是要實現高併發的話,就要對Django進行二次開發,好比把整個笨重的框架給拆掉,本身寫socket實現http的通訊,底層用純c,c++寫提高效率,ORM框架給幹掉,本身編寫封裝與數據庫交互的框架,由於啥呢,ORM雖然面向對象來操做數據庫,可是它的效率很低,使用外鍵來聯繫表與表之間的查詢; flask:輕量級,主要是用來寫接口的一個框架,實現先後端分離,提高開發效率,Flask自己至關於一個內核,其餘幾乎全部的功能都要用到擴展(郵件擴展Flask-Mail,用戶認證Flask-Login),都須要用第三方的擴展來實現。好比能夠用Flask-extension加入ORM、窗體驗正工具,文件上傳、身份驗證等。Flask沒有默認使用的數據庫,你能夠選擇MySQL,也能夠NoSQL.其WSGI工具箱採用Werkzeug(路由模塊),模板引擎則使用jinja2.這兩個也是Flask框架的核心。Python最出名的框架要數Django,此外還有Flask、Tornado等框架。雖然Flask不是最出名的礦建,可是Flask應該算是最靈活的框架之一,這也是Flask受到廣發開發者喜好的緣由。 Tornado:Tornado是一種 Web 服務器軟件的開源版本。Tornado 和如今的主流 Web 服務器框架(包括大多數 Python 的框架)有着明顯的區別:它是非阻塞式服務器,並且速度至關快。 得利於其非阻塞的方式和對epoll的運用,Tornado 每秒能夠處理數以千計的鏈接,所以 Tornado 是實時 Web 服務的一個 理想框架。
對一個後端開發程序員來講,提高性能指標主要有兩個一個是併發數,另外一個是響應時間網站性能的優化通常包括web前端性能優化,應用服務器性能優化,存儲服務器優化。 對前端的優化主要有: 1.減小http請求,減小數據庫的訪問量,好比使用雪碧圖。 2.使用瀏覽器緩存,將一些經常使用的css,js,logo圖標,這些靜態資源緩存到本地瀏覽器,經過設置http頭中的cache-control和expires的屬性,可設定瀏覽器緩存,緩存時間能夠自定義。 3.對html,css,javascript文件進行壓縮,減小網絡的通訊量。 對我我的而言,我作的優化主要是如下三個方面: 1.合理的使用緩存技術,對一些經常使用到的動態數據,好比首頁作一個緩存,或者某些經常使用的數據作個緩存,設置必定得過時時間,這樣減小了對數據庫的壓力,提高網站性能。 2.使用celery消息隊列,將耗時的操做扔到隊列裏,讓worker去監聽隊列裏的任務,實現異步操做,好比發郵件,發短信。 3.就是代碼上的一些優化,補充:nginx部署項目也是項目優化,能夠配置合適的配置參數,提高效率,增長併發量。 4.若是太多考慮安全因素,服務器磁盤用固態硬盤讀寫,遠遠大於機械硬盤,這個技術如今沒有普及,主要是固態硬盤技術上還不是徹底成熟, 相信之後會大量普及。 5.另外還能夠搭建服務器集羣,將併發訪問請求,分散到多臺服務器上處理。 6.最後就是運維工做人員的一些性能優化技術了。
上來先給面試官扔出一手Django的restgramework源碼(這一塊知識課下必定要本身看着源碼走三遍作到爛熟於心,看着面試官的眼睛快速自信的說出。這一手源碼扔出來以後,面試已經成功一半) REST:Representational State Transfer的縮寫,翻譯:「具象狀態傳輸」。通常解釋爲「表現層狀態轉換」。 REST是設計風格而不是標準。是指客戶端和服務器的交互形式。咱們須要關注的重點是如何設計REST風格的網絡接口。 REST的特色: 1.巨象的。通常指表現層,要表現的對象就是資源。好比,客戶端訪問服務器,獲取的數據就是資源。好比文字、圖片、音頻等。 2.表現:資源的表現形式。txt格式、html格式、json格式、jpg格式等。瀏覽器經過URL確認資源的位置,可是須要在HTML請求頭中,用AcceptContent-Type字段指定,這兩個字段是對資源表現的描述。 3.狀態轉換:客戶端和服務器交互的過程。在這個過程當中,必定會有數據和狀態的轉化,這種轉化叫作狀態轉換。其中,GET表示獲取資源,POST表示新建資源,PUT表示更新資源,DELETE表示刪除資源。HTTP協議中最經常使用的就是這四種操做方式。 RESTful架構: 1.每一個URL表明一種資源; 2.客戶端和服務器之間,傳遞這種資源的某種表現層; 3.客戶端經過四個http動詞,對服務器資源進行操做,實現表現層狀態轉換。
1、域名: 將api部署在專用域名下: http://api.example.com 或者將api放在主域名下: http://www.example.com/api/ 2、版本: 將API的版本號放在url中。 http://www.example.com/app/1.0/info http://www.example.com/app/1.2/info 3、路徑: 路徑表示API的具體網址。每一個網址表明一種資源。 資源做爲網址,網址中不能有動詞只能有名詞,通常名詞要與數據庫的表名對 應。並且名詞要使用複數。 錯誤示例: http://www.example.com/getGoods http://www.example.com/listOrders 正確示例: 獲取單個商品 http://www.example.com/app/goods/1 獲取全部商品 http://www.example.com/app/goods 4、使用標準的HTTP方法: 對於資源的具體操做類型,由HTTP動詞表示。 經常使用的HTTP動詞有四個。 GET SELECT :從服務器獲取資源。 POST CREATE :在服務器新建資源。 PUT UPDATE :在服務器更新資源。 DELETE DELETE :從服務器刪除資源。 示例: 獲取指定商品的信息 GET http://www.example.com/goods/ID 新建商品的信息 POST http://www.example.com/goods 更新指定商品的信息 PUT http://www.example.com/goods/ID 刪除指定商品的信息 DELETE http://www.example.com/goods/ID 5、過濾信息: 若是資源數據較多,服務器不能將全部數據一次所有返回給客戶端。API應該提供參數,過濾返回結果。 實例: 指定返回數據的數量 http://www.example.com/goods?limit=10 指定返回數據的開始位置 http://www.example.com/goods?offset=10 指定第幾頁,以及每頁數據的數量 http://www.example.com/goods?page=2&per_page=20 6、狀態碼: 服務器向用戶返回的狀態碼和提示信息,經常使用的有: 200 OK :服務器成功返回用戶請求的數據 201 CREATED :用戶新建或修改數據成功。 202 Accepted:表示請求已進入後臺排隊。 400 INVALID REQUEST :用戶發出的請求有錯誤。 401 Unauthorized :用戶沒有權限。 403 Forbidden :訪問被禁止。 404 NOT FOUND :請求針對的是不存在的記錄。 406 Not Acceptable :用戶請求的的格式不正確。 500 INTERNAL SERVER ERROR :服務器發生錯誤。 7、錯誤信息: 通常來講,服務器返回的錯誤信息,以鍵值對的形式返回。 8、響應結果: 針對不一樣結果,服務器向客戶端返回的結果應符合如下規範。 返回商品列表 GET http://www.example.com/goods 返回單個商品 GET http://www.example.com/goods/cup 返回新生成的商品 POST http://www.example.com/goods 返回一個空文檔 DELETE http://www.example.com/goods 9、使用連接關聯相關的資源: 在返回響應結果時提供連接其餘API的方法,使客戶端很方便的獲取相關聯的信息。 10、其餘: 服務器返回的數據格式,應該儘可能使用JSON,避免使用XML。
1六、Django關閉瀏覽器,怎樣清除cookies和session?
設置Cookie def cookie_set(request): response = HttpResponse("<h1>設置Cookie,請查看響應報文頭</h1>") response.set_cookie('h1', 'hello django') return response 讀取Cookie def cookie_get(request): response = HttpResponse("讀取Cookie,數據以下:<br>") if request.COOKIES.has_key('h1'): response.write('<h1>' + request.COOKIES['h1'] + '</h1>') return response 以鍵值對的格式寫會話 request.session['鍵']=值 根據鍵讀取值 request.session.get('鍵',默認值) 清除全部會話,在存儲中刪除值部分 request.session.clear() 清除會話數據,在存儲中刪除會話的整條數據 request.session.flush() 刪除會話中的指定鍵及值,在存儲中只刪除某個鍵及對應的值 del request.session['鍵'] 設置會話的超時時間,若是沒有指定過時時間則兩個星期後過時。 若是value是一個整數,會話將在value秒沒有活動後過時。 若是value爲0,那麼用戶會話的Cookie將在用戶的瀏覽器關閉時過時。 若是value爲None,那麼會話在兩週後過時。 request.session.set_expiry(value) Session 依賴於 Cookie,若是瀏覽器不能保存 cookie 那麼 session 就失效了。由於它須要瀏覽器的 cookie 值去 session 裏作對比。 session就是用來在服務器端保存用戶的會話狀態。 cookie 能夠有過時時間,這樣瀏覽器就知道何時能夠刪除 cookie了。 若是 cookie 沒有設置過時時間,當用戶關閉瀏覽器的時候,cookie 就自動過時了。你能夠改變 SESSION_EXPIRE_AT_BROWSER_CLOSE 的設置來控制session 框架的這一行爲。缺省狀況下, SESSION_EXPIRE_AT_BROWSER_CLOSE設置爲 False ,這樣,會話 cookie 能夠在用戶瀏覽器中保持有效達SESSION_COOKIE_AGE 秒(缺省設置是兩週,即 1,209,600 秒)若是你不想用戶每次打開瀏覽器都必須從新登錄的話,用這個參數來幫你。若是SESSION_EXPIRE_AT_BROWSER_CLOSE設置爲True,當瀏覽器關閉時,Django會使cookie失效。SESSION_COOKIE_AGE:設置cookie在瀏覽器中存活的時間
面試就喜歡面試官問這種問題,前面就已經說過了,這種問題一提出來,咱們心裏是高興的一筆的,正好將咱們學的Django restframework源碼帶面試官走一波,以後能夠再補充一點Django的其餘源碼,好比ORM源碼,settings源碼, admin源碼...最後必定要記住,你要展現出你不只閱讀過源碼還基於源碼在本身的實際項目中參考借鑑過。若是把面試比做考試題滿 分100的話,這一題就是送分的30分大題!!! 源碼引用博客:https://www.cnblogs.com/forcee/p/11135035.html
--至關於生產者消費者-- 情景:用戶發起request,並等待response返回。在本些views中,可能須要執行一段耗時的程序,那麼用戶就會等待很長時間,形成很差的用戶體驗,好比發送郵件、手機驗證碼等。 使用celery後,狀況就不同了。解決:將耗時的程序放到celery中執行。將多個耗時的任務添加到隊列queue中,也就是用redis實現broker中間人,而後用多個worker去監聽隊列 裏的任務去執行。 任務task:就是一個Python函數。 隊列queue:將須要執行的任務加入到隊列中。 工人worker:在一個新進程中,負責執行隊列中的任務。 代理人broker:負責調度,在佈置環境中使用redis。 正向代理:請求通過代理服務器從局域網發出,而後到達互聯網上的服務器。 特色:服務端並不知道真正的客戶端是誰。 反向代理:請求從互聯網發出,先進入代理服務器,再轉發給局域網內的服務器。 特色:客戶端並不知道真正的服務端是誰。 區別:正向代理的對象是客戶端。反向代理的對象是服務端。
1九、 簡述Django下的(內建的)緩存機制?
Django提供6種緩存方式: 開發調試 內存 文件 數據庫 Memcache緩存(python-memcached模塊) Memcache緩存(pylibmc模塊) 除此以外還可以使用redis緩存 因爲Django是動態網站,全部每次請求均會去數據進行相應的操做,當程序訪問量大時,耗時必然會更加明顯, 最簡單解決方式是使用:緩存,緩存將一個某個views的返回值保存至內存或者memcache中,5分鐘內(默認配置)再有人來訪問時, 則再也不去執行view中的操做,而是直接從內存或者Redis中以前緩存的內容拿到,並返回。 這裏能夠向面試官介紹一下前面提到的Django中間件配合緩存協同工做的機制
首先須要搞清楚的是session是存儲在服務器上的,cookie是存儲在客戶端瀏覽器上的二者是相輔相成的 用戶首次訪問服務器,服務器會爲每一個用戶單首創建一個session對象(HttpSession), 併爲每一個session分配惟一一個id(sessionId),sessionId經過cookie保存到用戶端,當用戶再次訪問服務器時,需將對應的sessionId攜帶給服務器,服務器經過這個惟一sessionId就能夠找到用戶對應的session對象,從而達到管理用戶狀態
2一、Django裏QuerySet的get和filter方法的區別?
1) 輸入參數 get 的參數只能是model中定義的那些字段,只支持嚴格匹配。 filter的參數能夠是字段,也能夠是擴展的 where查詢關鍵字,如 in,like 等。 2) 返回值 get返回值是一個定義的 model 對象。 filter返回值是一個新的 QuerySet 對象,而後能夠對 QuerySet 在進行查詢返回新的 QuerySet 對象,支持鏈式操做,QuerySet 一個 集合對象,可以使用迭代或者遍歷,切片等,可是不等於 list 類型(使用必定要注意)。 3) 異常 get只有一條記錄返回的時候才正常,也就說明 get 的查詢字段必須是主鍵或者惟一約束的字段。當返回多條記錄或者是沒有找到記 錄的時候都會拋出異常。 filter 有沒有匹配的記錄均可以
2二、 django 中當一個用戶登陸 A 應用服務器(進入登陸狀態),而後下次請求被 nginx 代理到 B
應用服務器會出現什麼影響?
若是用戶在A應用服務器登錄的session數據沒有共享到B應用服務器,那麼以前的登陸狀態就沒有了。 1.安裝django-cors-headers,以後在settings.py中配置 pip install django-cors-headers INSTALLED_APPS = [ ... 'corsheaders', ... ] MIDDLEWARE_CLASSES = ( ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # 注意順序 ... ) #跨域增長忽略 CORS_ALLOW_CREDENTIALS = True CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_WHITELIST = ( '*' ) CORS_ALLOW_METHODS = ( 'DELETE', 'GET', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'VIEW', ) CORS_ALLOW_HEADERS = ( 'XMLHttpRequest', 'X_FILENAME', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', 'x-requested-with', 'Pragma', ) 2.使用JSONP 使用Ajax獲取json數據時,存在跨域的限制。不過,在Web頁面上調用js的script腳本文件時卻不受跨域的影響,JSONP就是利用這個 來實現跨域的傳輸。所以,咱們須要將Ajax調用中的dataType從JSON改成JSONP(相應的API也須要支持JSONP)格式。 JSONP只能用於GET請求。 3.直接修改Django中的views.py文件 修改views.py中對應API的實現函數,容許其餘域經過Ajax請求數據: def myview(_request): response = HttpResponse(json.dumps({「key」: 「value」, 「key2」: 「value」})) response[「Access-Control-Allow-Origin」] = 「*」 response[「Access-Control-Allow-Methods」] = 「POST, GET, OPTIONS」 response[「Access-Control-Max-Age」] = 「1000」 response[「Access-Control-Allow-Headers」] = 「*」 return response
2三、Django對數據查詢結果排序怎麼作,降序怎麼作,查詢大於某個字段怎麼作?
排序使用order_by() 降序須要在排序字段名前加查詢字段大於某個值:使用filter(字段名_gt=值) 更多騷操做: models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 且 小於10的值 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、33的數據 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven") # 獲取name字段包含"ven"的 models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 models.Tb1.objects.filter(id__range=[1, 3]) # id範圍是1到3的,等價於SQL的bettwen and 相似的還有:startswith,istartswith, endswith, iendswith date字段還能夠: models.Class.objects.filter(first_day__year=2017)
2四、生成遷移文件和執行遷移文件的命令是什麼?
python manage.py makemigrations python manage.py migrate
2五、uWSGI與uwsgi區別
uWSGI是一個 Web 服務器,它實現了WSGI 協議、uwsgi、http 等協議。注意 uwsgi 是一種通訊協議,而 uWSGI 是實現 uwsgi 協議和 WSGI 協議的Web 服務器。uWSGI 具備超快的性能、低內存佔用和多app 管理等優勢,而且搭配着 Nginx就是一個生產環境了,可以將用戶訪問請求與應用 app 隔離開,實現真正的部署。相比來說,支持的併發量更高,方便管理多進程,發揮多核的優點,提高性能。
2六、apache和nginx的區別?(2018-4-16-lxy)
Nginx相對Apache的優勢: 輕量級,一樣起web 服務,比apache 佔用更少的內存及資源; 抗併發,nginx 處理請求是異步非阻塞的,支持更多的併發鏈接,而apache 則是阻塞型的,在高併發下nginx 能保持低資源低消耗高性能; 配置簡潔; 高度模塊化的設計,編寫模塊相對簡單;社區活躍。 Apache相對Nginx的優勢: rewrite ,比nginx 的rewrite 強大; 模塊超多,基本想到的均可以找到; 少bug ,nginx 的bug 相對較多; 超穩定。
git clone 克隆指定倉庫 git status 查看當前倉庫狀態 git diff 比較版本的區別 git log 查看 git 操做日誌 git reset 回溯歷史版本 git add 將文件添加到暫存區 git commit 將文件提交到服務器 git checkout 切換到指定分支 git rm 刪除指定文件 (命令好記,實際操做就相對較難,平時應有意識地去鍛鍊使用git管理咱們的代碼倉庫)
2八、什麼是gitlab,github和gitlab的區別?
公司開始把代碼從GitHub上遷移到GitLab上,在使用一段時間事後,發現GitLab與GitHub仍是有很多區別的。 先說一下相同點,兩者都是基於web的Git倉庫,在很大程度上GitLab是仿照GitHub來作的,它們都提供了分享開源項目的平臺,爲開發團隊提供了存儲、分享、發佈和合做開發項目的中心化雲存儲的場所。 GitHub做爲開源代碼庫及版本控制系統,擁有超過900萬的開發者用戶,目前仍然是最火的開源項目託管系統。GitHub同時提供公共倉庫和私有倉庫,但若是要使用私有倉庫,是須要付費的。 而GitLab解決了這個問題,你能夠在上面建立私人的免費倉庫。 GitLab讓開發團隊對他們的代碼倉庫擁有更多的控制,相比於GitHub,它有很多的特點: 容許免費設置倉庫權限;容許用戶選擇分享一個project的部分代碼;容許用戶設置project的獲取權限,進一步的提高安全性;能夠設置獲取到團隊總體的改進進度;經過innersourcing讓不在權限範圍內的人訪問不到該資源。 從代碼私有性方面來看,有時公司並不但願員工獲取到所有的代碼,這個時候GitLab無疑是更好的選擇。但對於開源項目而言, GitHub依然是代碼託管的首選。 公司開始把代碼從GitHub上遷移到GitLab上,在使用一段時間事後,發現GitLab與GitHub仍是有很多區別的。 先說一下相同點,兩者都是基於web的Git倉庫,在很大程度上GitLab是仿照GitHub來作的,它們都提供了分享開源項目的平臺,爲 開發團隊提供了存儲、分享、發佈和合做開發項目的中心化雲存儲的場所。 GitHub做爲開源代碼庫及版本控制系統,擁有超過900萬的開發者用戶,目前仍然是最火的開源項目託管系統。GitHub同時提供公共 倉庫和私有倉庫,但若是要使用私有倉庫,是須要付費的。 而GitLab解決了這個問題,你能夠在上面建立私人的免費倉庫。 GitLab讓開發團隊對他們的代碼倉庫擁有更多的控制,相比於GitLab,它有很多的特點: 容許免費設置倉庫權限;容許用戶選擇分享一個project的部分代碼;容許用戶設置project的獲取權限,進一步的提高安全性;能夠 設置獲取到團隊總體的改進進度;經過innersourcing讓不在權限範圍內的人訪問不到該資源。 從代碼私有性方面來看,有時公司並不但願員工獲取到所有的代碼,這個時候GitLab無疑是更好的選擇。但對於開源項目而言, GitHub依然是代碼託管的首選。
# 此爲註釋 – 將被 Git 忽略 *.a # 忽略全部 .a 結尾的文件 !lib.a # 但 lib.a 除外 /TODO # 僅僅忽略項目根目錄下的 TODO 文件,不包括 subdir/TODO build/ # 忽略 build/ 目錄下的全部文件 doc/*.txt # 會忽略 doc/notes.txt 但不包括 doc/server/arch.txt
30、HttpRequest和HttpResponse是什麼?幹嗎用的?
HttpRequest是django接受用戶發送多來的請求報文後,將報文封裝到HttpRequest對象中去。 HttpResponse 返回的是一個應答的數據報文。render內部已經封裝好了HttpResponse類。 視圖的第一個參數必須是HttpRequest對象,兩點緣由:表面上說,他是處理web請求的,因此必須是請求對象,根本上說,他是基 於請求的一種web框架,因此,必須是請求對象。 由於view處理的是一個request對象,請求的全部屬性咱們均可以根據對象屬性的 查看方法來獲取具體的信息:格式:request.屬性 request.path 請求頁面的路徑,不包含域名 request.get_full_path 獲取帶參數的路徑 request.method 頁面的請求方式 request.GET GET 請求方式的數據 request.POST POST請求方式的數據 request.COOKIES 獲取cookie request.session 獲取session request.FILES 上傳圖片(請求頁面有enctype="multipart/form-data"屬性時FILES纔有數據)
3一、 什麼是反向解析
使用場景:模板中的超連接,視圖中的重定向 使用:在定義url時爲include定義namespace屬性,爲url定義name屬性 在模板中使用url標籤:{% url 'namespace_value:name_value'%} 在視圖中使用reverse函數:redirect(reverse('namespce_value:name_value’)) 根據正則表達式動態生成地址,減輕後期維護成本。 注意反向解析傳參數,主要是在咱們的反向解析的規則後面天界了兩個參數,兩個參數之間使用空格隔開:<a href="{% url 'booktest:fan2' 2 3 %}">位置參數</a>
GET 請求指定的頁面信息,並返回實體主體。 HEAD 相似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭 POST 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會致使新的資源的創建和/或已有資源的修改。 PUT 從客戶端向服務器傳送的數據取代指定的文檔的內容。 DELETE 請求服務器刪除指定的頁面。 CONNECT HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。 OPTIONS 容許客戶端查看服務器的性能。 TRACE 回顯服務器收到的請求,主要用於測試或診斷。
狀態代碼有三位數字組成,第一個數字定義了響應的類別,共分五種類別: 1xx:指示信息--表示請求已接收,繼續處理 2xx:成功--表示請求已被成功接收、理解、接受 3xx:重定向--要完成請求必須進行更進一步的操做 4xx:客戶端錯誤--請求有語法錯誤或請求沒法實現 5xx:服務器端錯誤--服務器未能實現合法的請求 常見狀態碼: 200 OK //客戶端請求成功 400 Bad Request //客戶端請求有語法錯誤,不能被服務器所理解 401 Unauthorized //請求未經受權,這個狀態代碼必須和WWW-Authenticate報頭域一塊兒使用 403 Forbidden //服務器收到請求,可是拒絕提供服務 404 Not Found //請求資源不存在,eg:輸入了錯誤的URL 500 Internal Server Error //服務器發生不可預期的錯誤 503 Server Unavailable //服務器當前不能處理客戶端的請求,一段時間後可能恢復正常 更多狀態碼http://www.runoob.com/http/http-status-codes.html
http的中文叫作超文本傳輸協議,它負責完成客戶端到服務端的一系列操做,是專門用來傳輸注入HTML的超媒體文檔等web內容的協議,它是基於傳輸層的TCP協議的應用層協議 https:https是基於安全套接字的http協議,也能夠理解爲是http+ssl/tls(數字證書)的組合 http和https的區別: HTTP 的 URL 以 http:// 開頭,而 HTTPS 的 URL 以 https:// 開頭 HTTP 是不安全的,而 HTTPS 是安全的 HTTP 標準端口是 80 ,而 HTTPS 的標準端口是 443 在 OSI 網絡模型中,HTTPS的加密是在傳輸層完成的,由於SSL是位於傳輸層的,TLS的前身是SSL,因此同理 HTTP無需認證證書,而https須要認證證書
3五、簡述websocket協議及實現原理
websocket是一種在單個TCP鏈接上進行全雙工通信的協議,雙工(duplex)是指兩臺通信設備之間,容許有雙向的資料傳輸。全雙工的是指,容許兩臺設備間同時進行雙向資料傳輸。這是相對於半雙工來講的,半雙工不能同時進行雙向傳輸,這期間的區別至關於手機和對講機的區別,手機在講話的同時也能聽到對方說話,對講機只能一個說完另外一個才能說。
3六、django 中如何實現 websocket?
django實現websocket大體上有兩種方式,一種channels,一種是dwebsocket。channels依賴於redis,twisted等,相比之下使用 dwebsocket要更爲方便一些。 安裝 # pip install dwebsocket 配置: # setting.py INSTALLED_APPS = [ ..... ..... 'dwebsocket', ] MIDDLEWARE_CLASSES = [ ...... ...... 'dwebsocket.middleware.WebSocketMiddleware' # 爲全部的URL提供websocket,若是隻是單獨的視圖須要能夠不選 ] WEBSOCKET_ACCEPT_ALL=True # 能夠容許每個單獨的視圖實用websockets 簡單使用: 模擬文件下載的簡單示例 from dwebsocket.decorators import accept_websocket @accept_websocket def test(request): if not request.is_websocket(): # 判斷是否是websocket鏈接 return render(request, 'websocket.html') else: download = Haproxy() t = threading.Thread(target=download.run) t.start() sent = [] while download.status: if len(download.res_dict) > len(sent): for i in download.res_dict.keys(): if i not in sent: sent.append(i) request.websocket.send(str(sent[-1]+str(download.res_dict[sent[-1]])).encode('utf-8')) # 發送消息到客戶端 if not download.status: request.websocket.send('下載完成'.encode('utf-8')) -------------------------------------------------------------------- dwebsocket有兩種裝飾器:require_websocket和accept_websocekt,使用require_websocket裝飾器會致使視圖函數沒法接收致使 正常的http請求,通常狀況使用accept_websocket方式就能夠了, dwebsocket的一些內置方法: request.is_websocket():判斷請求是不是websocket方式,是返回true,不然返回false request.websocket: 當請求爲websocket的時候,會在request中增長一個websocket屬性, WebSocket.wait() 返回客戶端發送的一條消息,沒有收到消息則會致使阻塞 WebSocket.read() 和wait同樣能夠接受返回的消息,只是這種是非阻塞的,沒有消息返回None WebSocket.count_messages()返回消息的數量 WebSocket.has_messages()返回是否有新的消息過來 WebSocket.send(message)像客戶端發送消息,message爲byte類型
# 方案1.安裝django-cors-headers pip install django-cors-header 配置settings.py文件 INSTALLED_APPS = [ ... 'corsheaders', ... ] MIDDLEWARE_CLASSES = ( ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # 注意順序 ... ) #跨域增長忽略 CORS_ALLOW_CREDENTIALS = True CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_WHITELIST = ( '*' ) CORS_ALLOW_METHODS = ( 'DELETE', 'GET', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'VIEW', ) CORS_ALLOW_HEADERS = ( 'XMLHttpRequest', 'X_FILENAME', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', 'x-requested-with', 'Pragma', ) # 方案2.使用JSONP 使用Ajax獲取json數據時,存在跨域的限制。不過,在Web頁面上調用js的script腳本文件時卻不受跨域的影響,JSONP就是利用這個來實現跨域的傳輸。所以,咱們須要將Ajax調用中的dataType從JSON改成JSONP(相應的API也須要支持JSONP)格式。 JSONP只能用於GET請求。 # 方案3.直接修改Django中的views.py文件 修改views.py中對應API的實現函數,容許其餘域經過Ajax請求數據: def myview(_request): response = HttpResponse(json.dumps({「key」: 「value」, 「key2」: 「value」})) response[「Access-Control-Allow-Origin」] = 「*」 response[「Access-Control-Allow-Methods」] = 「POST, GET, OPTIONS」 response[「Access-Control-Max-Age」] = 「1000」 response[「Access-Control-Allow-Headers」] = 「*」 return response
3八、什麼是wsgi?
WSGI的全稱是Web Server Gateway Interface,翻譯過來就是Web服務器網關接口。具體的來講,WSGI是一個規範,定義了Web服務器如何與Python應用程序進行交互,使得使用Python寫的Web應用程序能夠和Web服務器對接起來。
3九、列舉django的內置組件?
.Admin是對model中對應的數據表進行增刪改查提供的組件 .model組件:負責操做數據庫 .form組件:1.生成HTML代碼2.數據有效性校驗3校驗信息返回並展現 .ModelForm組件即用於數據庫操做,也可用於用戶請求的驗證
40、django 中 model 的 SlugField 類型字段有什麼用途
SlugField本質上至關於存放字符串,可是在乎義上,主要用於把某些字段造成語義化的,能夠訪問的短網站(slug)字符串。
4一、django 中想要驗證表單交是否格式正確須要用到 form 中的那個方法
A. form.save() B. form.save(commit=False) C. form.verify() D. form.is_valid() *****
4二、.使用Django中modelfilter條件過濾方法,把下邊sql語句轉化成python 代
select * from company where title like "%abc%" or mecount>999 order by createtime desc;
4三、.django 對數據查詢結果排序怎麼作, 降序怎麼作
排序使用order_by() 降序須要在排序字段名前加- 查詢字段大於某個值:使用filter(字段名_gt=值)
4四、下面關於http協議中的get和post方式的區別,那些是錯誤的?(多選
A. 他們均可以被收藏, 以及緩存 B. get請求參數放在url中 C. get只用於查詢請求,不能用於數據請求 D. get不該該處理敏感數據的請求
4五、.django 中使用 memcached 做爲緩存的具體方法? 優缺點說明?
安裝: 首先要在django運行環境中安裝:python-memcached(命令:pip install python-memcached) 1)在Django的settings中設置緩存 CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': ,'127.0.0.1:11211', # 能夠爲遠程地址和端口,能夠設置多個ip 'TIMEOUT': 86400, # 1 day,設置成0緩存將失效 'OPTIONS': { 'MAX_ENTRIES': 1000, # 高速緩存容許的最大條目數,超出這個數則舊值將被刪除. 這個參數默認是300. 'CULL_FREQUENCY': 3, # 當達到MAX_ENTRIES 的時候,被刪除的條目比率。 實際比率是 1 / CULL_FREQUENCY,默認是3 } } } 2)業務邏輯 #coding=utf-8 def key_hash(value): """hash緩存key,防止過長""" import hashlib return '%s' % hashlib.md5(value).hexdigest() def cache(num1, num2): """ :param num1: 獲取或者設置cache的標識 :param num2:獲取或者設置cache的標識 :return: 緩存dict """ from django.core.cache import cache import logging log = logging.getLogger(__name__) # 日誌 # 去重並排序,增長緩存命中率 cache_key = 'num1={num1}&num2={num2}'.format(num1=num1, num2=num2) cache_key = key_hash(cache_key) # in cache, return cache if cache.get(cache_key): log.debug('cache %s hitting ' % cache_key) return cache.get(cache_key) # not in cache, get result and set cache ret = None # TODO do something get result ret = 'something' cache.set(cache_key, ret, 60 * 60 * 24) # 一天過時 return ret
4六、使用Django中modelfilter條件過濾方法,把下邊sql語句轉化成python 代碼
select * from company where title like "%abc%" or mecount>999 order by createtime desc;
4七、從輸入http://www.baidu.com/到頁面返回,中間都是發生了什麼?
一、域名解析: 瀏覽器向DNS獲取web服務器 www.baidu.com這個域名的 的ip地址 二、創建TCP鏈接 瀏覽器與對應ip地址的服務器進行TCP連接,端口爲80 三、瀏覽器執行HTTP協議,發送GET請求,讀取對應文件 四、服務器接收到請求後,返回網頁信息 5.客戶端瀏覽器將這些信息組織成用戶能夠查看的網頁形式
. 當用戶在瀏覽器中輸入url時,瀏覽器會生成請求頭和請求體發給服務端 請求頭和請求體中會包含瀏覽器的動做(action),這個動做一般爲get或者post,體如今url之中. . url通過Django中的wsgi,再通過Django的中間件,最後url到過路由映射表,在路由中一條一條進行匹配, 一旦其中一條匹配成功就執行對應的視圖函數,後面的路由就再也不繼續匹配了. . 視圖函數根據客戶端的請求查詢相應的數據.返回給Django,而後Django把客戶端想要的數據作爲一個字符串返回給客戶端. . 客戶端瀏覽器接收到返回的數據,通過渲染後顯示給用戶.
利用Django的Model的Signal Dispatcher, 經過django.db.models.signals.pre_save()方法, 在事件發生前,發射觸發信號, 這一切都被調度中的receiver方法深藏功與名的保存了。 信號的處理通常都寫在Model中, 舉個例子: import logging from django.db import models from django.db.models.signals import pre_save from django.dispatch import receiver class Order(models.Model): logger = logging.getLogger(__name__) @receiver(pre_save, sender=Order) def pre_save_handler(sender, **kwargs): logger.debug("{},{}".format(sender, **kwargs))
`class WSGIHandler(base.BaseHandler):` `-------request = self.request_class(environ)` 請求走到WSGIHandler類的時候,執行**cell**方法,將environ封裝成了request
5一、簡述django中間件及其應用場景?
.process_request : 請求進來時,權限認證 .process_view : 路由匹配以後,可以獲得視圖函數 .process_exception : 異常時執行 .process_template_responseprocess : 模板渲染時執行 .process_response : 請求有響應時執行
5二、簡述 django FBV 和 CBV?
FBV和CBV本質是同樣的,基於函數的視圖叫作FBV,基於類的視圖叫作CBV 在python中使用CBV的優勢: .提升了代碼的複用性,能夠使用面嚮對象的技術,好比Mixin(多繼承) .能夠用不一樣的函數針對不一樣的HTTP方法處理,而不是經過不少if判斷,提升代碼可讀性
5三、如何給 django CBV 的函數設置添加裝飾器?
from django.utils.decorators import method_decorator 一、給方法加: @method_decorator(check_login) def post(self, request): ... 二、給dispatch加: @method_decorator(check_login) def dispatch(self, request, *args, **kwargs): ... 三、給類加: @method_decorator(check_login, name="get") @method_decorator(check_login, name="post") class HomeView(View): ...
5四、django 如何鏈接多個數據庫並實現讀寫分離?
在配置文件中增長slave數據庫的配置 在Django的配置文件settings.py中,DATABASES中添加代碼以下: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', # 主服務器的運行ip 'PORT': 3306, # 主服務器的運行port 'USER': 'django', # 主服務器的用戶名 'PASSWORD': 'django', # 主服務器的密碼 'NAME': 'djangobase' # 數據表名 }, 'slave': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', 'PORT': 8306, 'USER': 'django_slave', 'PASSWORD': 'django_slave', 'NAME': 'djangobase_slave' } } 建立數據庫操做的路由分類 在項目的utils中建立db_router.py文件,並在該文件中定義一個db類,用來進行讀寫分離 class MasterSlaveDBRouter(object): """數據庫主從讀寫分離路由""" def db_for_read(self, model, **hints): """讀數據庫""" return "slave" def db_for_write(self, model, **hints): """寫數據庫""" return "default" def allow_relation(self, obj1, obj2, **hints): """是否運行關聯操做""" return True 配置讀寫分離路由 在配置文件中增長: #配置讀寫分離 DATABASE_ROUTERS = ['項目名.utils.db_router."自定義的類名稱"']
5五、列舉 django orm 中你瞭解的全部方法?
# QuerySet對象的全部方法 <1> all(): 查詢全部結果 <2> filter(**kwargs): 它包含了與所給篩選條件相匹配的對象。獲取不到返回None <3> get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個。 若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。 <4> exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象 <5> order_by(*field): 對查詢結果排序 <6> reverse(): 對查詢結果反向排序 <8> count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。 <9> first(): 返回第一條記錄 <10> last(): 返回最後一條記錄 <11> exists(): 若是QuerySet包含數據,就返回True,不然返回False <12> values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的 並非一系 model的實例化對象,而是一個可迭代的字典序列 <13> values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 <14> distinct(): 從返回結果中剔除重複紀錄
5六、django 中的 F 的做用?
像以前咱們所瞭解的一些過濾的例子和操做都是在針對字段值和某一個常量之間做比較,可是若是咱們要針對兩個字段值做比較的話就不行了,這就涉及到這個F查詢了
5七、django 中的 Q 的做用?
filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。 若是你須要執行更復雜的查詢(例如OR語句),你能夠使用Q對象。
5八、django 中如何執行原生 SQL?
1.使用execute執行自定義的SQL 直接執行SQL語句(相似於pymysql的用法) # 更高靈活度的方式執行原生SQL語句 from django.db import connection cursor = connection.cursor() cursor.execute("SELECT DATE_FORMAT(create_time, '%Y-%m') FROM blog_article;") ret = cursor.fetchall() print(ret) 2.使用extra方法 :queryset.extra(select={"key": "原生的SQL語句"}) 3.使用raw方法 1.執行原始sql並返回模型 2.依賴model多用於查詢
5九、only 和 defer 的區別?
defer('id','name'):取出對象,字段除了id和name都有 only('id','name'):取的對象,只有id和name
60、select_related 和 prefetch_related 的區別?
前提:有外鍵存在時,能夠很好的減小數據庫請求的次數,提升性能 select_related經過多表join關聯查詢,一次性得到全部數據,只執行一次SQL查詢 prefetch_related分別查詢每一個表,而後根據它們之間的關係進行處理,執行兩次查詢
6一、django 中 filter 和 exclude 的區別
二者取到的值都是QuerySet對象,filter選擇知足條件的,exclude:排除知足條件的
6二、django 中 values 和 values_list 的區別?
values : queryset類型的列表中是字典 values_list : queryset類型的列表中是元組
6三、如何使用 django orm 批量建立數據?
objs=[models.Book(title="圖書{}".format(i+15)) for i in range(100)] models.Book.objects.bulk_create(objs)
6四、django 的 Form 和 ModeForm 的做用?
Form組件的主要功能以下: 生成頁面可用的HTML標籤 ——>只能生成獲取用戶信息的那些input標籤等 對用戶提交的數據進行校驗,返回錯誤提示信息 保留頁面上用戶輸入的內容 ModelForm組件,這個組件主要就是將model與Form組件的功能結合起來,能夠更加便捷的對數據進行添加、編輯以及數據的驗證操做。相對於單獨的Form組價來講要方便不少。可是Form組件會比這個ModelForm組件更加靈活,若是在使用Django作web開發過程當中驗證的數據和數據庫字段相關(能夠對錶進行增、刪、改操,注意 Many to many字段,也能夠級聯操做第3張關係表;),建議優先使用ModelForm,用起來更方便些,可是在使用ModelForm的時候慎用fields='__all__',獲取數據庫全部字段勢必形成資源的浪費。
6五、django 的 Form 組件中,若是字段中包含 choices 參數,請使用兩種方式 實現數據源實時更
新。
1.重寫構造函數 def__init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["city"].widget.choices = models.City.objects.all().values_list("id", "name") 2.利用ModelChoiceField字段,參數爲queryset對象 authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())//多選
6六、django 的 Model 中的 ForeignKey 字段中的 on_delete 參數有什麼做用?
刪除關聯表中的數據時,當前表與其關聯的field的操做 django2.0以後,表與表之間關聯的時候,必需要寫on_delete參數,不然會報異常
6七、基於django使用ajax發送post請求時,有哪一種方法攜帶csrftoken?
1.後端將csrftoken傳到前端,發送post請求時攜帶這個值發送 data: { csrfmiddlewaretoken: '{{ csrf_token }}' }, 2.獲取form中隱藏標籤的csrftoken值,加入到請求數據中傳給後端 data: { csrfmiddlewaretoken:$('[name="csrfmiddlewaretoken"]').val() }, 3.cookie中存在csrftoken,將csrftoken值放到請求頭中 headers:{ "X-CSRFtoken":$.cookie("csrftoken")}
6八、django 的緩存能使用 redis 嗎?若是能夠的話,如何配置?
# 設置django緩存存放位置爲redis數據庫,並設置一個默認(default)選項,在redis中(配置文件/etc/redis/redis.conf)開啓了RDB持久化儲存 # pip install django-redis, 而後在視圖中能夠經過 from django_redis import get_redis_connection 這個方法和redis數據庫進行鏈接 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", # redis服務器的ip地址及端口號,及數據庫序號,redis一共有15個數據庫 0~15 "LOCATION": "redis://127.0.0.1:6379/6", # "LOCATION": "redis://:passwordpassword@47.193.146.xxx:6379/0", # 若是redis設置密碼的話,須要以這種格式進行設置,host前面是密碼 "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } }
6九、django 路由系統中 name 的做用?
name:對URL路由關係進行命名
70、django 的模板中 filter、simpletag、inclusiontag 的區別?
filter的用法: #先引入template from django import template #聲明register,名字只能是register register = template.Library() #帶名字的裝飾器,調用的時候用起的名字 如dsb @register.filter(name='dsb') def add_sb(value, arg): return "{}_{}abc".format(value, arg) @register.filter def add_sb(value, arg): return "{}_{}_abc".format(value, arg) 自定義simpletag和自定義inclusion_tag 1. 在app下建立一個名叫templatetags的python包 2. 在templatetags裏建一個py文件 simpletag的用法: 和自定義filter相似,只不過接收更靈活的參數。
7一、django-debug-toolbar 的做用?
django開發調試工具 django-debug-toolbar 是一組可配置的面板,可顯示有關當前請求/響應的各類調試信息,並在單擊時顯示有關面板內容的更多詳細信息。
7二、django 中如何實現單元測試?
Django的單元測試使用python的unittest模塊,這個模塊使用基於類的方法來定義測試。類名爲django.test.TestCase,繼承於python的unittest.TestCase。 執行目錄下全部的測試(全部的test*.py文件):運行測試的時候,測試程序會在全部以test開頭的文件中查找全部的test cases(inittest.TestCase的子類),自動創建測試集而後運行測試。 $ python manage.py test 執行animals項目下tests包裏的測試: $ python manage.py testanimals.tests 執行animals項目裏的test測試: $ python manage.py testanimals 單獨執行某個test case: $ python manage.py testanimals.tests.AnimalTestCase 單獨執行某個測試方法: $ python manage.py testanimals.tests.AnimalTestCase.test_animals_can_speak 爲測試文件提供路徑: $ python manage.py testanimals/ 通配測試文件名: $ python manage.py test--pattern="tests_*.py" 啓用warnings提醒: $ python -Wall manage.py test
7三、解釋orm中dbfirst和codefirst的含義?
Code First From Database(DbFirst)數據庫先行 Code First(代碼先行)
7四、django 中如何根據數據庫表生成 model 類?
建立一個項目,修改setting文件,在setting裏面設置你要鏈接的數據庫類型和鏈接名稱,地址之類,和建立新項目的時候一致 1.運行下面代碼能夠自動生成models模型文件 python manage.py inspectdb 2.把模型文件導入到app中 建立app django-admin.py startapp app 將模型導入建立的app中 python manage.py inspectdb > app/models.py
7五、使用orm和原生sql的優缺點?
相對來講,ORM的缺點就是SQL的優點地方,而有點也是SQL的劣勢地方 優勢 方便的使用面向對象,語句清晰 防注入『這個其實不算ORM的核心,由於好比Phalcon的SQL形式寫法也能夠防注入』 方便動態構造語句,對於不一樣的表的相同操做採用多態實現更優雅 必定程度方便重構數據層『好比改表名,字段名等』 設置鉤子函數 缺點 不太容易處理複雜查詢語句 性能較直接用SQL差
一、Flask 中正則 URL 的實現?
app.route('')中 URL 顯式支持 string、int、float、path uuid any 6種類型,隱式支持正則。 第一步: 寫正則類,繼承 BaseConverter,將匹配到的值設置爲 regex 的值。 1. class RegexUrl(BaseConverter): 2. def __init__(self, url_map, *args): 3. super(RegexUrl, self).__init__(url_map) 4. self.regex = args[0] 第二步: 把正則類賦值給咱們定義的正則規則。 5. app.url_map.converters['re'] = RegexUrl 第三步: 在 URL 中使用正則。 6. @app.route('/regex/<re("[a-z]{3}"):id>') 7. def regex111(id): 8. return 'id:%s'%id
current_app、g 是應用上下文。 request、session 是請求上下文。 手動建立上下文的兩種方法: 1. with app.app_context() 2. app = current_app._get_current_object() 二者區別: 請求上下文:保存了客戶端和服務器交互的數據。 應用上下文:flask 應用程序運行過程當中,保存的一些配置信息,好比程序名、數據庫鏈接、應用信息等。 二者做用: 請求上下文(request context): Flask從客戶端收到請求時,要讓視圖函數能訪問一些對象,這樣才能處理請求。請求對象是一個很好的例子,它封裝了客戶端發送 的HTTP請求。 要想讓視圖函數可以訪問請求對象,一個顯而易見的方式是將其做爲參數傳入視圖函數,不過這會致使程序中的每一個視圖函數都增長 一個參數,除了訪問請求對象,若是視圖函數在處理請求時還要訪問其餘對象,狀況會變得更糟。爲了不大量無關緊要的參數把視 圖函數弄得一團糟, Flask使用上下文臨時把某些對象變爲全局可訪問。 應用上下文(application context): 它的字面意思是 應用上下文,但它不是一直存在的,它只是request context 中的一個對 app 的代理(人),所謂local proxy。它的做 用主要是幫助 request 獲取當前的應用,它是伴 request 而生,隨 request 而滅的。
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test' 動態追蹤修改設置,如未設置只會提示警告 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True 查詢時會顯示原始SQL語句 app.config['SQLALCHEMY_ECHO'] = True 更多詳情:https://www.cnblogs.com/xiaoyuanqujing/articles/11722772.html
更多詳情:https://www.cnblogs.com/xiaoyuanqujing/articles/11722772.html
1) 藍圖的定義 藍圖 /Blueprint 是Flask應用程序組件化的方法,能夠在一個應用內或跨越多個項目共用藍圖。 使用藍圖能夠極大地簡化大型應用的開發難度,也爲 Flask擴展 提供了一種在應用中註冊服務的集中式機制。 2) 藍圖的應用場景 1. 把一個應用分解爲一個藍圖的集合。這對大型應用是理想的。一個項目能夠實例化一個應用對象,初始化幾個擴展,並註冊一 集合的藍圖。 1. 以 URL 前綴和/或子域名,在應用上註冊一個藍圖。 URL 前綴/子域名中的參數即成爲這個藍圖下的所 有視圖函數的共同的視圖參數(默認狀況下)。 2. 在一個應用中用不一樣的 URL 規則屢次註冊一個藍圖。 3. 經過藍圖提供模板過濾器、靜態文件、模板和其它功能。一個藍圖不必定要實現應用或者視圖函數。 4. 初始化一個 Flask 擴展時,在這些狀況中註冊一個藍圖。 3) 藍圖的缺點 不能在應用建立後撤銷註冊一個藍圖而不銷燬整個應用對象。 4)使用藍圖的三個步驟 1.建立一個藍圖對象 blue = Blueprint("blue",__name__) 2.在這個藍圖對象上進行操做,例如註冊路由、指定靜態文件夾、註冊模板過濾器 @blue.route('/') def blue_index(): return 'Welcome to my blueprint' 3.在應用對象上註冊這個藍圖對象 app.register_blueprint(blue,url_prefix='/blue') 字段對象 說明 FieldList 一組指定類型的字段 WTForms經常使用驗證函數 InputRequired 確保字段中有數據 DataRequired 確保字段中有數據而且數據爲真 EqualTo 比較兩個字段的值,經常使用於比較兩次密碼輸入 Length 驗證輸入的字符串長度 NumberRange 驗證輸入的值在數字範圍內 URL 驗證URL AnyOf 驗證輸入值在可選列表中 NoneOf 驗證輸入值不在可選列表中 使用Flask-WTF須要配置參數SECRET_KEY。 CSRF_ENABLED是爲了CSRF(跨站請求僞造)保護。 SECRET_KEY用來生成加密令牌,當CSRF激活的時候,該設置會根據設置的密匙生成加密令牌。
Flask中有三個 session: 第一個:數據庫中的 session,例如:db.session.add() 第二個:在 flask_session 擴展中的 session,使用:from flask_session importSession,使用第三方擴展的 session 能夠把信息存儲在服務器中,客戶端瀏覽器中只存儲 sessionid。 第三個:flask 自帶的 session,是一個請求上下文, 使用:from flask import session。自帶的session 把信息加密後都存儲在客戶端的瀏覽器 cookie 中。
1.能夠經過 postman 測試工具測試,或者看 log 日誌信息找到錯誤信息的大概位置。 2.斷點調試
1.URL反轉: 根據視圖函數名稱獲得當前所指向的url。 2.url_for() 函數最簡單的用法是以視圖函數名做爲參數,返回對應的url,還能夠用做加載靜態文件。 <link rel="stylesheet" href="{{url_for('static',filename='css/index.css')}}"> 該條語句就是在模版中加載css靜態文件。 3.url_for 和 redirect 區別 url_for是用來拼接 URL 的,能夠使用程序 URL 映射中保存的信息生成 URL。url_for() 函數最簡單的用法是以視圖函數名做爲參數, 返回對應的 URL。例如,在示例程序中 hello.py 中調用 url_for('index') 獲得的結果是 /。 redirect 是重定向函數,輸入一個URL後,自動跳轉到另外一個URL所在的地址,例如,你在函數 中寫 return redirect('https://www.baidu.com') 頁面就會跳轉向百度頁面。 1. from flask import Flask,redirect,url_for 2. app = Flask(__name__) 3. @app.route('/') 4. def index(): 5. login_url = url_for('login') 6. return redirect(login_url) 7. return u'這是首頁' 8. 9. @app.route('/login/') 10. def login(): 11. return u'這是登錄頁面' 12. 13. @app.route('/question/<is_login>/') 14. def question(is_login): 15. if is_login == '1': 16. return u'這是發佈問答的頁面' 17. else: 18. return redirect(url_for('login')) 19. 20. if __name__ == '__main__': 21. app.run(debug=True)
請求鉤子是經過裝飾器的形式實現的,支持如下四種: 1,before_first_request在處理第一個請求前運行 2,before_request:在每次請求前運行 3,after_request:若是沒有未處理的異常拋出,在每次請求後運行 4,teardown_request:即便有未處理的異常拋出,在每次請求後運行 應用: 請求鉤子 1. @api.after_request 2. def after_request(response): 3. """設置默認的響應報文格式爲 application/json""" 4. # 若是響應報文 response 的 Content-Type 是以 text 開頭,則將其改成 5. # 默認的 json 類型 6. if response.headers.get("Content-Type").startswith("text"): 7. response.headers["Content-Type"] = "application/json" 8. return respon
{{ expression | filter1 | filter2 | ... }} 即表達式(expression)使用filter1 過濾後再將filter1的結果去使用 filter2 過濾。
十一、如何把整個數據庫導出來,再導入指定數據庫中?
導出: mysqldump [-h 主機] -u 用戶名 -p 數據庫名 > 導出的數據庫名.sql 導入指定的數據庫中: 第一種方法: mysqldump [-h 主機] -u 用戶名 -p 數據庫名 < 導出的數據庫名.sql 第二種方法: 先建立好數據庫,由於導出的文件裏沒有建立數據庫的語句,若是數據庫已經建好,則不用再建立。 create database example charset=utf8;(數據庫名能夠不同) 切換數據庫: use example; 導入指定 sql 文件: mysql>source /path/example.sql
十二、Flask和Django路由映射的區別?
在django中,路由是瀏覽器訪問服務器時,先訪問的項目中的url,再由項目中的url找到應用中url,這些url是放在一個列表裏,聽從 從前日後匹配的規則。在flask中,路由是經過裝飾器給每一個視圖函數提供的,並且根據請求方式的不一樣能夠一個url用於不一樣的做用。
1三、跨站請求僞造和跨站請求保護的實現?
圖中Browse是瀏覽器,WebServerA是受信任網站/被攻擊網站A,WebServerB是惡意網站/點 擊網站B。 (1)一開始用戶打開瀏覽器,訪問受信任網站A,輸入用戶名和密碼登錄請求登錄網站A。 (2)網站A驗證用戶信息,用戶信息經過驗證後,網站A產生Cookie信息並返回給瀏覽器。 (3)用戶登錄網站A成功後,能夠正常請求網站A。 (4)用戶未退出網站A以前,在同一瀏覽器中,打開一個TAB訪問網站B。 (5)網站B看到有人方式後,他會返回一些攻擊性代碼。 (6)瀏覽器在接受到這些攻擊性代碼後,促使用戶不知情的狀況下瀏覽器攜帶Cookie(包括sessionId)信息,請求網站A。這種請 求有可能更新密碼,添加用戶什麼的操做。 從上面CSRF攻擊原理能夠看出,要完成一次CSRF攻擊,須要被攻擊者完成兩個步驟: 1.登錄受信任網站A,並在本地生成COOKIE。 2.在不登出A的狀況下,訪問危險網站B。 若是不知足以上兩個條件中的一個,就不會受到CSRF的攻擊,如下狀況可能會致使CSRF: 1.登陸了一個網站後,打開一個tab頁面並訪問另外的網站。 2.關閉瀏覽器了後,本地的Cookie還沒有過時,你上次的會話尚未已經結束。(事實上,關閉瀏覽器不能結束一個會話,但大多數人解決辦法:就是在表單中添加from.srcf_token
1四、Flask(name )中的__name__能夠傳入哪些值?
能夠傳入的參數: 1,字符串:‘hello’, 可是‘abc’,不行,由於abc是python內置的模塊 2,__name__,約定俗成 不能夠插入的參數 1,python內置的模塊,re,urllib,abc等 2,數字
1五、請手寫一個 flask 的 Hello World。
from flask import Flask;------->引入Flask插件,pip install Flask; app=Flask(__name__) #變量app是Flask的一個實例而且必須傳入一個參數,__name__對應的值是__main,即當前的py文件的文件名做爲Flask的程序名稱,這個也能夠自定義,好比,取,'MY_ZHH_APP' #__name__是固定寫法,主要是方便flask框架去尋找資源 ,也方便flask插件出現錯誤時,去定位問題 @app.route('/') #至關於一個裝飾器,視圖映射,路由系統生成 視圖對應url,這邊沒有指定method .默認使用get def first_flask(): #視圖函數 return 'Hello World' #response,最終給瀏覽器返回的內容 if __name__ == '__main__': app.run(debug=True) #啓動這個應用服務器,並開啓debug,才能定位問題
1六、Flask 框架的優點?
1.輕巧 2.簡潔 3.擴展性強(我的認爲最重要的特色) 4.核心(werkzeug和jinja2)jinja2就是指模板引擎。 Flask確實很「輕」,不愧是Micro Framework,從Django轉向Flask的開發者必定會如此感慨,除非兩者均爲深刻使用過 Flask自由、靈活,可擴展性強,第三方庫的選擇面廣,開發時能夠結合本身最喜歡用的輪子,也能結合最流行最強大的Python庫。 入門簡單,即使沒有多少web開發經驗,也能很快作出網站 很是適用於小型網站 很是適用於開發web服務的API 開發大型網站無壓力,但代碼架構須要本身設計,開發成本取決於開發者的能力和經驗 各方面性能均等於或優於Django Django自帶的或第三方的好評如潮的功能,Flask上總會找到與之相似第三方庫 Flask靈活開發,Python高手基本都會喜歡Flask,但對Django卻可能褒貶不一 Flask與關係型數據庫的配合使用不弱於Django,而其與NoSQL數據庫的配合遠遠優於Django Flask比Django更加Pythonic,與Python的philosophy更加吻合
1七、Flask 框架依賴組件?
# 依賴jinja2模板引擎 # 依賴werkzurg協議
1八、Flask 藍圖的做用?
# blueprint把實現不一樣功能的module分開.也就是把一個大的App分割成各自實現不一樣功能的module. # 在一個blueprint中能夠調用另外一個blueprint的視圖函數, 但要加相應的blueprint名.
1九、列舉使用過的 Flask 第三方組件?
# Flask組件 flask-session session放在redis flask-SQLAlchemy 如django裏的ORM操做 flask-migrate 數據庫遷移 flask-script 自定義命令 blinker 信號-觸發信號 # 第三方組件 Wtforms 快速建立前端標籤、文本校驗 dbutile 建立數據庫鏈接池 gevnet-websocket 實現websocket # 自定義Flask組件 自定義auth認證 參考flask-login組件
20、簡述 Flask 上下文管理流程?
# a、簡單來講,falsk上下文管理能夠分爲三個階段: 一、'請求進來時':將請求相關的數據放入上下問管理中 二、'在視圖函數中':要去上下文管理中取值 三、'請求響應':要將上下文管理中的數據清除 # b、詳細點來講: 一、'請求剛進來': 將request,session封裝在RequestContext類中 app,g封裝在AppContext類中 並經過LocalStack將requestcontext和appcontext放入Local類中 二、'視圖函數中': 經過localproxy--->偏函數--->localstack--->local取值 三、'請求響應時': 先執行save.session()再各自執行pop(),將local中的數據清除
2一、Flask 中的 g 的做用?
# g是貫穿於一次請求的全局變量,當請求進來將g和current_app封裝爲一個APPContext類, # 再經過LocalStack將Appcontext放入Local中,取值時經過偏函數在LocalStack、local中取值; # 響應時將local中的g數據刪除
2二、如何編寫 flask 的離線腳本?
#新建create_tablepy from chun import db,create_app app = create_app() app_ctx = app.app_context() # app_ctx = app/g with app_ctx: # __enter__,經過LocalStack放入Local中 db.create_all() # 調用LocalStack放入Local中獲取app,再去app中獲取配置
2三、Flask 中上下文管理主要涉及到了那些相關的類?並述類主要做用
RequestContext #封裝進來的請求(賦值給ctx) AppContext #封裝app_ctx LocalStack #將local對象中的數據維護成一個棧(先進後出) Local #保存請求上下文對象和app上下文對象
2四、 爲何要Flask把Local對象中的的值stack維護成一個列表
# 由於經過維護成列表,能夠實現一個棧的數據結構,進棧出棧時只取一個數據,巧妙的簡化了問題。 # 還有,在多app應用時,能夠實現數據隔離;列表裏不會加數據,而是會生成一個新的列表 # local是一個字典,字典裏key(stack)是惟一標識,value是一個列表
2五、 Flask 中多 app 應用如何編寫?
請求進來時,能夠根據URL的不一樣,交給不一樣的APP處理。藍圖也能夠實現。 #app1 = Flask('app01') #app2 = Flask('app02') #@app1.route('/index') #@app2.route('/index2') 源碼中在DispatcherMiddleware類裏調用app2.__call__, 原理其實就是URL分割,而後將請求分發給指定的app。 以後app也按單app的流程走。就是從app.__call__走。
2六、在Flask中實現WebSocket須要什麼組件?
# gevent-websocket
2七、wtforms 組件的做用?
# WTForms是一個支持多個web框架的form組件,主要用於對用戶請求數據進行驗證。 # WTforms做用:當網站中須要用到表單時,WTForms變得頗有效。應該把表單定義爲類,做爲單獨的一個模塊。
2八、Flask 框架默認 session 處理機制?
# 前提: 不熟的話:記不太清了,應該是……分兩個階段吧 # 建立: 當請求剛進來的時候,會將request和session封裝成一個RequestContext()對象, 接下來把這個對象經過LocalStack()放入內部的一個Local()對象中; 由於剛開始 Local 的ctx中session是空的; 因此,接着執行open_session,將cookie 裏面的值拿過來,從新賦值到ctx中 (Local實現對數據隔離,相似threading.local) # 銷燬: 最後返回時執行 save_session() 將ctx 中的session讀出來進行序列化,寫到cookie 而後給用戶,接着把 ctx pop掉
2九、解釋Flask框架中的Local對象和threadinglocal對象的區別?
# a.threading.local 做用:爲每一個線程開闢一塊空間進行數據存儲(數據隔離)。 問題:本身經過字典建立一個相似於threading.local的東西。 storage = { 4740: {val: 0}, 4732: {val: 1}, 4731: {val: 3}, } # b.自定義Local對象 做用:爲每一個線程(協程)開闢一塊空間進行數據存儲(數據隔離)。 class Local(object): def __init__(self): object.__setattr__(self, 'storage', {}) def __setattr__(self, k, v): ident = get_ident() if ident in self.storage: self.storage[ident][k] = v else: self.storage[ident] = {k: v} def __getattr__(self, k): ident = get_ident() return self.storage[ident][k] obj = Local() def task(arg): obj.val = arg obj.xxx = arg print(obj.val) for i in range(10): t = Thread(target=task, args=(i,)) t.start()
30、SQLAlchemy中的session和scoped_session的區別?
# Session: 因爲沒法提供線程共享功能,開發時要給每一個線程都建立本身的session 打印sesion可知他是sqlalchemy.orm.session.Session的對象 # scoped_session: 爲每一個線程都建立一個session,實現支持線程安全 在整個程序運行的過程中,只存在惟一的一個session對象。 建立方式: 經過本地線程Threading.Local() # session=scoped_session(Session) 建立惟一標識的方法(參考flask請求源碼)
3一、SQLAlchemy 如何執行原生 SQL?
# 使用execute方法直接操做SQL語句(導入create_engin、sessionmaker) engine=create_engine('mysql://root:*****@127.0.0.1/database?charset=utf8') DB_Session = sessionmaker(bind=engine) session = DB_Session() session.execute('alter table mytablename drop column mycolumn ;')
3二、ORM 的實現原理?
# ORM的實現基於一下三點 映射類:描述數據庫表結構, 映射文件:指定數據庫表和映射類之間的關係 數據庫配置文件:指定與數據庫鏈接時須要的鏈接信息(數據庫、登陸用戶名、密碼or鏈接字符串)
3三、 DBUtils 模塊的做用?
# 數據庫鏈接池 使用模式: 一、爲每一個線程建立一個鏈接,鏈接不可控,須要控制線程數 二、建立指定數量的鏈接在鏈接池,當線程訪問的時候去取,不夠了線程排隊,直到有人釋放(推薦) --------------------------------------------------------------------------- 兩種寫法: 一、用靜態方法裝飾器,經過直接執行類的方法來鏈接使用數據庫 二、經過實例化對象,經過對象來調用方法執行語句 https://www.cnblogs.com/ArmoredTitan/p/Flask.html
3四、如下SQLAlchemy的字段是否正確?若是不正確請更正.
fromdatetime importdatetime fromsqlalchemy.ext.declarative importdeclarative_base fromsqlalchemy importColumn, Integer, String, DateTime Base =declarative_base() classUserInfo(Base): __tablename__ ='userinfo' id=Column(Integer, primary_key=True, autoincrement=True) name =Column(String(64), unique=True) ctime =Column(DateTime, default=datetime.now()) from datetime import datetime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, DateTime Base = declarative_base() class UserInfo(Base): __tablename__ = 'userinfo' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(64), unique=True) ctime = Column(DateTime, default=datetime.now()) ----------------------------------------------------------------------- 不正確: Ctime字段中參數應爲’default=datetime.now’ now 後面不該該加括號,加了的話,字段不會實時更新。
3五、SQLAchemy 中如何爲表設置引擎和字符編碼?
sqlalchemy設置編碼字符集,必定要在數據庫訪問的URL上增長'charset=utf8' 不然數據庫的鏈接就不是'utf8'的編碼格式 eng=create_engine('mysql://root:root@localhost:3306/test2?charset=utf8',echo=True) 1. 設置引擎編碼方式爲utf8。 engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/sqldb01?charset=utf8") 2. 設置數據庫表編碼方式爲utf8 class UserType(Base): __tablename__ = 'usertype' id = Column(Integer, primary_key=True) caption = Column(String(50), default='管理員') # 添加配置設置編碼 __table_args__ = { 'mysql_charset':'utf8' } 這樣生成的SQL語句就自動設置數據表編碼爲utf8了,__table_args__還可設置存儲引擎、外鍵約束等等信息。
3六、SQLAchemy 中如何設置聯合惟一索引?
經過'UniqueConstraint'字段來設置聯合惟一索引 __table_args=(UniqueConstraint('h_id','username',name='_h_username_uc')) # h_id和username組成聯合惟一約束
一、tornado 中的 gen.coroutine 的做用?
# tornado的coroutine裝飾器,使得回調函數能夠用同步的方式實現,極大提升了代碼的可讀性。它的實現涉及到了yield,ioloop和Future的模塊。
二、簡述 tornado 框架特色及應用場景。
# web聊天室,在線投票等操做!
三、tornado 框架中 Future 對象的做用?
# 實現異步非阻塞 視圖函數yield一個futrue對象,futrue對象默認: self._done = False ,請求未完成 self._result = None ,請求完成後返回值,用於傳遞給回調函數使用。 tornado就會一直去檢測futrue對象的_done是否已經變成True。 若是IO請求執行完畢,自動會調用future的set_result方法: self._result = result self._done = True
四、tornado 框架中如何編寫 webSocket 程序?
Tornado在websocket模塊中提供了一個WebSocketHandler類。 這個類提供了和已鏈接的客戶端通訊的WebSocket事件和方法的鉤子。 當一個新的WebSocket鏈接打開時,open方法被調用, 而on_message和on_close方法,分別在鏈接、接收到新的消息和客戶端關閉時被調用。 此外,WebSocketHandler類還提供了write_message方法用於向客戶端發送消息,close方法用於關閉鏈接。
五、tornado 中靜態文件是如何處理的?
如: # settings.py settings = { "static_path": os.path.join(os.path.dirname(__file__), "static"), # 指定了靜態文件的位置在當前目錄中的"static"目錄下 "cookie_secret": "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=", "login_url": "/login", "xsrf_cookies": True, } 經上面配置後 static_url()自動去配置的路徑下找'commons.css'文件
一、Mysql基礎
一、from子句組裝來自不一樣數據源的數據; 二、where子句基於指定的條件對記錄行進行篩選; 三、group by子句將數據劃分爲多個分組; 四、使用匯集函數進行計算; 五、使用having子句篩選分組; 六、計算全部的表達式; 七、select 的字段; 八、使用order by對結果集進行排序。 SQL語言不一樣於其餘編程語言的最明顯特徵是處理代碼的順序。在大多數據庫語言中,代碼按 編碼順序被處理。但在SQL語句中,第一個被處理的子句式 FROM,而不是第一齣現的SELECT。 SQL查詢處理的步驟序號: (1) FROM (2) JOIN (3) ON (4) WHERE (5) GROUP BY (6) WITH {CUBE | ROLLUP} (7) HAVING (8) SELECT (9) DISTINCT (9) ORDER BY (10) 以上每一個步驟都會產生一個虛擬表,該虛擬表被用做下一個步驟的輸入。這些虛擬表對調用 者(客戶端應用程序或者外部查詢)不可用。只有最後一步生成的表纔會會給調用者。若是沒有在 查詢中指定某一個子句,將跳過相應的步驟。 邏輯查詢處理階段簡介: 一、 FROM:對FROM子句中的前兩個表執行笛卡爾積(交叉聯接),生成虛擬表VT1。 二、 ON:對VT1應用ON篩選器,只有那些使爲真才被插入到TV2。 三、 OUTER (JOIN):若是指定了OUTER JOIN(相對於CROSS JOIN或INNER JOIN),保留表中未找到匹配的行將做爲外部行添加到 VT2,生成TV3。若是FROM子句包含兩個以上的表,則對上一個聯接生成的結果表和下一個表重複執行步驟1到步驟3,直處處理完 全部的表位置。 四、 WHERE:對TV3應用WHERE篩選器,只有使爲true的行才插入TV4。 五、 GROUP BY:按GROUP BY子句中的列列表對TV4中的行進行分組,生成TV5。 六、 CUTE|ROLLUP:把超組插入VT5,生成VT6。 七、 HAVING:對VT6應用HAVING篩選器,只有使爲true的組插入到VT7。 八、 SELECT:處理SELECT列表,產生VT8。 九、 DISTINCT:將重複的行從VT8中刪除,產品VT9。 十、 ORDER BY:將 VT9中的行按ORDER BY子句中的列列表順序,生成一個遊標(VC10)。 十一、 TOP:從 VC10的開始處選擇指定數量或比例的行,生成表TV11,並返回給調用者。 where子句中的條件書寫順序
二、什麼是事務,MySQL是如何支持事務的?
事務就是一段sql語句的批處理,可是這個批處理是一個原子,不可分割,要麼都執行,要麼回滾(rollback)都不執行。 事務具體四大特性,也就是常常說的ACID : 1.原子性(全部操做要麼所有成功,要麼所有失敗回滾) 2.一致性(事務執行以前和執行以後都必須處於一致性狀態。) 3.隔離性(數據庫爲每個用戶開啓的事務,不能被其餘事務的操做所幹擾,多個併發事務之間要相互隔離) 4.持久性(一個事務一旦被提交了,那麼對數據庫中的數據的改變就是永久性的, 即便遭遇故障依然可以經過日誌恢復最後一次更新在 MySQL 中只有使用了 Innodb 數據庫引擎的數據庫或表才支持事務 MYSQL 事務處理主要有兩種方法: 一、用 BEGIN, ROLLBACK, COMMIT來實現 BEGIN 開始一個事務 ROLLBACK 事務回滾 COMMIT 事務確認 二、直接用 SET 來改變 MySQL 的自動提交模式: SET AUTOCOMMIT=0 禁止自動提交 SET AUTOCOMMIT=1 開啓自動提交
三、說一下Mysql數據庫存儲的原理?
儲存過程是一個可編程的函數,它在數據庫中建立並保存。它能夠有SQL語句和一些特殊的控制結構組成。當但願在不一樣的應用程序或平臺上執行相同的函數,或者封裝特定功能時,存儲過程是很是有 用的。數據庫中的存儲過程能夠看作是對編程中面向對象方法的模擬。它容許控制數據的訪問方式。 存儲過程一般有如下優勢: 一、存儲過程能實現較快的執行速度 二、存儲過程容許標準組件是編程。 三、存儲過程能夠用流程控制語句編寫,有很強的靈活性,能夠完成複雜的判斷和較複雜的運算。 四、存儲過程可被做爲一種安全機制來充分利用。 五、存儲過程可以減小網絡流量
四、數據庫索引種類?
索引是一種特殊的文件(InnoDB數據表上的索引是表空間的一個組成部分),更通俗的說,數據庫索引比如是一本書前面的目錄,能加 快數據庫的查詢速度 MySQL索引的類型: 1. 普通索引:這是最基本的索引,它沒有任何限制 2.惟一索引:索引列的值必須惟一,但容許有空值,若是是組合索引,則列值的組合必須惟一 3.全文索引:全文索引僅可用於 MyISAM 表,能夠從CHAR、VARCHAR或TEXT列中做爲CREATE TABLE語句的一部分被 建立,或是隨後使用ALTER TABLE 或CREATE INDEX被添加(切記對於大容量的數據表,生成全文索引是一個很是消耗時間非 常消耗硬盤空間的作法) 2. 單列索引、多列索引:多個單列索引與單個多列索引的查詢效果不一樣,由於執行查詢時,MySQL只能使用一個索引,會從多個 索引中選擇一個限制最爲嚴格的索引。 5.組合索引(最左前綴):簡單的理解就是隻從最左面的開始組合(實在單列索引的基礎上進一步壓榨索引效率的一種方式)
五、索引在什麼狀況下遵循最左前綴的規則?
mysql在使用組合索引查詢的時候須要遵循「最左前綴」規則
六、MySQL常見的函數?
聚合函數: AVG(col)返回指定列的平均值 COUNT(col)返回指定列中非NULL值的個數 MIN(col)返回指定列的最小值 MAX(col)返回指定列的最大值 SUM(col)返回指定列的全部值之和 GROUP_CONCAT(col) 返回由屬於一組的列值鏈接組合而成的結果 數學函數: ABS(x) 返回x的絕對值 BIN(x) 返回x的二進制(OCT返回八進制,HEX返回十六進制)
七、如何開啓慢日誌查詢?
1 執行 SHOW VARIABLES LIKE 「%slow%」,獲知 mysql 是否開啓慢查詢 slow_query_log 慢查詢開啓狀態 OFF 未開啓 ON 爲開啓 slow_query_log_file 慢查詢日誌存放的位置(這個目錄須要MySQL的運行賬號的可寫權限,通常設置爲MySQL的數據存放目錄) 2 修改配置文件( 放在[mysqld]下),重啓 long_query_time 查詢超過多少秒才記錄 3 測試是否成功 4 慢查詢日誌文件的信息格式
八、數據庫導入導出命令(結構+數據)?
1.導出整個數據庫 mysqldump -u用戶名 -p密碼 數據庫名 > 導出的文件名 例如:C:\Users\jack> mysqldump -uroot -pmysql sva_rec > e:\sva_rec.sql 2.導出一個表,包括表結構和數據 mysqldump -u用戶名 -p 密碼 數據庫名 表名> 導出的文件名 例如:C:\Users\jack> mysqldump -uroot -pmysql sva_rec date_rec_drv> e:\date_rec_drv.sql 3.導出一個數據庫結構 例如:C:\Users\jack> mysqldump -uroot -pmysql -d sva_rec > e:\sva_rec.sql 4.導出一個表,只有表結構 mysqldump -u用戶名 -p 密碼 -d數據庫名 表名> 導出的文件名 例如:C:\Users\jack> mysqldump -uroot -pmysql -d sva_rec date_rec_drv> e:\date_rec_drv.sql 5.導入數據庫 經常使用source 命令 進入mysql數據庫控制檯, 如mysql -u root -p mysql>use 數據庫 而後使用source命令,後面參數爲腳本文件(如這裏用到的.sql) mysql>source d:wcnc_db.sql
九、數據庫怎麼優化查詢效率?
一、儲存引擎選擇:若是數據表須要事務處理,應該考慮使用InnoDB,由於它徹底符合ACID特性。 若是不須要事務處理,使用默認存儲引擎MyISAM是比較明智的 二、分表分庫,主從。 三、對查詢進行優化,要儘可能避免全表掃描,首先應考慮在 where 及 order by 涉及的列上創建索引 四、應儘可能避免在 where 子句中對字段進行 null 值判斷,不然將致使引擎放棄使用索引而進行全表掃描 五、應儘可能避免在 where 子句中使用 != 或 <> 操做符,不然將引擎放棄使用索引而進行全表掃描 六、應儘可能避免在 where 子句中使用 or 來鏈接條件,若是一個字段有索引,一個字段沒有索引,將致使引擎放棄使用索引而進行全表掃描 七、Update 語句,若是隻更改一、2個字段,不要Update所有字段,不然頻繁調用會引發明顯的性能消耗,同時帶來大量日誌 八、對於多張大數據量(這裏幾百條就算大了)的表JOIN,要先分頁再JOIN,不然邏輯讀會很高,性能不好。
十、Mysql集羣的優缺點?
優勢: 99.999%的高可用性 快速的自動失效切換 靈活的分佈式體系結構,沒有單點故障 高吞吐量和低延遲 可擴展性強,支持在線擴容 缺點: 存在不少限制,好比:不支持外鍵 部署、管理、配置很複雜 佔用磁盤空間大、內存大 備份和恢復不方便 重啓的時候,數據節點將數據load到內存須要很長的時間
十一、你用的Mysql是哪一個引擎,各引擎之間有什麼區別?
主要 MyISAM 與 InnoDB 兩個引擎,其主要區別以下: InnoDB 支持事務,MyISAM 不支持,這一點是很是之重要。事務是一種高級的處理方式,如在一些列增刪改中只要哪一個出錯還能夠回滾還原,而 MyISAM就不能夠了; MyISAM 適合查詢以及插入爲主的應用, InnoDB 適合頻繁修改以及涉及到安全性較高的應用; InnoDB 支持外鍵,MyISAM 不支持; MyISAM 是默認引擎,InnoDB 須要指定; InnoDB 不支持 FULLTEXT 類型的索引; InnoDB 中不保存表的行數,如 select count() from table 時,InnoDB;須要掃描一遍整個表來計算有多少行,可是 MyISAM 只要簡單的讀出保存好的行數便可。注意的是,當 count()語句包含 where 條件時 MyISAM 也須要掃描整個表; 對於自增加的字段,InnoDB 中必須包含只有該字段的索引,可是在 MyISAM表中能夠和其餘字段一塊兒創建聯合索引;清空整個表時,InnoDB 是一行一行的刪除,效率很是慢。MyISAM 則會重建表; InnoDB 支持行鎖(某些狀況下仍是鎖整表,如 update table set a=1 where user like '%lee%'
十二、數據庫的優化?
1.優化索引、SQL 語句、分析慢查詢; 2.設計表的時候嚴格根據數據庫的設計範式來設計數據庫; 3.使用緩存,把常常訪問到的數據並且不須要常常變化的數據放在緩存中,能節約磁盤IO 4.優化硬件;採用SSD,使用磁盤隊列技術(RAID0,RAID1,RDID5)等 5.採用MySQL 內部自帶的表分區技術,把數據分層不一樣的文件,可以提升磁盤的讀取效率; 6.垂直分表;把一些不常常讀的數據放在一張表裏,節約磁盤I/O; 7.主從分離讀寫;採用主從複製把數據庫的讀操做和寫入操做分離開來; 8.分庫分表分機器(數據量特別大),主要的的原理就是數據路由; 9.選擇合適的表引擎,參數上的優化 10.進行架構級別的緩存,靜態化和分佈式; 11.不採用全文索引; 12.採用更快的存儲方式,例如 NoSQL存儲常常訪問的數據**。
1三、Mysql數據庫如何分區、分表?
分表能夠經過三種方式:Mysql集羣、自定義規則和merge存儲引擎。 分區有四類: RANGE 分區:基於屬於一個給定連續區間的列值,把多行分配給分區。 LIST 分區:相似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個 值來進行選擇。 HASH分區:基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的 這些行的列值進行計算。這個函數能夠包含MySQL 中有效的、產生非負整數值的任何表達式。 KEY 分區:相似於按HASH分區,區別在於KEY分區只支持計算一列或多列,且MySQL 服務器 提供其自身的哈希函數。必須有一列或多列包含整數值
1四、Sql注入是如何產生的,如何防止?
程序開發過程當中不注意規範書寫sql語句和對特殊字符進行過濾,致使客戶端能夠經過全局變量 POST和GET提交一些sql語句正常執行。產生Sql注入。下面是防止辦法: a. 過濾掉一些常見的數據庫操做關鍵字,或者經過系統函數來進行過濾。 b. 在PHP配置文件中將Register_globals=off;設置爲關閉狀態 c. SQL語句書寫的時候儘可能不要省略小引號(tab鍵上面那個)和單引號 e. 對於經常使用的方法加以封裝,避免直接暴漏SQL語句 f. 開啓PHP安全模式:Safe_mode=on; g. 打開magic_quotes_gpc來防止SQL注入 h. 控制錯誤信息:關閉錯誤提示信息,將錯誤信息寫到系統日誌。 i. 使用mysqli或pdo預處理
1五、 NoSQL和關係數據庫的區別?
a. SQL數據存在特定結構的表中;而NoSQL則更加靈活和可擴展,存儲方式能夠省是JSON文檔、哈希表或者其餘方式。 b. 在SQL中,必須定義好表和字段結構後才能添加數據,例如定義表的主鍵(primary key),索引(index),觸發器(trigger),存儲過程 (stored procedure)等。表結構能夠在被定義以後更新,可是若是有比較大的結構變動的話就會變得比較複雜。在NoSQL中,數據可 以在任什麼時候候任何地方添加,不須要先定義表。 c. SQL中若是須要增長外部關聯數據的話,規範化作法是在原表中增長一個外鍵,關聯外部數據表。而在NoSQL中除了這種規範化的 外部數據表作法之外,咱們還能用以下的非規範化方式把外部數據直 接放到原數據集中,以提升查詢效率。缺點也比較明顯,更新審覈人數據的時候將會比較麻煩。 d. SQL 中能夠使用JOIN表連接方式將多個關係數據表中的數據用一條簡單的查詢語句查詢出來。NoSQL暫未提供相似JOIN的查詢方 式對多個數據集中的數據作查詢。因此大部分NoSQL使用非規範化的數據存儲方式存儲數據。 e. SQL中不容許刪除已經被使用的外部數據,而NoSQL中則沒有這種強耦合的概念,能夠隨時刪除任何數據。 f. SQL中若是多張表數據須要同批次被更新,即若是其中一張表更新失敗的話其餘表也不能更新成功。這種場景能夠經過事務來控 制,能夠在全部命令完成後再統一提交事務。而NoSQL中沒有事務這個概念,每個數據集的操做都是原子級的。 g. 在相同水平的系統設計的前提下,由於NoSQL中省略了JOIN查詢的消耗,故理論上性能上是優於SQL的。
1六、簡述觸發器、函數、視圖、存儲過程?
觸發器:觸發器是一個特殊的存儲過程,它是MySQL在insert、update、delete的時候自動執行的代碼塊。 create trigger trigger_name after/before insert /update/delete on 表名 for each row begin sql語句:(觸發的語句一句或多句) end 函數:MySQL中提供了許多內置函數,還能夠自定義函數(實現程序員須要sql邏輯處理) 自定義函數建立語法: 建立:CREATE FUNCTION 函數名稱(參數列表) RETURNS 返回值類型 函數體 修改:ALTER FUNCTION 函數名稱 [characteristic ...] 刪除:DROP FUNCTION [IF EXISTS] 函數名稱 調用:SELECT 函數名稱(參數列表) 視圖:視圖是由查詢結果造成的一張虛擬表,是表經過某種運算獲得的一個投影 create view view_name as select 語句 存儲過程:把一段代碼封裝起來,當要執行這一段代碼的時候, 能夠經過調用該存儲過程來實現(通過第一次編譯後再次調用不須要再次編譯,比一個個執行sql語句效率高) create procedure 存儲過程名(參數,參數,…) begin //代碼 end
1七、 列舉 建立索引可是沒法命中索引的8種狀況。
一、若是條件中有or,即便其中有條件帶索引也不會使用(這也是爲何儘可能少用or的緣由) 二、對於多列索引,不是使用的第一部分(第一個),則不會使用索引 三、like查詢是以%開頭 四、若是列類型是字符串,那必定要在條件中將數據使用引號引用起來,不然不使用索引 五、若是mysql估計使用全表掃描要比使用索引快,則不使用索引 六、對小表查詢 七、提示不使用索引 八、統計數據不真實 九、單獨引用複合索引裏非第一位置的索引列.
1八、優化數據庫?提升數據庫的性能
1. 對語句的優化 ①用程序中,保證在實現功能的基礎上,儘可能減小對數據庫的訪問次數; 經過搜索參數,儘可能減小對錶的訪問行數,最小化結果集,從而減輕網絡負擔; ②可以分開的操做盡可能分開處理,提升每次的響應速度;在數據窗口使用SQL時,儘可能把使用的索引放在選擇的首列;算法的 結構儘可能簡單; ③在查詢時,不要過多地使用通配符如 SELECT * FROM T1 語句,要用到幾列就選擇幾列如: SELECT COL1,COL2 FROM T1; ④在可能的狀況下儘可能限制儘可能結果集行數如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,由於某些狀況下用戶是不須要那麼多的數據的。 ⑤不要在應用中使用數據庫遊標,遊標是很是有用的工具,但比使用常規的、面向集的SQL語句須要更大的開銷;按照特定順序提取數據的查找。 2. 避免使用不兼容的數據類型 例如float和int、char和varchar、binary 和varbinary是不兼容的。 數據類型的不兼容可能使優化器沒法執行一些原本能夠進行的優化操做。 例如: SELECT name FROM employee WHERE salary > 60000 在這條語句中,如salary字段是money型的,則優化器很難對其進行優化,由於60000 是個整型數。咱們應當在編程時將整型轉化成 爲錢幣型,而不要等到運行時轉化。 若在查詢時強制轉換,查詢速度會明顯減慢。 3. 避免在WHERE子句中對字段進行函數或表達式操做。 若進行函數或表達式操做,將致使引擎放棄使用索引而進行全表掃描。 4. 避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等這樣的操做符 5. 儘可能使用數字型字段 6. 合理使用EXISTS,NOT EXISTS子句。 7. 儘可能避免在索引過的字符數據中,使用非打頭字母搜索。 8. 分利用鏈接條件 9. 消除對大型錶行數據的順序存取 10. 避免困難的正規表達式 11. 使用視圖加速查詢 12. 可以用BETWEEN的就不要用IN 13. DISTINCT的就不用GROUP BY 14. 部分利用索引 15. 能用UNION ALL就不要用UNION 16. 不要寫一些不作任何事的查詢 17. 儘可能不要用SELECT INTO語句 18. 必要時強制查詢優化器使用某個索引 19. 雖然UPDATE、DELETE語句的寫法基本固定,可是仍是對UPDATE語句給點建議: a) 儘可能不要修改主鍵字段。 b) 當修改 VARCHAR型字段時,儘可能使用相同長度內容的值代替。 c) 儘可能最小化對於含有UPDATE觸發器的表的UPDATE操做。 d) 避免 UPDATE將要複製到其餘數據庫的列。 e) 避免UPDATE建有不少索引的列。 f) 避免UPDATE在WHERE子句條件中的列。
1九、數據庫負載均衡
負載均衡集羣是由一組相互獨立的計算機系統構成,經過常規網絡或專用網絡進行鏈接,由路由器銜接在一塊兒,各節點相互協做、共同負載、均衡壓力,對客戶端來講,整個羣集能夠視爲一臺具備超高性能的獨立服務器。 一、 實現原理 實現數據庫的負載均衡技術,首先要有一個能夠控制鏈接數據庫的控制端。在這裏,它截斷了數據庫和程序的直接鏈接,由全部的程序來訪問這個中間層,而後再由中間層來訪問數據庫。這樣,咱們就能夠具體控制訪問某個數據庫了,而後還能夠根據數據庫的當前負載採起有效的均衡策略,來調整每次鏈接到哪一個數據庫。 二、 實現多據庫數據同步 對於負載均衡,最重要的就是全部服務器的數據都是實時同步的。這是一個集羣所必需的,由於,若是數不據實時、不一樣步,那麼用戶從一臺服務器讀出的數據,就有別於從另外一臺服務器讀出的數據,這是不能容許的。因此必須實現數據庫的數據同步。這樣,在查詢的時候就能夠有多個資源,實現均衡。比較經常使用的方法是Moebius for SQL Server集羣,Moebius for SQL Server集羣採用將核心程序駐留在每一個機器的數據庫中的辦法,這個核心程序稱爲Moebius for SQL Server 中間件,主要做用是監測數據庫內數據的變化並將變化的數據同步到其餘數據庫中。數據同步完成後客戶端纔會獲得響應,同步過程是併發完成的,因此同步到多個數據庫和同步到一個數據庫的時間基本相等;另外同步的過程是在事務的環境下完成的,保證了多份數據在任什麼時候刻數據的一致性。正由於Moebius中間件宿主在數據庫中的創新,讓中間件不但能知道數據的變化,並且知道引發數據變化的SQL語句,根據SQL語句的類型智能的採起不一樣的數據同步的策略以保證數據同步成本的最小化。 數據條數不多,數據內容也不大,則直接同步數據。數據條數不多,可是裏面包含大數據類型,好比文本,二進制數據等,則先對數據進行壓縮而後再同步,從而減小網絡帶寬的佔用和傳輸所用的時間。 數據條數不少,此時中間件會拿到形成數據變化的SQL語句, 而後對SQL語句進行解析,分析其執行計劃和執行成本,並選擇是同步數據仍是同步SQL語句到其餘的數據庫中。此種狀況應用在對錶結構進行調整或者批量更改數據的時候很是有用。 三、 優缺點 優勢: 1) 擴展性強:當系統要更高數據庫處理速度時,只要簡單地增長數據庫服務器就 能夠獲得擴展。 2) 可維護性:當某節點發生故障時,系統會自動檢測故障並轉移故障節點的應用,保證數據庫的持續工做。 3) 安全性:由於數據會同步的多臺服務器上,能夠實現數據集的冗餘,經過多份數據來保證安全性。另外它成功地將數據庫放到了 內網之中,更好地保護了數據庫的安全性。 4) 易用性:對應用來講徹底透明,集羣暴露出來的就是一個IP 缺點: a) 不可以按照Web服務器的處理能力分配負載。 b) 負載均衡器(控制端)故障,會致使整個數據庫系統癱瘓。
20、數據庫三大範式?
什麼是範式: 簡言之就是,數據庫設計對數據的存儲性能,還有開發人員對數據的操做都有莫大的關係。因此創建科學的,規範的的數據庫是須要知足一些 規範的來優化數據數據存儲方式。在關係型數據庫中這些規範就能夠稱爲範式。 什麼是三大範式: 第一範式:當關系模式R的全部屬性都不能在分解爲更基本的數據單位時,稱R是知足第一範式的,簡記爲1NF。知足第一範式是關係模式規範化的最低要求,不然,將有不少基本操做在這樣的關係模式中實現不了。 第二範式:若是關係模式R知足第一範式,而且R得全部非主屬性都徹底依賴於R的每個候選關鍵屬性,稱R知足第二範式,簡記爲2NF。 第三範式:設R是一個知足第一範式條件的關係模式,X是R的任意屬性集,若是X非傳遞依賴於R的任意一個候選關鍵字,稱R知足第三範式,簡記爲3NF. 注:關係實質上是一張二維表,其中每一行是一個元組,每一列是一個屬性
2一、簡述數據庫設計中一對多和多對多的應用場景?
一對多:學生與班級---一個學生只能屬於一個班級,一個班級能夠有多個學生 多對多:學生與課程---一個學生能夠選擇多個課程,一個課程也能夠被多個學生選擇
2二、 如何基於數據庫實現商城商品計數器?
建立一個商城表---包含(id,商品名,每個商品對應數量) create table product (id primary key auto_increment, pname varchar(64), pcount int);
2三、char和varchar的區別?
char: 定長,char的存取數度相對快 varchar: 不定長,存取速度相對慢 到底如何取捨能夠根據一下幾個方面考慮: 一、對於MyISAM表,儘可能使用Char,對於那些常常須要修改而容易造成碎片的myisam和isam數據表就更是如此,它的缺點就是佔用 磁盤空間; 二、對於InnoDB表,由於它的數據行內部存儲格式對固定長度的數據行和可變長度的數據行不加區分(全部數據行共用一個表頭部 分,這個標頭部分存放着指向各有關數據列的指針),因此使用char類型不見得會比使用varchar類型好。事實上,由於char類型通 常要比varchar類型佔用更多的空間,因此從減小空間佔用量和減小磁盤i/o的角度,使用varchar類型反而更有利; 三、存儲很短的信息,好比門牌號碼101,201……這樣很短的信息應該用char,由於varchar還要佔個byte用於存儲信息長度,原本打算 節約存儲的如今得不償失。 四、固定長度的。好比使用uuid做爲主鍵,那用char應該更合適。由於他固定長度,varchar動態根據長度的特性就消失了,並且還要 佔個長度信息。 五、十分頻繁改變的column。由於varchar每次存儲都要有額外的計算,獲得長度等工做,若是一個很是頻繁改變的,那就要有不少 的精力用於計算,而這些對於char來講是不須要的
2四、在對name作了惟一索引前提下,簡述如下區別:
select * from tb where name = ‘Oldboy’ -------------查找到tb表中全部name = ‘Oldboy’的數據 select * from tb where name = ‘Oldboy’ limit 1------查找到tb表中全部name = ‘Oldboy’的數據只取其中的第一條
2五、MySQL 常見數據庫引擎及區別?
''' MySQL數據庫引擎取決於MySQL在安裝的時候是如何被編譯的。要添加一個新的引擎,就必須從新編譯MYSQL。在缺省狀況下,MYSQL支持三個引擎:ISAM、MYISAM和HEAP。另外兩種類型INNODB和BERKLEY(BDB),也經常能夠使用。若是技術高超,還能夠使用MySQL+API本身作一個引擎。下面介紹幾種數據庫引擎: ISAM:ISAM是一個定義明確且歷經時間考驗的數據表格管理方法,它在設計之時就考慮到 數據庫被查詢的次數要遠大於更新的次數。所以,ISAM執行讀取操做的速度很快,並且不佔用大量的內存和存儲資源。ISAM的兩個主要不足之處在於,它不 支持事務處理,也不可以容錯:若是你的硬盤崩潰了,那麼數據文件就沒法恢復了。若是你正在把ISAM用在關鍵任務應用程序裏,那就必須常常備份你全部的實 時數據,經過其複製特性,MYSQL可以支持這樣的備份應用程序。 MyISAM:MyISAM是MySQL的ISAM擴展格式和缺省的數據庫引擎。除了提供ISAM裏所沒有的索引和字段管理的大量功能,MyISAM還使用一種表格鎖定的機制,來優化多個併發的讀寫操做,其代價是你須要常常運行OPTIMIZE TABLE命令,來恢復被更新機制所浪費的空間。MyISAM還有一些有用的擴展,例如用來修復數據庫文件的MyISAMCHK工具和用來恢復浪費空間的 MyISAMPACK工具。MYISAM強調了快速讀取操做,這可能就是爲何MySQL受到了WEB開發如此青睞的主要緣由:在WEB開發中你所進行的大量數據操做都是讀取操做。因此,大多數虛擬主機提供商和INTERNET平臺提供商只容許使用MYISAM格式。MyISAM格式的一個重要缺陷就是不能在表損壞後恢復數據。 HEAP:HEAP容許只駐留在內存裏的臨時表格。駐留在內存裏讓HEAP要比ISAM和MYISAM都快,可是它所管理的數據是不穩定的,並且若是在關機以前沒有進行保存,那麼全部的數據都會丟失。在數據行被刪除的時候,HEAP也不會浪費大量的空間。HEAP表格在你須要使用SELECT表達式來選擇和操控數據的時候很是有用。要記住,在用完表格以後就刪除表格。 InnoDB:InnoDB數據庫引擎都是造就MySQL靈活性的技術的直接產品,這項技術就是MYSQL+API。在使用MYSQL的時候,你所面對的每個挑戰幾乎都源於ISAM和MyISAM數據庫引擎不支持事務處理(transaction process)也不支持外來鍵。儘管要比ISAM和 MyISAM引擎慢不少,可是InnoDB包括了對事務處理和外來鍵的支持,這兩點都是前兩個引擎所沒有的。如前所述,若是你的設計須要這些特性中的一者 或者二者,那你就要被迫使用後兩個引擎中的一個了。 若是感受本身的確技術高超,你還可以使用MySQL+API來建立本身的數據庫引擎。這個API爲你提供了操做字段、記錄、表格、數據庫、鏈接、安全賬號的功能,以及創建諸如MySQL這樣DBMS所須要的全部其餘無數功能。深刻講解API已經超出了本文的範圍,可是你須要瞭解MySQL+API的存在及其可交換引擎背後的技術,這一點是很重要的。估計這個插件式數據庫引擎的模型甚至可以被用來爲MySQL建立本地的XML提供器(XML provider)。(任何讀到本文的MySQL+API開發人員能夠把這一點看成是個要求。) MyISAM與InnoDB的區別 InnoDB和MyISAM是許多人在使用MySQL時最經常使用的兩個表類型,這兩個表類型各有優劣,視具體應用而定。基本的差異爲:MyISAM類型不支持事務處理等高級處理,而InnoDB類型支持。MyISAM類型的表強調的是性能,其執行數度比InnoDB類型更快,可是不提供事務支持,而InnoDB提供事務支持已經外部鍵等高級數據庫功能。 '''
2六、簡述事務及其特性?
事務具備四個特性,即 ACID 特性: ( 1 )原子性:事務中包括的全部操做要麼都作,要麼都不作。 ( 2 )一致性:事務必須使數據庫從一個一致性狀態變到另外一個一致性狀態。 ( 3 )隔離性:一個事務內部的操做及使用的數據對併發的其餘事務是隔離的。 ( 4 )持續性:事務一旦提交,對數據庫的改變是永久的。
2七、簡述觸發器、函數、視圖、存儲過程?
觸發器:觸發器是一個特殊的存儲過程,它是MySQL在insert、update、delete的時候自動執行的代碼塊。 函數:MySQL中提供了許多內置函數,還能夠自定義函數(實現程序員須要sql邏輯處理) 自定義函數建立語法: 建立:CREATE FUNCTION 函數名稱(參數列表) RETURNS 返回值類型 函數體 修改: ALTER FUNCTION 函數名稱 [characteristic ...] 刪除:DROP FUNCTION [IF EXISTS] 函數名稱 調用:SELECT 函數名稱(參數列表) 視圖:視圖是由查詢結果造成的一張虛擬表,是表經過某種運算獲得的一個投影 create view view_name as select 語句 存儲過程:把一段代碼封裝起來,當要執行這一段代碼的時候,能夠經過調用該存儲過程來實現(通過第一次編譯後再次調用不須要再次編譯,比一個個執行sql語句效率高) create procedure 存儲過程名(參數,參數,…) begin //代碼 end
2八、簡述MySQL的執行計劃的做用及使用方法?
做爲程序員,不免要和數據庫打交道,通常狀況下,咱們不是DBA ,可是又要寫不少SQL,所以SQL效率就成了很大的問題。關於SQL效率優化,除了要掌握必定優化技巧外, 還得有不少經驗的積累,可是這裏咱們能夠經過執行計劃對SQL進行分析,能快速找到優化的地方,這是一種很不錯的方式 1.查看mysql執行計劃 explain select ...... 2.執行計劃包含的信息 Column Meaning id The SELECT identifier select_type The SELECT type table The table for the output row partitions The matching partitions type The join type possible_keys The possible indexes to choose key The index actually chosen key_len The length of the chosen key ref The columns compared to the index rows Estimate of rows to be examined filtered Percentage of rows filtered by table condition Extra Additional information (1).id 含義,指示select字句或操做表的順序。 (2).select_type 含義:select語句的類型 (3).type 含義:獲取記錄行採用的方式,亦即mysql的訪問方式。 (4).possible_keys 含義:指出MySQL能使用哪一個索引在表中找到行,查詢涉及到的字段上若存在索引,則該索引將被列出,但不必定被查詢使用 (5).key 含義:顯示MySQL在查詢中實際使用的索引,若沒有使用索引,顯示爲NULL (6)key_len 含義:表示索引中使用的字節數,可經過該列計算查詢中使用的索引的長度 (7)ref 含義:用於鏈接查詢,表示具體某個表的某列被引用 (8)rows 含義:MySQL根據表統計信息及索引選用狀況,估算的找到所需的記錄所須要讀取的行數,這個值是不許確的,只有參考意義。 (9)Extra 含義:顯示一些輔助的額外信息
2九、1000w 條數據,使用 limit offset 分頁時,爲何越日後翻越慢?如何解決?
當一個數據庫表過於龐大,LIMIT offset, length中的offset值過大,則SQL查詢語句會很是緩慢,你需增長order by,而且order by字段須要創建索引。 若是使用子查詢去優化LIMIT的話,則子查詢必須是連續的,某種意義來說,子查詢不該該有where條件,where會過濾數據,使數據失去連續性。 若是你查詢的記錄比較大,而且數據傳輸量比較大,好比包含了text類型的field,則能夠經過創建子查詢。
30、什麼是索引合併?
The Index Merge method is used to retrieve rows with several range scans and to merge their results into one. The merge can produce unions, intersections, or unions-of-intersections of its underlying scans. This access method merges index scans from a single table; it does not merge scans across multiple tables. 根據官方文檔中的說明,咱們能夠了解到: 一、索引合併是把幾個索引的範圍掃描合併成一個索引。 二、索引合併的時候,會對索引進行並集,交集或者先交集再並集操做,以便合併成一個索引。 三、這些須要合併的索引只能是一個表的。不能對多表進行索引合併。
3一、什麼是覆蓋索引?
若是一個索引包含(或覆蓋)全部須要查詢的字段的值,稱爲‘覆蓋索引’。即只需掃描索引而無須回表。 只掃描索引而無需回表的優勢: 1.索引條目一般遠小於數據行大小,只須要讀取索引,則mysql會極大地減小數據訪問量。 2.由於索引是按照列值順序存儲的,因此對於IO密集的範圍查找會比隨機從磁盤讀取每一行數據的IO少不少。 3.一些存儲引擎如myisam在內存中只緩存索引,數據則依賴於操做系統來緩存,所以要訪問數據須要一次系統調用 4.innodb的聚簇索引,覆蓋索引對innodb表特別有用。(innodb的二級索引在葉子節點中保存了行的主鍵值,因此若是二級主鍵可以覆蓋查詢,則能夠避免對主鍵索引的二次查詢) 覆蓋索引必需要存儲索引列的值,而哈希索引、空間索引和全文索引不存儲索引列的值,因此mysql只能用B-tree索引作覆蓋索引。 當發起一個索引覆蓋查詢時,在explain的extra列能夠看到using index的信息
3二、簡述數據庫讀寫分離?
MySQL Proxy最強大的一項功能是實現「讀寫分離(Read/Write Splitting)」。基本的原理是讓主數據庫處理事務性查詢,而從數據庫處理SELECT查詢。數據庫複製被用來把事務性查詢致使的變動同步到集羣中的從數據庫。 固然,主服務器也能夠提供查詢服務。使用讀寫分離最大的做用無非是環境服務器壓力。 讀寫分離的好處 一、增長冗餘 二、增長了機器的處理能力 三、對於讀操做爲主的應用,使用讀寫分離是最好的場景,由於能夠確保寫的服務器壓力更小,而讀又能夠接受點時間上的延遲。 讀寫分離提升性能之緣由 一、物理服務器增長,負荷增長 二、主從只負責各自的寫和讀,極大程度的緩解X鎖和S鎖爭用 三、從庫可配置myisam引擎,提高查詢性能以及節約系統開銷 四、從庫同步主庫的數據和主庫直接寫仍是有區別的,經過主庫發送來的binlog恢復數據,可是,最重要區別在於主庫向從庫發送binlog是異步的,從庫恢復數據也是異步的 五、讀寫分離適用與讀遠大於寫的場景,若是隻有一臺服務器,當select不少時,update和delete會被這些select訪問中的數據堵塞,等待select結束,併發性能不高。 對於寫和讀比例相近的應用,應該部署雙主相互複製 六、能夠在從庫啓動是增長一些參數來提升其讀的性能,例如--skip-innodb、--skip-bdb、--low-priority-updates以及--delay-key-write=ALL。固然這些設置也是須要根據具體業務需求來定得,不必定能用上 七、分攤讀取。假如咱們有1主3從,不考慮上述1中提到的從庫單方面設置,假設如今1分鐘內有10條寫入,150條讀取。那麼,1主3從至關於共計40條寫入,而讀取總數沒變,所以平均下來每臺服務器承擔了10條寫入和50條讀取(主庫不承擔讀取操做)。所以,雖然寫入沒變,可是讀取大大分攤了,提升了系統性能。另外,當讀取被分攤後,又間接提升了寫入的性能。因此,整體性能提升了,說白了就是拿機器和帶寬換性能。MySQL官方文檔中有相關演算公式:官方文檔 見6.9FAQ之「MySQL複製可以什麼時候和多大程度提升系統性能」 八、MySQL複製另一大功能是增長冗餘,提升可用性,當一臺數據庫服務器宕機後能經過調整另一臺從庫來以最快的速度恢復服務,所以不能光看性能,也就是說1主1從也是能夠的。
3三、簡述數據庫分庫分表?(水平、垂直)
# 水平分庫 一、概念:以字段爲依據,按照必定策略(hash、range等),將一個庫中的數據拆分到多個庫中。 二、結果: 每一個庫的結構都同樣; 每一個庫的數據都不同,沒有交集; 全部庫的並集是全量數據; 三、場景:系統絕對併發量上來了,分表難以根本上解決問題,而且尚未明顯的業務歸屬來垂直分庫。 四、分析:庫多了,io和cpu的壓力天然能夠成倍緩解。 # 水平分表 一、概念:以字段爲依據,按照必定策略(hash、range等),將一個表中的數據拆分到多個表中。 二、結果: 每一個表的結構都同樣; 每一個表的數據都不同,沒有交集; 全部表的並集是全量數據; 三、場景:系統絕對併發量並無上來,只是單表的數據量太多,影響了SQL效率,加劇了CPU負擔,以致於成爲瓶頸。 四、分析:表的數據量少了,單次SQL執行效率高,天然減輕了CPU的負擔。 # 垂直分庫 一、概念:以表爲依據,按照業務歸屬不一樣,將不一樣的表拆分到不一樣的庫中。 二、結果: 每一個庫的結構都不同; 每一個庫的數據也不同,沒有交集; 全部庫的並集是全量數據; 三、場景:系統絕對併發量上來了,而且能夠抽象出單獨的業務模塊。 四、分析:到這一步,基本上就能夠服務化了。例如,隨着業務的發展一些公用的配置表、字典表等愈來愈多,這時能夠將這些表拆到單獨的庫中,甚至能夠服務化。再有,隨着業務的發展孵化出了一套業務模式,這時能夠將相關的表拆到單獨的庫中,甚至能夠服務化。 # 垂直分表 一、概念:以字段爲依據,按照字段的活躍性,將表中字段拆到不一樣的表(主表和擴展表)中。 二、結果: 2.一、每一個表的結構都不同; 2.二、每一個表的數據也不同,通常來講,每一個表的字段至少有一列交集,通常是主鍵,用於關聯數據; 2.三、全部表的並集是全量數據; 三、場景:系統絕對併發量並無上來,表的記錄並很少,可是字段多,而且熱點數據和非熱點數據在一塊兒,單行數據所需的存儲空間較大。以致於數據庫緩存的數據行減小,查詢時會去讀磁盤數據產生大量的隨機讀IO,產生IO瓶頸。 四、分析:能夠用列表頁和詳情頁來幫助理解。垂直分表的拆分原則是將熱點數據(可能會冗餘常常一塊兒查詢的數據)放在一塊兒做爲主表,非熱點數據放在一塊兒做爲擴展表。這樣更多的熱點數據就能被緩存下來,進而減小了隨機讀IO。拆了以後,要想得到所有數據就須要關聯兩個表來取數據。 但記住,千萬別用join,由於join不只會增長CPU負擔而且會講兩個表耦合在一塊兒(必須在一個數據庫實例上)。關聯數據,應該在業務Service層作文章,分別獲取主表和擴展表數據而後用關聯字段關聯獲得所有數據。
3四、數據庫鎖的做用?
根據不一樣的鎖的做用域咱們能夠把數據庫的鎖分爲三種,分別爲: 行鎖:對錶中的某一行進行加鎖。 頁鎖:對錶中一組連續的行進行加鎖。 表鎖:對整張表進行加鎖 不一樣的做用域對併發性能是有很大影響的,好比說若是數據庫的插入都是使用表鎖,那在大量用戶對某張表進行插入讀取操做的話,同時只能有一個用戶能夠訪問該表,那併發量確定就是慘不忍睹了。 樂觀鎖 在樂觀鎖中,咱們有3種經常使用的作法來實現: 第一種就是在數據取得的時候把整個數據都copy到應用中,在進行提交的時候比對當前數據庫中的數據和開始的時候更新前取得的數據。當發現兩個數據如出一轍之後,就表示沒有衝突能夠提交,不然則是併發衝突,須要去用業務邏輯進行解決。 第二種樂觀鎖的作法就是採用版本戳,這個在Hibernate中獲得了使用。採用版本戳的話,首先須要在你有樂觀鎖的數據庫table上創建一個新的column,好比爲number型,當你數據每更新一次的時候,版本數就會往上增長1。好比一樣有2個session一樣對某條數據進行操做。二者都取到當前的數據的版本號爲1,當第一個session進行數據更新後,在提交的時候查看到當前數據的版本還爲1,和本身一開始取到的版本相同。就正式提交,而後把版本號增長1,這個時候當前數據的版本爲2。當第二個session也更新了數據提交的時候,發現數據庫中版本爲2,和一開始這個session取到的版本號不一致,就知作別人更新過此條數據,這個時候再進行業務處理,好比整個Transaction都Rollback等等操做。在用版本戳的時候,能夠在應用程序側使用版本戳的驗證,也能夠在數據庫側採用Trigger(觸發器)來進行驗證。不過數據庫的Trigger的性能開銷仍是比較的大,因此能在應用側進行驗證的話仍是推薦不用Trigger。 第三種作法和第二種作法有點相似,就是也新增一個Table的Column,不過此次這個column是採用timestamp型,存儲數據最後更新的時間。在Oracle9i之後能夠採用新的數據類型,也就是timestamp with time zone類型來作時間戳。這種Timestamp的數據精度在Oracle的時間類型中是最高的,精確到微秒(還沒與到納秒的級別),通常來講,加上數據庫處理時間和人的思考動做時間,微秒級別是很是很是夠了,其實只要精確到毫秒甚至秒都應該沒有什麼問題。和剛纔的版本戳相似,也是在更新提交的時候檢查當前數據庫中數據的時間戳和本身更新前取到的時間戳進行對比,若是一致則OK,不然就是版本衝突。若是不想把代碼寫在程序中或者因爲別的緣由沒法把代碼寫在現有的程序中,也能夠把這個時間戳樂觀鎖邏輯寫在Trigger或者存儲過程當中 悲觀鎖(排他鎖) 悲觀鎖也稱之爲互斥鎖,能夠寫爲X鎖,指的是同時只能有一個事務能夠對某個資源進行訪問操做。若是有兩個事務同時要操做某張表,咱們稱之爲事務A和事務B,若是事務A得到了這張表的表鎖,那事務B只能等待事務A釋放了這個鎖以後才能對該表進行操做。 數據庫的insert,update操做默認是採用互斥鎖進行加鎖,讀取select則不是,若是要對select操做使用互斥鎖,能夠這樣寫 select * from table where id = 1 for update 共享鎖 共享鎖是一種樂觀鎖,能夠寫爲S鎖,在數據庫中共享鎖的做用主要是針對讀取操做的。若是讀取操做使用X鎖的話,併發量會很是低,因此數據庫提供了共享鎖S鎖,提升讀取操做的併發性能,多個事務能夠同時持有一個資源的S鎖,不像X鎖,同時只能有一個事務持有。 舉個例子: 事務A和事務B對錶TABLE進行訪問,事務A想查看id = 1的行信息 select * from TABLE where id = 1 lock in share mode 若是當前id = 1的行對應的X鎖沒有被其餘事務獲取,那事務A就順利的得到了該行的S鎖。 如今事務B也想查看id = 1 的行信息,會怎麼樣? select * from TABLE where id = 1 lock in share mode 如今持有該行鎖的只有事務A,持有的是S鎖,因此事務B也能夠獲取該行的S鎖,兩個事務能夠併發的讀取id = 1的行。 這個和以前所說的樂觀鎖實現是有區別的,最大的不一樣就是讀取的時候共享鎖是要真的去持有鎖,可是樂觀鎖只是實現了一種CAS模式,可是並讀取的時候沒有真的持有鎖。
3五、where 子句中有 a,b,c 三個查詢條件, 建立一個組合索引 abc(a,b,c),如下哪 種會命中索引
(a) ***** (b) (c) (a,b) ***** (b,c) (a,c) (a,b,c) *****
between like "c%" not in not exists != < <= = > >= in
varchar與char的區別char是一種固定長度的類型,varchar則是一種可變長度的類型 儘量的使用 varchar 代替 char , 由於首先變長字段存儲空間小,能夠節省存儲空間, 其次對於查詢來講, 在一個相對較小的字段內搜索效率顯然要高些。 varchar(50)表明的含義: varchar(50)中50的涵義最多存放50個字符, varchar(50)和(200)存儲hello所佔空間同樣, 但後者在排序時會消耗更多內存, 由於order by col採用fixed_length計算col長度(memory引擎也同樣)
3八、從delete語句中省略where子句,將產生什麼後果?
A. delete語句將失敗由於沒有記錄可刪除 B. delete語句將從表中刪除全部的記錄 ***** C. delete語句將示用戶進入刪除的標準 D. delete語句將失敗,由於語法錯誤
mysql的主備庫經過binlog日誌保持一致, 主庫本地執行完事務, binlog日誌落盤後即返回給用戶; 備庫經過拉取主庫binlog日誌來同步主庫的操做。 默認狀況下, 主庫與備庫並無嚴格的同步, 所以存在必定的機率備庫與主庫的數據是不對等的。 半同步特性的出現, 就是爲了保證在任什麼時候刻主備數據一致的問題。 相對於異步複製, 半同步複製要求執行的每個事務, 都要求至少有一個備庫成功接收後,才返回給用戶。 實現原理也很簡單:主庫本地執行完畢後,等待備庫的響應消息(包含最新備庫接收到的binlog(file,pos)),接收到備庫響應消息後,再返回給用戶,這樣一個事務纔算真正完成。 在主庫實例上,有一個專門的線程(ack_receiver)接收備庫的響應消息, 並以通知機制告知主庫備庫已經接收的日誌,能夠繼續執行。
40、sql 查詢
存在的表有 \1. products(商品表) columns 爲 id, name, price \2. orders(商城訂單表) columns 爲 id, reservation_id, product_id, quentity(購買數量) \3. reservations(酒店訂單表) columns 爲 id,user_id, price, created 須要查詢的: 1. 各個商品的售賣狀況, 須要字段 商品名 購買總量 商品收入 2. 全部用戶在2018-01-01至2018-02-01下單次數,下單金額,商城下單次 數, 商城下單金額 3. 歷月下單用戶數: 下單一次用戶數, 下單兩次用戶數, 下單三次及以上用戶 數
4一、考慮以下表結構,寫出建表語句
ID(自增主鍵) NAME(非空) Balance(非空) 1 A 19.50 2 A 20.50 3 A 100.00 DROP TABLE IF EXISTS `test`; CREATE TABLE `test` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `NAME` varchar(255) NOT NULL, `Balance` varchar(255) NOT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; SET FOREIGN_KEY_CHECKS = 1;
4二、假設學生Students和教師Teachers關係模型以下所示
1.Student:(學號,姓名,性別,類別,身份證號) 2.Teacher:(教師號,姓名,性別,身份證號,工資) 其中,學生關係中的類別分別爲"本科生"和"研究生兩類", 性別分爲"男"和"女" 兩類. 查詢研究生教師平均工資(顯示爲平均工資), 最高工資與最低工資之間的差值 (顯示爲差值)的 SQL 語句 select (1) as 平均工資, (2) as 差值 from Students,Teacher where (3); 查詢工資少於 10000 元的女研究生教師的身份證號和姓名的 SQL 語句(非嵌套查 詢方式); select 身份證號,姓名 from Students where (4) (5) select 身份證號,姓名 from Teachers where (6)
4三、mysql 中怎麼建立索引?
建表時建立 CREATE TABLE 表名( 字段名 數據類型 [完整性約束條件], ……, [UNIQUE | FULLTEXT | SPATIAL] INDEX | KEY [索引名](字段名1 [(長度)] [ASC | DESC]) [USING 索引方法] ); 說明: UNIQUE:可選。表示索引爲惟一性索引。 FULLTEXT:可選。表示索引爲全文索引。 SPATIAL:可選。表示索引爲空間索引。 INDEX和KEY:用於指定字段爲索引,二者選擇其中之一就能夠了,做用是 同樣的。 索引名:可選。給建立的索引取一個新名稱。 字段名1:指定索引對應的字段的名稱,該字段必須是前面定義好的字段。 長度:可選。指索引的長度,必須是字符串類型才能夠使用。 ASC:可選。表示升序排列。 DESC:可選。表示降序排列。 注:索引方法默認使用BTREE。
所謂SQL注入,就是經過把SQL命令插入到Web表單提交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。具體來講,它是利用現有應用程序,將(惡意)的SQL命令注入到後臺數據庫引擎執行的能力,它能夠經過在Web表單中輸入(惡意)SQL語句獲得一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行SQL語句。[1] 好比先前的不少影視網站泄露VIP會員密碼大多就是經過WEB表單遞交查詢字符暴出的,這類表單特別容易受到SQL注入式攻擊. 根據相關技術原理,SQL注入能夠分爲平臺層注入和代碼層注入。前者由不安全的數據庫配置或數據庫平臺的漏洞所致;後者主要是因爲程序員對輸入未進行細緻地過濾,從而執行了非法的數據查詢。基於此,SQL注入的產生緣由一般表如今如下幾方面: ①不當的類型處理; ②不安全的數據庫配置; ③不合理的查詢集處理; ④不當的錯誤處理; ⑤轉義字符處理不合適; ⑥多個提交處理不當。 預防措施: 1.永遠不要信任用戶的輸入。對用戶的輸入進行校驗,能夠經過正則表達式,或限制長度;對單引號和 雙"-"進行轉換等。 2.永遠不要使用動態拼裝sql,能夠使用參數化的sql或者直接使用存儲過程進行數據查詢存取。 3.永遠不要使用管理員權限的數據庫鏈接,爲每一個應用使用單獨的權限有限的數據庫鏈接。 4.不要把機密信息直接存放,加密或者hash掉密碼和敏感的信息。 5.應用的異常信息應該給出儘量少的提示,最好使用自定義的錯誤信息對原始錯誤信息進行包裝 6.sql注入的檢測方法通常採起輔助軟件或網站平臺來檢測,軟件通常採用sql注入檢測工具jsky,網站平臺就有億思網站安全平臺檢測工具。MDCSOFT SCAN等。採用MDCSOFT-IPS能夠有效的防護SQL注入,XSS攻擊等
4五、使用Python實現將數據庫的student表中取的數據寫入db.txt
import pymysql host = '127.0.0.1' user = 'root' passwd = '123456' port = '3306' db = 'test' # 連接數據庫 conn = pymysql.connect(host=host, port=port, user=user, passwd=passwd, db=db, charset='utf8', ) cur = conn.cursor() cur.execute("SELECT * FROM student;") data = cur.fetchall() with open('db.txt', 'w') as f: for i in data: f.write(str(i) + '\n')
4六、簡述left join和right join的區別?
left join:外連接之左鏈接:優先顯示左表所有記錄 #以左表爲準,即找出全部員工信息,固然包括沒有部門的員工 #本質就是:在內鏈接的基礎上增長左邊有右邊沒有的結果 right join:外連接之右鏈接:優先顯示右表所有記錄 #以右表爲準,即找出全部部門信息,包括沒有員工的部門 #本質就是:在內鏈接的基礎上增長右邊有左邊沒有的結果
4七、索引有什麼用,有哪些分類,有什麼好處和壞處?
做用: 索引提供指向存儲在表的指定列中的數據值的指針,而後根據您指定的排序順序對這些指針排序。數據庫使用索引以找到特定值,而後順指針找到包含該值的行。這樣能夠使對應於表的SQL語句執行得更快,可快速訪問數據庫表中的特定信息。 分類: 一、惟一索引 惟一索引是不容許其中任何兩行具備相同索引值的索引。當現有數據中存在重複的鍵值時,大多數數據庫不容許將新建立的惟一索引與表一塊兒保存。 二、主鍵索引 數據庫表常常有一列或多列組合,其值惟一標識表中的每一行。該列稱爲表的主鍵。在數據庫關係圖中爲表定義主鍵將自動建立主鍵索引,主鍵索引是惟一索引的特定類型。該索引要求主鍵中的每一個值都惟一。當在查詢中使用主鍵索引時,它還容許對數據的快速訪問。 三、彙集索引 在彙集索引中,表中行的物理順序與鍵值的邏輯(索引)順序相同。一個表只能包含一個彙集索引。若是某索引不是彙集索引,則表中行的物理順序與鍵值的邏輯順序不匹配。與非彙集索引相比,彙集索引一般提供更快的數據訪問速度。 四、索引列 能夠基於數據庫表中的單列或多列建立索引。多列索引能夠區分其中一列可能有相同值的行。若是常常同時搜索兩列或多列或按兩列或多列排序時,索引也頗有幫助。例如,若是常常在同一查詢中爲姓和名兩列設置判據,那麼在這兩列上建立多列索引將頗有意義。 優勢: 一、大大加快數據的檢索速度。 二、建立惟一性索引,保證數據庫表中每一行數據的惟一性。 三、加速表和表之間的鏈接。 四、在使用分組和排序子句進行數據檢索時,能夠顯著減小查詢中分組和排序的時間。 缺點: 一、索引須要佔物理空間。 二、當對錶中的數據進行增長、刪除和修改的時候,索引也要動態的維護,下降了數據的維護速度。
4八、寫sql語句
查詢: 1.查詢出每門課程都大於80分的學生姓 SELECT `NAME` FROM TableA WHERE `NAME` NOT IN ( SELECT `NAME` FROM TableA WHERE FENSHU < 80 GROUP BY `NAME` ) GROUP BY `NAME`; ------------------ 2.查詢出語文成績最大的學生姓名 SELECT TableA.`NAME` FROM TableA WHERE FENSHU = ( SELECT `FENSHU` FROM TableA WHERE KECHENG = "語文" GROUP BY FENSHU ORDER BY FENSHU DESC LIMIT 1 ) --------- 3.查詢沒有成績的學生姓名 SELECT `NAME` FROM TableB WHERE NAME NOT IN ( SELECT `NAME` FROM TableA GROUP BY `NAME` )
4九、試列出至少三種目前流行的大型關係型數據庫的名稱
試列出至少三種目前流行的大型關係型數據庫的名稱 其中您最熟悉的是 何時開始使用 「」「 Oracle SQL Server MySQL 」「」
慢日誌查詢的主要功能就是,記錄sql語句中超過設定的時間閾值的查詢語句。例如,一條查詢sql語句,咱們設置的閾值爲1s,當這條查詢語句的執行時間超過了1s,則將被寫入到慢查詢配置的日誌中. 慢查詢主要是爲了咱們作sql語句的優化功能. 配置項說明: 登錄mysql服務: > show variables like '%query%'; 關注三個配置項便可。 1.slow_query_log 該配置項是決定是否開啓慢日誌查詢功能,配置的值有ON或者OFF. 2.slow_query_log_file 該配置項是慢日誌查詢的記錄文件,須要手動建立. 3.long_query_time 該配置項是設置慢日誌查詢的時間閾值,當超過這個閾值時,慢日誌纔會被記錄.配置的值有0(任何的sql語句都記錄下來),或者>0(具體的閾值).該配置項是以秒爲單位的,而且能夠設置爲小數. 4.log-queries-not-using-indexes 該配置項是爲了記錄未使用到索引的sql語句.
一、一行代碼實現1--100之和
# 利用sum()函數求和 sum(range(1, 101))
二、如何在一個函數內部修改全局變量
# 利用global在函數聲明 修改全局變量 a = 5 def func(): global a a = 10 func() print(a) # 結果: 10
三、列出5個python標準庫
''' os:提供了很多與操做系統相關聯的函數 sys: 一般用於命令行參數 re: 正則匹配 math: 數學運算 datetime:處理日期時間 '''
四、字典如何刪除鍵和合並兩個字典
del和update方法 刪除鍵: del dic["name"] dic {'age':18} dic2 = {"name":"ls"} update合併:dic.update(dic2) dic {'age':18,'name':'18'}
五、談下python的GIL
GIL是python的全局解釋器鎖, 同一進程中假若有多個線程運行, 一個線程在運行python程序的時候會霸佔python解釋器(加了一把鎖即GIL), 使該進程內的其餘線程沒法運行, 等該線程運行完後其餘線程才能運行。 若是線程運行過程當中遇到耗時操做,則解釋器鎖解開,使其餘線程運行。 因此在多線程中,線程的運行還是有前後順序的,並非同時進行。 多進程中由於每一個進程都能被系統分配資源,至關於每一個進程有了一個python解釋器, 因此多進程能夠實現多個進程的同時運行,缺點是進程系統資源開銷大。
六、python實現列表去重的方法
# 先經過集合去重,在轉列表 list1 = [11, 12, 10, 13, 14, 11, 12] set1 = set(list1) print(set1) # {10, 11, 12, 13, 14} list1 = list(set1) print(list1) # [10, 11, 12, 13, 14]
七、fun(args,kwargs)中的args, kwargs什麼意思?
# *args: 能夠接收任意個形參 # **kwargs: 能夠接收任意個關鍵字參數
八、python2和python3的range(100)的區別
# python2返回列表,python3返回迭代器,節約內存
九、一句話解釋什麼樣的語言可以用裝飾器?
# 函數能夠做爲參數傳遞的語言,能夠使用裝飾器
十、python內建數據類型有哪些
''' 整型--int 布爾型--bool 字符串--str 列表--list 元組--tuple 字典--dict '''
十一、簡述面向對象中__new__和__init__區別
''' __init__是初始化方法,建立對象後,就馬上被默認調用了,可接收參數。 一、__new__至少要有一個參數cls,表明當前類,此參數在實例化時由Python解釋器自動識別 二、__new__必需要有返回值,返回實例化出來的實例,這點在本身實現__new__時要特別注意,能夠return父類(經過super(當前類名, cls))__new__出來的實例,或者直接是object的__new__出來的實例 三、__init__有一個參數self,就是這個__new__返回的實例,__init__在__new__的基礎上能夠完成一些其它初始化的動做,__init__不須要返回值 四、若是__new__建立的是當前類的實例,會自動調用__init__函數,經過return語句裏面調用的__new__函數的第一個參數是cls來保證是當前類實例,若是是其餘類的類名,;那麼實際建立返回的就是其餘類的實例,其實就不會調用當前類的__init__函數,也不會調用其餘類的__init__函數。 '''
十二、簡述with方法打開處理文件幫我咱們作了什麼?
打開文件在進行 讀寫的時候 可能會出現一些異常情況, 若是按照常規的 f.open寫法, 咱們須要 try, except, finally,作異常判斷, 而且文件最終無論遇到什麼狀況,都要執行finally f.close()關閉文件, with方法幫咱們實現了finally中 f.close (固然還有其餘自定義功能,有興趣能夠研究with方法源碼) 需求: 咱們平時對文件和數據庫操做的時候,執行的步驟都是打開---操做數據---關閉,這是正常的操做順序,但有時候不免會在操做完數據以後忘記關閉文件對象或數據庫,而使用with正是能夠解決這個問題。 原理: class MysqlHelper(object): def open(self): print(‘open‘) pass def close(self): print(‘close‘) pass def fetch_all(self): pass def __enter__(self): """ 在執行with語句中代碼以前該函數首先被調用 :return: """ self.open() def __exit__(self, exc_type, exc_val, exc_tb): """ 當with語句中最後一行代碼執行完畢以後,自動調用該方法 :param exc_type: :param exc_val: :param exc_tb: :return: """ self.close() with MysqlHelper() as f: pass 對於要使用with語句的對象,在執行with代碼體以前會首先執行該對象的__enter__方法, 而後再執行代碼體,最後自動執行__exit__方法
1三、列表[1,2,3,4,5],請使用map()函數輸出[1,4,9,16,25],並使用列表推導式提取出大於10的數,最終輸
出[16,25]
map()# 函數第一個參數是fun,第二個參數是通常是list,第三個參數能夠寫list,也能夠不寫,根據需求 def f(x): return x ** 2 res = map(f, [1, 2, 3, 4, 5]) print([i for i in res if i > 10]) ------------- 結果: [16,25]
1四、python中生成隨機整數、隨機小數、0--1之間小數方法
''' 隨機整數:random.randint(a,b),生成區間內的整數 隨機小數:習慣用numpy庫,利用np.random.randn(5)生成5個隨機小數 0-1隨機小數:random.random(),括號中不傳參 '''
1五、避免轉義給字符串加哪一個字母表示原始字符串?
r , 表示須要原始字符串,不轉義特殊字符