談談對Python和其他語言的區別
Python屬於解釋型語言,當程序運行時,是一行一行的解釋,並運行,所以調式代碼很方便,開發效率高, 還有龜叔給Python定位是任其自由發展、優雅、明確、簡單,所以在每個領域都有建樹,所有它有着非常強大的第三方庫, 特點: 語法簡潔優美,功能強大,標准庫與第三方庫都非常強大,而且應用領域也非常廣 可移植性,可擴展性,可嵌入性 缺點: 運行速度慢, - 解釋型 - python/php - 編譯型 - c/java/c# - Python弱類型
(1)與java相比:在很多方面,Python比Java要簡單,比如java中所有變量必須聲明才能使用,而Python不需要聲明,用少量的代碼構建出很多功能;(高效的高級數據結構)
(2)與php相比:python標准包直接提供了工具,並且相對於PHP代碼更易於維護;
(3)Python與c相比:
Python 和 C Python這門語言是由C開發而來
對於使用:Python的類庫齊全並且使用簡潔,如果要實現同樣的功能,Python 10行代碼可以解決,C可能就需要100行甚至更多.
對於速度:Python的運行速度相較與C,絕逼是慢了
Python的優勢:
1、Python 易於學習;
2、用少量的代碼構建出很多功能;(高效的高級數據結構)
3、Python 擁有最成熟的程序包資源庫之一;
4、Python完全支持面向對象;
5、Python 是跨平台且開源的。
6、動態類型:
位和字節的關系
1字節 = 8 位 位(bit),數據存儲是以“字節”(Byte)為單位,數據傳輸是以大多是以“位”(bit,又名“比特”)為單位, 一個位就代表一個0或1(即一個二進制),二進制是構成存儲器的最小單位,每8個位(bit,簡寫為b)組成一個字節(Byte,簡寫為B), 字節是最小一級的信息單位
b、B、KB、MB、GB的關系
b --->位(bit) B --->字節 一個字節等於8位 1B = 8 bit 1kb = 1024 B 1 MB = 1024 KB 1 GB = 1024 MB
PEP8規范
1、使用4個空格而不是tab鍵進行縮進。 2、每行長度不能超過79 3、使用空行來間隔函數和類,以及函數內部的大塊代碼 4、必要時候,在每一行下寫注釋 5、使用文檔注釋,寫出函數注釋 6、在操作符和逗號之后使用空格,但是不要在括號內部使用 7、命名類和函數的時候使用一致的方式,比如使用CamelCase來命名類, 使用lower_case_with_underscores來命名函數和方法 8、在類中總是使用self來作為默認 9、盡量不要使用魔法方法 10、默認使用UTF-8,甚至ASCII作為編碼方式 11、換行可以使用反斜杠,最好使用圓括號。 12、不要在一句import中多個庫, 空格的使用 各種右括號前不要加空格。 逗號、冒號、分號前不要加空格。 函數的左括號前不要加空格。如Func(1) 序列的左括號前不要加空格。如list[2] 操作符左右各加一個空格,不要為了對齊增加空格 函數默認參數使用的賦值符左右省略空格 不要將多句語句寫在同一行,盡管使用‘;’允許 if/for/while語句中,即使執行語句只有一句,也必須另起一行 函數命名使用全部小寫的方式,常量命名使用大寫,類屬性(方法和變量)使用小寫 類的命名首字母大寫
一行代碼實現刪除列表里重復的元素
sorted(set(list),key=list.index)
排列順序不變oldList
=
[
'a'
,
'b'
,
'c'
,
'd'
,
'a'
,
'a'
]
newList
=
[]
for
letter
in
oldList:
if
letter
not
in
newList:
newList.append(letter)
print
newList
運行結果:
[
'a'
,
'b'
,
'c'
,
'd'
]
一行代碼實現九九乘法表
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)]))
s="1,2,3" print(s.split(",")) 結果 ['1', '2', '3']
s=['1', '2', '3']
print([int(i) for i in s])
結果
[1, 2, 3]
一行代碼生成
[i**2 for i in range(1,11)]
結果
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
a=(5)與b=(5,)的區別
元組中只包含一個元素時,需要在元素后面添加逗號,否則括號會被當作運算符使用:
a=(5)
b=(5,)
print(type(a),a)
print(type(b),b)
結果
<class 'int'> 5
<class 'tuple'> (5,)
三元運算寫法和應用場景?
應用場景:簡化if語句 # 關於三元運算 # 結果+ if + 條件 + else + 結果 result='gt' if 1>3 else 'lt' print(result) # lt # 理解:如果條件為真,把if前面的值賦值給變量,否則把else后面的值賦值給變量。 lambda 表達式 temp = lambda x,y:x+y print(temp(4,10)) # 14 可替代: def foo(x,y): return x+y print(foo(4,10)) # 14
Python3和Python2的區別?
1:打印時,py2需要可以不需要加括號,py3 需要 python 2 :print ('lili') , print 'lili' python 3 : print ('lili') python3 必須加括號 exec語句被python3廢棄,統一使用exec函數 2:內涵 Python2:1,臃腫,源碼的重復量很多。 2,語法不清晰,摻雜着C,php,Java,的一些陋習。 Python3:幾乎是重構后的源碼,規范,清晰,優美。 3、輸出中文的區別 python2:要輸出中文 需加 # -*- encoding:utf-8 -*- Python3 : 直接搞 4:input不同 python2 :raw_input python3 :input 統一使用input函數 5:指定字節 python2在編譯安裝時,可以通過參數-----enable-unicode=ucs2 或-----enable-unicode=ucs4分別用於指定使用2個字節、4個字節表示一個unicode; python3無法進行選擇,默認使用 ucs4 查看當前python中表示unicode字符串時占用的空間: impor sys print(sys.maxunicode) #如果值是65535,則表示使用usc2標准,即:2個字節表示 #如果值是1114111,則表示使用usc4標准,即:4個字節表示 6: py2:xrange range py3:range 統一使用range,Python3中range的機制也進行修改並提高了大數據集生成效率 7:在包的知識點里 包:一群模塊文件的集合 + __init__ 區別:py2 : 必須有__init__ py3:不是必須的了 8:不相等操作符"<>"被Python3廢棄,統一使用"!=" 9:long整數類型被Python3廢棄,統一使用int 10:迭代器iterator的next()函數被Python3廢棄,統一使用next(iterator) 11:異常StandardError 被Python3廢棄,統一使用Exception 12:字典變量的has_key函數被Python廢棄,統一使用in關鍵詞 13:file函數被Python3廢棄,統一使用open來處理文件,可以通過io.IOBase檢查文件類型
xrange和range的區別
python2中 都在循環時使用,xrange內存性能更好,xrange用法與range完全相同,range一個生成list對象,xrange是生成器 要生成很大的數字序列的時候,用xrange會比range性能優很多,因為不需要一上來就開辟一塊很大的內存空間。 在 Python 3 中,range() 是像 xrange() 那樣實現,xrange()被拋棄。
文件操作時:xreadlines和readlines的區別?
python2中 readlines 返回一個列表 xreadlines 返回一個生成器
#format的三種玩法 格式化輸出 res='{} {} {}'.format('egon',18,'male') ==> egon 18 male res='{1} {0} {1}'.format('egon',18,'male') ==> 18 egon 18 res='{name} {age} {sex}'.format(sex='male',name='egon',age=18)
談談Python的深淺拷貝?
淺拷貝只是增加了一個指針指向一個存在的地址, 而深拷貝是增加一個指針並且開辟了新的內存,這個增加的指針指向這個新的內存, 采用淺拷貝的情況,釋放內存,會釋放同一內存,深拷貝就不會出現釋放同一內存的錯誤
Python垃圾回收機制?
引用計數 標記清除 分代回收
按每個字符串的第一個值,合並a和b到c
a = ["a,1", "b,3,22", "c,3,4"] b = ["a,2", "b,1", "d,2"]
d=a+b
dic={}
for i in d:
dic.setdefault(i[0],"")
dic[i[0]]+=i[1:]
c=[]
for i in dic:
msg=i+dic[i]
c.append(msg)
print(c)
一個list中多層嵌套list或者tuple(元組)或字典(dict)等的遍歷
#coding=utf-8 def printList(list1): for elements in list1: if isinstance(elements,list) or isinstance(elements, tuple): printList(elements) #遞歸調用函數本身進行深層次的遍歷 elif isinstance(elements, dict): for i in elements.items(): print(i) else : print(elements) 該題的基本思路就是先判斷list中每一個元素具體是什么類型,如果是list或者是tuple,就采用遞歸算法往深進行一層一層的遍歷,
直到list中的元素為常規類型時,就打印輸出,由於dict類型中的鍵值key必須唯一,所以只能是不可變類型數據,所以這里不存在深層遍歷dict鍵值的問題。
列表排序
正數在前負數在后 2.整數從小到大 3.負數從大到小
例: 排序前[7, -8, 5, 4, 0, -2, -5] 排序后[0, 4, 5, 7, -2, -5, -8] print(list(sorted(lst, key = lambda x: (x < 0, abs(x)))))
詳解 https://www.cnblogs.com/ellisonzhang/p/10359057.html
什么是反射?以及應⽤用場景?
反射的核心本質就是以字符串的形式去導入個模塊,利用字符串的形式去執行函數。 Django中的 CBV就是基於反射實現的。
用盡量多的方法實現單例模式
1:使用模塊 Python的模塊就是天然的單例模式。 因為模塊在第一次導入時,會生成 .pyc 文件,當第二次導入時,就會直接加載 .pyc 文件,而不會再次執行模塊代碼。 因此,我們只需把相關的函數和數據定義在一個模塊中,就可以獲得一個單例對象了。 例如: class V1(object): def foo(self) pass V1 = V1() 將上面代碼保存在文件test.py,要使用時,直接在其他文件中導入此文件中的對象,這個對象既是單例模式的對象 如:from a import V1 2:使用裝飾器 def Singleton(cls): _instance = {} def _singleton(*args, **kargs): if cls not in _instance: _instance[cls] = cls(*args, **kargs) return _instance[cls] return _singleton @Singleton class A(object): a = 1 def __init__(self, x=0): self.x = x a1 = A(2) a2 = A(3) 3:使用類 4:基於__new__方法實現 當我們實例化一個對象時,是先執行了類的__new__方法 當:(我們沒寫時,默認調用object.__new__),實例化對象;然后再執行類的__init__方法,對這個對象進行初始化,所有我們可以基於這個,實現單例模式
def func(a,b=[]) 這種寫法有什什么坑?
def func(a,b = []): b.append(1) print(a,b) func(a=2) func(2) func(2) ''' [1] [1, 1] [1, 1, 1] 函數的默認參數是一個list 當第一次執行的時候實例化了一個list 第二次執行還是用第一次執行的時候實例化的地址存儲 所以三次執行的結果就是 [1, 1, 1] 想每次執行只輸出[1] ,默認參數應該設置為None '''
字符串駐留機制
字符串駐留機制 對於短字符串,將其賦值給多個不同的對象時,內存中只有一個副本,多個對象共享該副 本。長字符串不遵守駐留機制。 駐留適用范圍 由數字,字符和下划線(_)組成的python標識符以及整數[-5,256]。
Python里面如何拷貝一個對象
1.淺拷貝 : 使用copy.copy,它可以進行對象的淺拷貝(shallow copy),它復制了對象,但對於對象中的元素,依然使用引用(換句話說修改拷貝對象元素,則被拷貝對象元素也被修改) 2.深拷貝 : 使用copy.deepcopy,它可以進行深拷貝,不僅拷貝了對象,同時也拷貝了對象中的元素,獲得了全新的對象,與被拷貝對象完全獨立,但這需要犧牲一定的時間和空間。 3.特殊拷貝:相當於淺拷貝 如要復制列表L,使用list(L),要復制一個字典d,使用dict(d),要復制一個集合s,使用set(s)。 總結一下的話:如果你要復制某個對象object, 它屬於python內建的類型type,那么你可以使用type(object)來 獲得一個拷貝。
如何打亂一個排好序的list
1. import random 2. random.shuffle(alist)
.find()和.index()的區別
s.index(x):返回字符串中出現x的最左端的索引值,如果不在則拋出valueError異常 s.find(x) :返回字符串中出現x的最左端字符的索引值,如果不在則返回-1
輸入一個字符串,輸出該字符串中字符的所有組合
def func(s) s=s.split(",") lst=[] lst1=[] lst2=[] for i in range(len(s)): for j in range(len(s)): for k in range(len(s)): if i>=j: msg="".join(s[j:i]) msg=msg+s[len(s)-k-1] count=0 for i in range(1,len(msg)): if len(msg) ==1 : lst.append(msg) elif msg[i]>msg[i-1]: count+=1 if count==len(msg)-1: lst.append(msg) a=list(set(lst)) for i in a: lst1.append(int(i)) lst1=sorted(lst1) for i in lst1: lst2.append(str(i)) print(lst2,len(lst2))
一個數如果恰好等於它的因子之和,這個數就稱為“完數”。例如6=1+2+3.編程
找出1000以內的所有完數。
def func(n):
a=n/2
lst=[]
count=1
while count<a+1:
if n%count==0:
lst.append(count)
count+=1
if sum(lst)==n:
return n
lst=[]
for i in range(1001):
if func(i):
lst.append(i)
print(lst)
將一個正整數分解質因數。例如:輸入90,打印出90=2*3*3*5
n = int(input(">>>")) b = n a = n / 2 lst = [] count = 2 while count < a + 1: if n % count == 0: n = n / count lst.append(count) else: count += 1 print(f"{b}=", end="") for i in range(len(lst)): if i == len(lst) - 1: print(lst[i]) else: print(f"{lst[i]}*", end="")
判斷101-200之間有多少個素數,並輸出所有素數
def func(n): b=n a=n/2 lst=[] count=2 while count<a+1: if n%count==0: n=n/count lst.append(count) else: count += 1 return lst count=0 for i in range(101,201): a=func(i) if a == []: count += 1 print(count)
對於一個非空字符串,判斷其是否可以有一個子字符串重復多次組成
# def func(s): # lst=list(s) # count=0 # for j in range(1,len(s)//2+1): # lst1=[] # for i in range(0,len(s),j): # msg="".join(lst[i:i+j]) # lst1.append(msg) # if len(set(lst1))==1: # count=1 # print("Ture") # return lst1[0] # if count==0: # print("False")
把aaabbcccd這種形式的字符串壓縮成a3b2c3d1這種形式
s="aaabbcccd" lst=[] for i in s: if i not in lst: lst.append(i) lst.append(str(s.count(i))) msg="".join(lst) print(msg)
通過代碼實現如下進制轉換:
1 hex() 2 轉換一個整數對象為十六進制的字符串 3 4 >>> hex(16) 5 '0x10' 6 >>> hex(18) 7 '0x12' 8 >>> hex(32) 9 '0x20'
1 oct() 2 轉換一個整數對象為八進制的字符串 3 4 >>> oct(8) 5 '0o10' 6 >>> oct(166) 7 '0o246'
1 bin() 2 轉換一個整數對象為二進制字符串 3 4 >>> bin(10) 5 '0b1010' 6 >>> bin(255) 7 '0b11111111'
1 chr() 2 轉換一個[0, 255]之間的整數為對應的ASCII字符 3 4 >>> chr(65) 5 'A' 6 >>> chr(67) 7 'C' 8 >>> chr(90) 9 'Z' 10 >>> chr(97) 11 'a'
1 ord() 2 將一個ASCII字符轉換為對應整數 3 4 >>> ord('A') 5 65 6 >>> ord('z') 7 122
1 16進制轉10進制 2 >>> int('10', 16) 3 16 4 >>> int('0x10', 16) 5 16 6 7 8進制轉10進制 8 >>> int('0o10', 8) 9 8 10 >>> int('10', 8) 11 8 12 13 2進制轉10進制 14 >>> int('0b1010', 2) 15 10 16 >>> int('1010', 2) 17 10
lambda表達式格式以及應用場景
2、map,filter,reduce函數
例子: a = [('a',1),('b',2),('c',3),('d',4)] a_1 = list(map(lambda x:x[0],a)) 如上例子,map函數第一個參數是一個lambda表達式,輸入一個對象,返回該對象的第一個元素。
第二個就是需要作用的對象,此處是一個列表。Python3中map返回一個map對象,我們需要人工
轉為list,得到的結果就是[‘a’,’b’,’c’,’d’] 例子: a = [1,2,3,4] b = [2,3,4,5] a_1 = list(map(lambda x,y:x+y,a,b)) 上邊這個例子是為了說明,lambda表達式參數可以是多個。返回結果是[3,5,7,9]
例子: a = [1,2,3,4,5,6,7] a_1 = filter(lambda x:x<4,a) 如上例子,定義lambda表達式,篩選a列表中小於4的元素,結果為[1,2,3]。filter函數直接返回一個列表,
無需再進行轉換,第三個是初始值,我們沒給初始值,那么開始操作的兩個元素就是序列的前兩個。否則將使用我們
給出的初始值和序列第一個元素操作,然后結果再與第三個元素操作,以此類推。上個例子結果是28
例子: from functools import reduce #python3需要導入此模塊 a = [1,2,3,4,5,6,7] a_1 = reduce(lambda x,y:x+y,a) reduce中使用的lambda表達式需要兩個參數,reduce函數共三個參數, 第一個是就是lambda表達式,第二個是要累計的序列,第三個是初始值, 我們沒給初始值,那么開始操作的兩個元素就是序列的前兩個。否則將使 用我們給出的初始值和序列第一個元素操作,然后結果再與第三個元素操 作,以此類推。上個例子結果是28
3、字典多條件排序
例子: dict = {'a':1,'b':2,'c':3,'d':4,'e':3,'f':1,'g':7} sorted_dict_asc = sorted(dict.items(),key=lambda item:item[0]) sorted_dict_dsc = sorted(dict.items(),key=lambda item:item[0],reverse=True) 輸出(第一個升序,第二個降序): [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 3), ('f', 1), ('g', 7)] [('g', 7), ('f', 1), ('e', 3), ('d', 4), ('c', 3), ('b', 2), ('a', 1)]]
pass的作用
pass是空語句占位符,是為了保持程序結構的完整性。
*arg和**kwarg作用
定義函數時,使用*arg和**kwarg *arg和**kwarg 可以幫助我們處理上面這種情況,允許我們在調用函數的時候傳入多個實參 def exmaple2(required_arg, *arg, **kwarg): if arg: print "arg: ", arg if kwarg: print "kwarg: ", kwarg exmaple2("Hi", 1, 2, 3, keyword1 = "bar", keyword2 = "foo") >> arg: (1, 2, 3) >> kwarg: {'keyword2': 'foo', 'keyword1': 'bar'} 從上面的例子可以看到,當我傳入了更多實參的時候 *arg會把多出來的位置參數轉化為tuple **kwarg會把關鍵字參數轉化為dict
簡述 生成器、迭代器、可迭代對象 以及應用場景?
簡述 生成器、迭代器、可迭代對象 以及應用場景? Python可迭代對象(Iterable) Python中經常使用for來對某個對象進行遍歷,此時被遍歷的這個對象就是可迭代對象,像常見的list,tuple都是。
如果給一個准確的定義的話,就是只要它定義了可以返回一個迭代器的__iter__方法,或者定義了可以支持下標索引的__getitem__方法
(這些雙下划線方法會在其他章節中全面解釋),那么它就是一個可迭代對象。 Python迭代器(iterator) 迭代器是通過next()來實現的,每調用一次他就會返回下一個元素,當沒有下一個元素的時候返回一個StopIteration異常,
所以實際上定義了這個方法的都算是迭代器。可以用通過下面例子來體驗一下迭代器: 生成器(Generators) 生成器是構造迭代器的最簡單有力的工具,與普通函數不同的只有在返回一個值的時候使用yield來替代return,然后yield會自動構建好next()和iter() 因為迭代器如此普遍,python專門為for關鍵字做了迭代器的語法糖。在for循環中,Python將自動調用工廠函數iter()獲得迭代器,
自動調用next()獲取元素,還完成了檢查StopIteration異常的工作。
談談你對閉包的理解。
1 #閉包函數的實例 2 # outer是外部函數 a和b都是外函數的臨時變量 3 def outer( a ): 4 b = 10 5 # inner是內函數 6 def inner(): 7 #在內函數中 用到了外函數的臨時變量 8 print(a+b) 9 # 外函數的返回值是內函數的引用 10 return inner 11 12 if __name__ == '__main__': 13 # 在這里我們調用外函數傳入參數5 14 #此時外函數兩個臨時變量 a是5 b是10 ,並創建了內函數,然后把內函數的引用返回存給了demo 15 # 外函數結束的時候發現內部函數將會用到自己的臨時變量,這兩個臨時變量就不會釋放,會綁定給這個內部函數 16 demo = outer(5) 17 # 我們調用內部函數,看一看內部函數是不是能使用外部函數的臨時變量 18 # demo存了外函數的返回值,也就是inner函數的引用,這里相當於執行inner函數 19 demo() # 15 20 21 demo2 = outer(7) 22 demo2()#17
# 一行代碼 通過filter 和 lambda 函數輸出以下列表索引為奇數的對應的元素 list_b = [12, 232, 22, 2, 2, 3, 22, 22, 32]
new_list=[x[1] for x in filter(lambda x:x[0]%2==1,enumerate(list_b))]
Python中 dict.items() dict.iteritems()區別
dict.items()返回的是一個完整的列表,而dict.iteritems()返回的是一個生成器(迭代器)。 dict.items()返回列表list的所有列表項,形如這樣的二元組list:[(key,value),(key,value),...],
dict.iteritems()是generator, yield 2-tuple。相對來說,前者需要花費更多內存空間和時間,但訪問某一項的時間較快(KEY)。
后者花費很少的空間,通過next()不斷取下一個值,但是將花費稍微多的時間來生成下一item。
對於yield與yield from 的理解
yield是什么?
yield單詞的含義:屈服,投降,提供
對於一個函數而言,程序的執行,從上到下執行完一遍,這個函數也就完成了它的使命。
def hello():
print('exe 1')
print('exe 2')
hello()這個函數從上到下依次執行,然后hello()結束。
若一個函數中加入了yield語句,那么這個函數就被增強了,變成了一個生成器:generator。 對於一個函數,其程序執行到了yield語句,那么它選擇了`投降`,返回一個結果,這個函數被中斷,然后隨着生成器的next的執行,該函數從中斷的地方執行。 >``` def helloYield(): print('exe 1') yield '1 be exed' print('exe 2') yield '2 be exed'
執行:
gen=helloYield()
print(gen.__next__()) print(gen.__next__()) 結果: exe 1 1 be exed exe 2 2 be exed
yield from是什么?
yield 可以返回結果
yield from 可以返回一個新的迭代器
看一個例子:
有一個list,如下:
lists = [
1, 2, 3,
[4, 5, [6, 7], 8],
[[[9, 10], 11]],
[[]],
12,
]
需要將list中的所有數據一個個顯示出來,如下:
1
2
3
4
5
6
7
8
9
10
11
12
采用yield from的方式,代碼如下:
def flatten(items): for item in items: if isinstance(item, (list, tuple)): yield from flatten(item) else: yield item
常用模塊都有那些? re模塊,os模塊,json模塊,time模塊, 爬蟲里面的requests/beautifulsoup4(bs4) re的match和search區別? re.match 嘗試從字符串的起始位置匹配一個模式,如果不是起始位置匹配成功的話,match()就返回none。 re.search 掃描整個字符串並返回第一個成功的匹配。 什么是正則的貪婪匹配? 匹配一個字符串沒有節制,能匹配多少就去匹配多少,知道沒有匹配的為止
logging模塊的作用?以及應用場景?
模塊定義的函數和類為應用程序和庫的開發實現了一個靈活的事件日志系統 作用:可以了解程序運行情況,是否正常
在程序的出現故障快速定位出錯地方及故障分析
談談你對面向對象的理解
三大特性以及解釋?
面對對象是一種編程思想,以類的眼光來來看待事物的一種方式。將有共同的屬性和方法的事物封裝到同一個類下面。
繼承:將多個類的共同屬性和方法封裝到一個父類下面,然后在用這些類來繼承這個類的屬性和方法
封裝:將有共同的屬性和方法封裝到同一個類下面
- 第一層面:創建類和對象會分別創建二者的名稱空間,我們只能用類名.或者obj.的方式去訪問里面的名字,這本身就是一種封裝
- 第二層面:類中把某些屬性和方法隱藏起來(或者說定義成私有的),只在類的內部使用、外部無法訪問,或者留下少量接口(函數)供外部訪問。
多態:Python天生是支持多態的。指的是基類的同一個方法在不同的派生類中有着不同的功能
Python面向對象中的繼承有什么特點
繼承概念的實現方式主要有2類:實現繼承、接口繼承。 實現繼承是指使用基類的屬性和方法而無需額外編碼的能力; 接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力(子類重構爹類方法); python 兩種類:經典類 新式類 python3 新式類 —— 都默認繼承object class Animal(object): == class Animal: python2 經典類和新式類 並存 class Animal: 經典類 —— 繼承順序 個別使用方法 class Animal(object): 新式類 繼承分為單繼承和多繼承 Python是支持多繼承的 如果沒有指定基類,python的類會默認繼承object類,object是所有python類的基類,它提供了一些常見方法(如__str__)的實現。
補充繼承的應用(面試題)
1、對象可以調用自己本類和父類的所有方法和屬性, 先調用自己的 自己沒有才調父類的。誰(對象)調用方法,方法中的self就指向誰 class Foo: def __init__(self): self.func() def func(self): print('Foo.func') class Son(Foo): def func(self): print('Son.func') s = Son() # Son.func ======================================================== class A: def get(self): self.say() def say(self): print('AAAAA') class B(A): def say(self): print('BBBBB') b = B() b.get() #輸出結果為:BBBBB
面向對象深度優先和廣度優先是什么?
Python的類可以繼承多個類,Python的類如果繼承了多個類,那么其尋找方法的方式有兩種 當類是經典類時,多繼承情況下,會按照深度優先方式查找 py3 當類是新式類時,多繼承情況下,會按照廣度優先方式查找 py2 簡單點說就是:經典類是縱向查找,新式類是橫向查找 經典類和新式類的區別就是,在聲明類的時候,新式類需要加上object關鍵字。在python3中默認全是新式類
面向對象中super的作用?
用於子類繼承基類的方法
class FooParent(object): def __init__(self): self.parent = 'I\'m the parent.' print('Parent') print('1111') def bar(self, message): print("%s from Parent" % message) class FooChild(FooParent): def __init__(self): # super(FooChild,self) 首先找到 FooChild 的父類(就是類 FooParent),然后把類B的對象 FooChild 轉換為類 FooParent 的對象 super(FooChild, self).__init__() print('Child') # def bar(self, message): # # super(FooChild, self).bar(message) # print('Child bar fuction') # print(self.parent) if __name__ == '__main__': fooChild = FooChild() fooChild.bar('HelloWorld')
是否使用過functools中的函數?其作用是什么?
用於修復裝飾器
import functools def deco(func): @functools.wraps(func) # 加在最內層函數正上方 def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper @deco def index(): '''哈哈哈哈''' x = 10 print('from index') print(index.__name__) print(index.__doc__) # 加@functools.wraps # index # 哈哈哈哈 # 不加@functools.wraps # wrapper # None
列舉面向對象中帶雙下划線的特殊方法,如:__new__、__init__
- __new__:生成實例
- __init__:生成實例的屬性
-
__call__:實例對象加( )會執行def __call__:... 方法里邊的內容。
__del__:析構方法,當對象在內存中被釋放時,自動觸發執行。如當 del obj 或者應用程序運行完畢時,執行該方法里邊的內容。
__enter__和__exit__:出現with語句,對象的__enter__被觸發,有返回值則賦值給as聲明的變量;with中代碼塊執行完畢時執行__exit__里邊的內容。
__module__:表示當前操作的對象在那個模塊 obj.__module__
__class__ :表示當前操作的對象的類是什么 obj.__class____doc__:類的描述信息,該描述信息無法被繼承
__str__:改變對象的字符串顯示 print函數 --->obj.__str__()
__repr__:改變對象的字符串顯示 交互式解釋器 --->obj.__repr__()
__format__:自定制格式化字符串__slots__:一個類變量 用來限制實例可以添加的屬性的數量和類型
__setitem__,__getitem,__delitem__:
class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): print(self.__dict__[item]) def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): print('del obj[key]時,我執行') self.__dict__.pop(key) def __delattr__(self, item): print('del obj.key時,我執行') self.__dict__.pop(item) f1=Foo('sb') f1['age']=18 f1['age1']=19 del f1.age1 del f1['age'] f1['name']='alex' print(f1.__dict__)
__get__():調用一個屬性時,觸發
__set__():為一個屬性賦值時,觸發
__delete__():采用del刪除屬性時,觸發
__setattr__,__delattr__,__getattr__ :
如何判斷是函數還是方法?
看他的調用者是誰,如果是類,就需要傳入一個參數self的值,這時他就是一個函數,
如果調用者是對象,就不需要給self傳入參數值,這時他就是一個方法
print(isinstance(obj.func, FunctionType)) # False
print(isinstance(obj.func, MethodType)) # True
class Foo(object): def __init__(self): self.name = 'lcg' def func(self): print(self.name) obj = Foo() print(obj.func) # <bound method Foo.func of <__main__.Foo object at 0x000001ABC0F15F98>> print(Foo.func) # <function Foo.func at 0x000001ABC1F45BF8> # ------------------------FunctionType, MethodType------------# from types import FunctionType, MethodType obj = Foo() print(isinstance(obj.func, FunctionType)) # False print(isinstance(obj.func, MethodType)) # True print(isinstance(Foo.func, FunctionType)) # True print(isinstance(Foo.func, MethodType)) # False # ------------------------------------------------------------# obj = Foo() Foo.func(obj) # lcg obj = Foo() obj.func() # lcg """ 注意: 方法,無需傳入self參數 函數,必須手動傳入self參數 """
靜態方法和類方法區別?
盡管 classmethod 和 staticmethod 非常相似,但在用法上依然有一些明顯的區別。classmethod 必須有一個指
向類對象的引用作為第一個參數,而 staticmethod 可以沒有任何參數。
舉個栗子:
class Num: # 普通方法:能用Num調用而不能用實例化對象調用 def one(): print ('1') # 實例方法:能用實例化對象調用而不能用Num調用 def two(self): print ('2') # 靜態方法:能用Num和實例化對象調用 @staticmethod def three(): print ('3') # 類方法:第一個參數cls長什么樣不重要,都是指Num類本身,調用時將Num類作為對象隱式地傳入方法 @classmethod def go(cls): cls.three() Num.one() #1 #Num.two() #TypeError: two() missing 1 required positional argument: 'self' Num.three() #3 Num.go() #3 i=Num() #i.one() #TypeError: one() takes 0 positional arguments but 1 was given i.two() #2 i.three() #3 i.go() #3
什么是面向對象的mro
mro就是方法解析順序
isinstance作用以及應用場景?
isinstance(對象,類) 判斷這個對象是不是這個類或者這個類的子類的實例化
# # 判斷a 屬不屬於A這個類(可以判斷到祖宗類) class A: pass class B(A): pass a = A() b = B() print(isinstance(b,A)) # ===> True 判斷到祖宗類 # 任何與object都是True,內部都繼承object class A:pass a = A() # 實例化 print(isinstance(a,object)) # True
75. json序列化時,可以處理的數據類型有哪些?如何定制支持datetime類型?
class CJsonEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime.date): return obj.strftime('%Y-%m-%d %H:%M:%S') else: return json.JSONEncoder.default(self, obj) import json import datetime a = datetime.datetime.now() print(a) b = json.dumps(a,cls=CJsonEncoder) print(b)
json序列化時,默認遇到中文會轉換成unicode,如果想要保留中文怎么辦?
在序列化時,中文漢字總是被轉換為unicode碼,在dumps函數中添加參數ensure_ascii=False即可解決。
什么是斷言?應用場景?
assert 是的作用?斷言 條件成立(布爾值為True)則繼續往下,否則跑出異常,一般用於:滿足某個條件之后,才能執行,否則應該跑出異常。
logging模塊的作用?以及應用場景?
1.日志的作用 通過log的分析,可以方便用戶了解系統或軟件、應用的運行情況;如果你的應用log足夠豐富,也可以分析以往用戶的操作行為、
類型喜好、地域分布或其他更多信息;如果一個應用的log同時也分了多個級別,那么可以很輕易地分析得到該應用的健康狀況,
及時發現問題並快速定位、解決問題,補救損失。簡單來講就是,我們通過記錄和分析日志可以了解一個系統或軟件程序運行情況
是否正常,也可以在應用程序出現故障時快速定位問題。比如,做運維的同學,在接收到報警或各種問題反饋后,進行問題排查時
通常都會先去看各種日志,大部分問題都可以在日志中找到答案。再比如,做開發的同學,可以通過IDE控制台上輸出的各種日志進
行程序調試。對於運維老司機或者有經驗的開發人員,可以快速的通過日志定位到問題的根源。可見,日志的重要性不可小覷。
日志的作用可以簡單總結為以下3點: 程序調試 了解軟件程序運行情況,是否正常 軟件程序運行故障分析與問題定位 即:DEBUG < INFO < WARNING < ERROR < CRITICAL,而日志的信息量是依次減少的;
有用過with statement嗎?它的好處是什么?
文件操作的時候用過 with語句的作用是通過某種方式簡化異常處理,它是所謂的上下文管理器的一種 with open('output.txt', 'w') as f: f.write('Hi there!') 當你要成對執行兩個相關的操作的時候,這樣就很方便,以上便是經典例子,with語句會在嵌套的代碼執行之后,
自動關閉文件。這種做法的還有另一個優勢就是,無論嵌套的代碼是以何種方式結束的,它都關閉文件。
如果在嵌套的代碼中發生異常,它能夠在外部exception handler catch異常前關閉文件。如果嵌套代碼有return/continue/break語句,它同樣能夠關閉文件。
請描述with的用法
python中with可以明顯改進代碼友好度,比如: 復制代碼 代碼如下: with open('a.txt') as f: print f.readlines() 為了我們自己的類也可以使用with, 只要給這個類增加兩個函數__enter__, __exit__即可: 復制代碼 代碼如下: >>> class A: def __enter__(self): print 'in enter' def __exit__(self, e_t, e_v, t_b): print 'in exit' >>> with A() as a: print 'in with' in enter in with in exit 另外python庫中還有一個模塊contextlib,使你不用構造含有__enter__, __exit__的類就可以使用with: 復制代碼 代碼如下: >>> from contextlib import contextmanager >>> from __future__ import with_statement >>> @contextmanager ... def context(): ... print 'entering the zone' ... try: ... yield ... except Exception, e: ... print 'with an error %s'%e ... raise e ... else: ... print 'with no error' ... >>> with context(): ... print '----in context call------' ... entering the zone ----in context call------ with no error 使用的最多的就是這個contextmanager, 另外還有一個closing 用處不大 復制代碼 代碼如下: from contextlib import closing import urllib with closing(urllib.urlopen('http://www.python.org')) as page: for line in page: print line