2020 年最全 Python 面试题汇总 (二)
@Author:Runsen
求職季在即,技巧千萬條,硬實力才是關鍵,聽說今年疫情大環(huán)境不好,更要好好準備才行。于是Runsen在??途W(wǎng),Leetcode,九章算法,不斷地尋找面試真題,共計100題,包括Python基礎,算法,數(shù)據(jù)庫,SQL,Linux。
大四刷題拼offer系列,不拼不行啊。我先刷下??途W(wǎng)的Python的題目和知識點,適當?shù)挠涗浵伦约鹤?br /> 錯的題目。
文章目錄
- 21、__new__和__init__的區(qū)別
- 22、==和is的區(qū)別
- 23、*args and **kwargs
- 24、 閉包
- 25、PEP8規(guī)范
- 26、ascii、Unicode、utf-8、gbk的區(qū)別
- 27、進制轉換
- 28、可迭代對象迭代器
- 29、迭代器
- 30、獲取命令行參數(shù)
- 31、filter、map、reduce
- 32、yield和return的區(qū)別
- 33、生成器
- 34、enumerate
- 35、面向對象的三大特性
- 36、super
- 37、魔術方法
- 38、@staticmethod和@classmethod區(qū)別
- 39、@property
- 40、內置類屬性
21、__new__和__init__的區(qū)別
填空題:在Python中__new__ 和 __init__ 的區(qū)別主要表現(xiàn)在
-
__new__:創(chuàng)建對象時調用,會返回當前對象的一個實例
-
__init__:創(chuàng)建完對象后調用,對當前對象的一些實例初始化,無返回值
簡單總結如下:
1,__new__方法是對象的生成方法,__init__方法是對象的初始化方法。
2,對象生成后,才能初始化。故__new__方法在__init__方法之前調用。
3,__new__方法的第一個參數(shù)是cls,指的是類本身,__init__的第一個參數(shù)是self,指的是__new__方法生成的對象。
4,__new__方法的其余參數(shù)會和生成的對象一起繼續(xù)傳給__init__方法。
5,__new__方法的返回值通常調用其父類的__new__方法生成。
6,__init__方法不能有返回值。
7,__new__較少使用,可以用它實現(xiàn)單例模式,即一個類只能創(chuàng)建一個實例,有時候通過使用單例模式可以極大減少內存的占用。
22、==和is的區(qū)別
題目舉例:說明Python中==和is的區(qū)別。
參考解析:is是判讀對象標識符是否一致,而==是判讀兩個對象的內容是否相等!
x is y 相當于 id(x)==id(y)
==是檢查兩個對象的內容是否相等,會調用對象的內部__eq__()。
例如下面這段代碼,只有數(shù)值型和字符串型的情況下,a is b才為True,當a和b是tuple,list,dict或set型時,a is b為False。(下面代碼只舉了字符串和list)
>>> a = "Runsen" >>> b = "Runsen" >>> a is b True >>> id(a) == id(b) True >>> a == b True >>> c = [1,2,3] >>> d = [1,2,3] >>> c is d False >>> id(c) == id(d) False >>> c == d True23、*args and **kwargs
請問:在Python函數(shù)中*args and **kwargs有上面區(qū)別?
*args 代表一個元組(數(shù)組參數(shù)),**kwargs代表一個字典(字典參數(shù))
# 單星號(*): 將所有參數(shù)以元祖(tuple)的形式導入 def signal_start(param1,*param2):print ("param1={}".format(param1))print ("*param2={}".format(param2)) signal_start(1,2,3,4,5) # param1=1 # *param2=(2, 3, 4, 5)# 雙星號(**)將參數(shù)以字典的形式導入 def double_start(param1,**param2):print ("param1={}".format(param1))print ("**param2={}".format(param2))double_start(1,a=2,b=3) # param1=1 # **param2={'a': 2, 'b': 3}24、 閉包
問:說說Python中閉包是什么?
答:可以將閉包理解為一種特殊的函數(shù),這種函數(shù)由兩個函數(shù)的嵌套組成,外函數(shù)和內函數(shù)。
def 外層函數(shù)(參數(shù)):def 內層函數(shù)():print("內層函數(shù)執(zhí)行", 參數(shù))return 內層函數(shù)內層函數(shù)的引用 = 外層函數(shù)("傳入?yún)?shù)") 內層函數(shù)的引用()在一個外函數(shù)中定義了一個內函數(shù),內函數(shù)里運用了外函數(shù)的臨時變量,并且外函數(shù)的返回值是內函數(shù)的引用。這樣就構成了一個閉包。
下面舉一個具體的閉包函數(shù)的實例,代碼如下。
# outer是外部函數(shù) def outer(a):# inner是內函數(shù)def inner( b ):#在內函數(shù)中 用到了外函數(shù)的臨時變量print(a+b)# 外函數(shù)的返回值是內函數(shù)的引用return inner ret = outer(5) #ret = inner ret(10) #15 ret 存了外函數(shù)的返回值,也就是inner函數(shù)的引用,這里相當于執(zhí)行inner函數(shù)25、PEP8規(guī)范
請列出至少5個PEP8規(guī)范
-
每一級縮進使用4個空續(xù)縮進對齊。
-
每行代碼的最大長度限制為79個字符
-
在表達式中避免無關的空格
-
代碼更改時,相應的注釋也要隨之更改。
-
命名要規(guī)范,通俗易懂
26、ascii、Unicode、utf-8、gbk的區(qū)別
- ascii 是最早美國用的標準信息交換碼,把所有的字母的大小寫,各種符號用 二進制來表示,共有256中,加入些拉丁文等字符,1bytes代表一個字符
- Unicode是為了統(tǒng)一世界各國語言的不用,統(tǒng)一用2個bytes代表一個字符,可以表達2^16=65556個,稱為萬國語言,特點:速度快,但浪費空間
- utf-8 為了改變Unicode的這種缺點,規(guī)定1個英文字符用1個字節(jié)表示,1個中文字符用3個字節(jié)表示,特點;節(jié)省空間,速度慢,用在硬盤數(shù)據(jù)傳輸,網(wǎng)絡數(shù)據(jù)傳輸,相比硬盤和網(wǎng)絡速度,體現(xiàn)不出來的
- gbk 是中文的字符編碼,用2個字節(jié)代表一個字符
27、進制轉換
進制轉換以十進制為媒介:十六進制前面加上0x,八進制加上0o,二進制前面加上0b。
| 二進制 | bin(int(x, 8)) | bin(int(x, 10)) | bin(int(x, 16)) | |
| 八進制 | oct(int(x, 2)) | oct(int(x, 10)) | oct(int(x, 16)) | |
| 十進制 | int(x, 2) | int(x, 8) | int(x, 16) | |
| 十六進制 | hex(int(x, 2)) | hex(int(x, 8)) | hex(int(x, 10)) |
28、可迭代對象迭代器
什么是可迭代對象?
可迭代的對象:常見的可以被for循環(huán)迭代的一些數(shù)據(jù)類型都是可迭代的對象,如列表,元組,字典,集合,字符串,生成器,range函數(shù)生成的數(shù)列等。凡是可作用于for循環(huán)的對象都是Iterable可迭代對象類型;
>>> iter(1111) Traceback (most recent call last):File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable >>> iter("1111") <str_iterator object at 0x000002430E9C2320>這些對象都有一個內置的iter方法,且該方法可以返回一個迭代器對象,當用iter(可迭代對象)調用這個對象時,會返回一個迭代器對象(屬于Iterator類)
29、迭代器
什么是迭代器?
凡是可作用于next( )函數(shù)的對象都是迭代器(Iterator類型),它們表示一個惰性計算的序列。
集合數(shù)據(jù)類型如list、tuple、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數(shù)獲得一個Iterator對象。
30、獲取命令行參數(shù)
Python代碼如何獲取命令行參數(shù)?
python中獲取命令行參數(shù)的方法有很多,早先的sys模塊的argv就是其中之一,現(xiàn)在使用比較多的是argparse模塊。
sys.argv[0]是Python腳本文件名,sys.argv[1:]之后的才是傳入到python腳本中的參數(shù)。所有通過命令行傳入到腳本中的參數(shù),都是字符串類型!
下面是testargv.py文件中的代碼。
import sysif __name__ == "__main__":print(sys.argv)print(sys.argv[0])sum = 0if len(sys.argv) > 1:for i in sys.argv[1:]:sum += int(i) # 強制類型轉換成int類型print("sum = ", sum)else:print("No Parameter is passed in!")argparse更易于編寫用戶友好的命令行界面。程序定義所需要的參數(shù),argparse將找出如何從sys.argv中解析這些參數(shù)。
使用步驟:
- import argparse 首先導入模塊
- parser = argparse.ArgumentParser() 創(chuàng)建一個解析對象
- parser.add_argument() 向該對象中添加你要關注的命令行參數(shù)和選項
- parser.parse_args() 進行解析
下面是testargparse.py的代碼。
import argparse# ArgumentParser對象保存了將命令行傳入的參數(shù)解析成Python數(shù)據(jù)類型的所以信息 parser = argparse.ArgumentParser(description='Process some integers.') # 調用add_argument,即可將程序的參數(shù)填充進ArgumentParser,規(guī)定 # ArgumentParser如何將命令行的字符轉換成objects parser.add_argument('integers', metavar='N', type=int, nargs='+',help='an integer for the accumulator') parser.add_argument('--sum', dest='accumulate', action='store_const',const=sum, default=max,help='sum the integers (default: find the max)') # 調用parse_args() 可以將上述所有的信息保存并開始使用 args = parser.parse_args() print(args.accumulate(args.integers))31、filter、map、reduce
filter() 相當于過濾器的作用
s=[1,2,3,5,6,8,9,10,25,12,30] # 篩選出3的倍數(shù) # 第一個參數(shù)為一個返回True或者False的函數(shù),第二個參數(shù)為可迭代對象 # 該函數(shù)把可迭代對象依次傳入第一個函數(shù),如果為True,則篩選 d=filter(lambda x:True if x % 3 == 0 else False,s) print(list(d)) # [3, 6, 9, 12, 30]map與lambda連用
# 第一個參數(shù)為函數(shù),依次將后面的參數(shù)傳給第一個函數(shù),并執(zhí)行函數(shù) # 如果有多個參數(shù)則,依次將后面的對應傳給參數(shù) s=map(lambda x,y:x+y,range(10),range(10)) print(list(s)) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] ss=map(lambda x:x*x,range(10)) print(list(ss)) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]reduce與lambda連用,與區(qū)別是:map返回的是Map對象,需要用List轉化。
from functools import reduce # 開始的時候將可迭代對象的第一個數(shù)和第二個數(shù)當成x和y # 然后將第一次函數(shù)的執(zhí)行結果當成x,然后再傳入一個數(shù)當成y # 再執(zhí)行函數(shù) s=reduce(lambda x,y:x+y,range(101)) print(s) # 相當于0+1+2+……+99+100 # 505032、yield和return的區(qū)別
你知道yield和return的區(qū)別
相同點:都是返回函數(shù)執(zhí)行的結果
不同點:return 在返回結果后結束函數(shù)的運行,而yield 則是讓函數(shù)變成一個生成器,生成器每次產(chǎn)生一個值(yield語句),函數(shù)被凍結,被喚醒后再產(chǎn)生一個值。
例子:求一組數(shù)的平方值
# return 實現(xiàn):def squre(n):ls = [i*i for i in range(n)]return ls for i in squre(5):print(i, end=' ')結果為:0 1 4 9 16
# yield 實現(xiàn):def squre(n):for i in range(n):yield i*ifor i in squre(5):print(i, end=' ')結果為:0 1 4 9 16
yield和return也很好區(qū)別,return就返回值,結束函數(shù),yield只是保存,不會結束函數(shù)。想下,在scrapy中,如果將yield改為retrun,那么爬一個就return,也就是爬取一個數(shù)據(jù)就停止了。
33、生成器
什么是生成器?
在Python中,一邊循環(huán)一邊計算的機制,稱為生成器:generator。
因為列表所有數(shù)據(jù)都在內存中,如果有海量數(shù)據(jù)的話將會非常耗內存。
創(chuàng)建生成器,只要把一個列表生成式的[]改成(),就創(chuàng)建了一個generator:
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x1022ef630>還有一種方法就是在函數(shù)中使用yield關鍵字,那么這個函數(shù)就不再是一個普通函數(shù),而是一個generator。調用函數(shù)就是創(chuàng)建了一個生成器(generator)對象。
def gen():yield 1# 返回一個對象,這個對象的值是1 def ret():return 1# 返回一個數(shù)字1 g = gen() r = ret() print(g,r) print(next(g))#輸出如下 <generator object gen at 0x0000020452E83840> 1 1也是就函數(shù)中只要有yield,這個函數(shù)就會變成生成器。每次運行到y(tǒng)ield的時候,函數(shù)會暫停,并且保存當前的運行狀態(tài),返回返回當前的數(shù)值,并在下一次執(zhí)行next方法的時候,又從當前位置繼續(xù)往下走。
34、enumerate
enumerate的意思是什么?如何使用。
在Python中,如果要在迭代列表的同時對迭代次數(shù)進行計數(shù),可以使用 enumerate關鍵字。下面是沒有使用enumerate實現(xiàn)的遍歷。
Mylist = ['Runsen','為','offer', '而戰(zhàn)'] for i in range(len(Mylist )):print(i, Mylist [i])# 輸出如下 0 Runsen 1 為 2 offer 3 而戰(zhàn)enumerate()提供了強大的功能,例如,當您需要獲取索引列表時,它會派上用場:
for i, j in enumerate(Mylist):print(i, j)# 輸出如下 0 Runsen 1 為 2 offer 3 而戰(zhàn)35、面向對象的三大特性
簡述面向對象的三大特性?
-
繼承:繼承就是繼承的類直接擁有被繼承類的屬性而不需要在自己的類體中重新再寫一遍,其中被繼承的類叫做父類、基類,繼承的類叫做派生類、子類。
-
封裝: 封裝就是把類中的屬性和方法定義為私有的,方法就是在屬性名或方法名前加雙下劃線,而一旦這樣定義了屬性或方法名后,python會自動將其轉換為_類名__屬性名(方法名)的格式,在類的內部調用還是用雙下劃線加屬性名或方法名,在類的外部調用就要用_類名__屬性名(方法名)。父類的私有屬性和方法,子類無法對其進行修改。
-
多態(tài):多態(tài)就是不同的對象可以調用相同的方法然后得到不同的結果,有點類似接口類的感覺,在python中處處體現(xiàn)著多態(tài),比如不管你是列表還是字符串還是數(shù)字都可以使用+和*。
36、super
簡述super關鍵字?
調用父類(超類)的一個方法,可以使用 super() 函數(shù),super() 函數(shù)的一個常見用法是在 init() 方法中確保父類被正確的初始化了,具體的看我寫的示例。
''' @Author: Runsen @微信公眾號: Python之王 @博客: https://blog.csdn.net/weixin_44510615 @Date: 2020/8/29 '''# 創(chuàng)建一個A類 class A(object):def __init__(self):self.x = 0def A(self):print("This A func")class B(A):# 創(chuàng)建 B 繼承 Adef __init__(self):super().__init__()self.y = 1def B(self):print("This B class ")print(self.x, self.y)super().A()if __name__ == '__main__':b = B()# 實例化 Bb.B()# 調用B# 輸出如下 This B class 0 1 This A func但是這里需要注意如果出現(xiàn)了"雙下劃線"的函數(shù)中的變量,只有類對象自己能訪問,連子類對象也不能訪問到這個數(shù)據(jù)。具體看我很早之前寫的博客的示例。
class Father():__money = 1000 #私有變量是繼承不了def __action(self): # 父類的私有方法money = 1000print('調用父類的方法')class Son(Father):def action(self):super()._Father__action()print(money) son=Son() son.action() 調用父類的方法 name 'money' is not defined這里的__action由于是"雙下劃線“,因此money 私有變量是不能用supper繼承不了,也就是不可以訪問父類中的私有屬性方法的變量money。
37、魔術方法
什么是魔術方法?
在Python中的面向對象中有很多魔術方法如:
__init__: 構造函數(shù),在生成對象時調用 __del__: 析構函數(shù),釋放對象時使用 __str__: 使用print(對象)或者str(對象)的時候觸發(fā) __repr__: 在使用repr(對象)的時候觸發(fā),前提是沒有__str__。如果有__str__,則沒有用。 __setitem__ : 按照索引賦值:每當屬性被賦值的時候都會調用該方法:self.__dict__[name] = value __getitem__: 按照索引獲取值:當訪問不存在的屬性時會調用該方法 _delitem__(self,name): 當刪除屬性時調用該方法 __len__: 獲得長度 __cmp__: 比較運算 __call__: 函數(shù)調用 __add__: 加運算 __sub__: 減運算 __mul__: 乘運算 __div__: 除運算 __mod__: 求余運算 __pow__: 乘方下面,我只介紹幾個常見的。__init__和__init__在上面有談到,這里不再述說。
1、__str__:用于處理打印實例本身的時候的輸出內容。如果沒有覆寫該函數(shù),則默認輸出一個對象名稱和內存地址。
2、 __del__ : 析構方法,恰好在對象要被刪除之前調用,目的是做一些釋放銷毀工作。
3、__call__:其實就是調用這個對象的 對象名__call__()方法,可以用來改變實例的內部成員的值。
下面看一個具體示例,區(qū)別上面的三種魔術方法。
''' @Author: Runsen @微信公眾號: Python之王 @博客: https://blog.csdn.net/weixin_44510615 @Date: 2020/8/29 '''class Student(object):def __init__(self, name, age): # 重寫了__init__方法self.name = nameself.age = agedef __str__(self):return "姓名:%s; 年齡:%d" % (self.name, self.age)def __del__(self):# 當對象被銷毀時,會自動調用這個方法print('__del__ 方法被調用了')def __call__(self, a, b):self.name = aself.age = bprint('__call__ with ({}, {})'.format(self.name, self.age))def say(self):return "Runsen為Offer而戰(zhàn)"s = Student('Runsen', 20) print(s) s("runsen",20) print(s) print(s.say()) del s# 輸出如下 姓名:Runsen; 年齡:20 __call__ with (runsen, 20) 姓名:runsen; 年齡:20 Runsen為Offer而戰(zhàn) __del__ 方法被調用了38、@staticmethod和@classmethod區(qū)別
說下@staticmethod和@classmethod的區(qū)別
其實@staticmethod和@classmethod都是用來聲明靜態(tài)方法的。只不過一個聲明靜態(tài)方法,一個聲明類方法。
-
類方法:使用裝飾器@classmethod。第一個參數(shù)為當前類的對象,通常為cls。實例對象和類對象都可以調用類方法。(不用聲明對象就可以調用)
-
靜態(tài)方法:使用裝飾器@staticmethod。沒有self和cls參數(shù)。方法體中不能使用類或者實例的任何屬性和方法。實例對象和類對象都可以調用。
為了方便大家了解兩者的差別,以下的示例代碼將有助于發(fā)現(xiàn)其中的差別:
''' @Author: Runsen @微信公眾號: 潤森筆記 @博客: https://blog.csdn.net/weixin_44510615 @Date: 2020/8/30 ''' class A():@classmethoddef get_name(cls, name):print(cls) # <class '__main__.A'>print('my name is %s' % name)@staticmethoddef get_age(age):print(f'i am %s years old' % age)if __name__ == '__main__':A.get_name('Runsen') # my name is RunsenA.get_age(20) # i am 20 years old@staticmethod 與 @classmethod在Python中稱為 裝飾器,用來修飾函數(shù),相當于添加一個額外的功能,比如不再像普通函數(shù)那樣進行實例化。通過使用裝飾器可以讓代碼更加整潔,易讀。用了修飾器之后,也可以進行實例化之后再調用,但是就顯得多此一舉了。
| a = A() | a.get_name() | a.get_name() | a.get_name() |
| A | 不可用 | A.get_name() | A.get_name() |
39、@property
說下你對@property的理解
@property可以將一個方法的調用變成屬性調用。舉例說明:平時我們調用數(shù)據(jù)屬性和方法,是這樣的
class School():name = "家里蹲大學"def test(self):print("實例方法")@propertydef test_pro(self):print("靜態(tài)屬性")if __name__ == "__main__":s = School()print(s.name)s.test()#輸出 # 家里蹲大學# 實例方法如果我們想直接類似于數(shù)據(jù)屬性一樣的去調用方法
class School():name = "家里蹲大學"def test(self):print("實例方法")@propertydef test_pro(self):print("靜態(tài)屬性")if __name__ == "__main__":s = School()print(s.name)# 注意返回的函數(shù) 千萬別加()s.test_pro#輸出 # 家里蹲大學# 靜態(tài)屬性40、內置類屬性
說下你了解幾個內置類屬性?
__dict__: 類的屬性(包含一個字典,由類的數(shù)據(jù)屬性組成)
__doc__ :類的文檔字符串
__name__: 類名
__module__: 類定義所在的模塊
__bases__: 類的所有父類構成元素(包含了一個由所有父類組成的元組)
如果你想跟博主建立親密關系,可以關注博主,或者關注博主公眾號“Python之王”,了解一個非本科程序員是如何成長的。
博主ID:潤森,希望大家點贊、評論、收藏
總結
以上是生活随笔為你收集整理的2020 年最全 Python 面试题汇总 (二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 五十六、TodoList的三种写法,祭奠
- 下一篇: websocket python爬虫_p