前言
我們上篇文章為大家介紹了Python常見的部分面試題,今天的文章給大家吧剩下的常見的面試題全部介紹給大家,希望能夠幫到大家。
- 一、Python如何實作單例模式?
Python有三種方式可以實作單例模式,首先就是通過子產品。其實,Python 的子產品就是天然的單例模式,因為子產品在第一次導入時,會生成 .pyc 檔案,當第二次導入時,就會直接加載 .pyc 檔案,而不會再次執行子產品代碼。是以,我們隻需把相關的函數和資料定義在一個子產品中,就可以獲得一個單例對象了。如果我們真的想要一個單例類,可以考慮這樣做:
class Singleton(object):
def foo(self):
pass
singleton = Singleton()
将上面的代碼儲存在檔案 mysingleton.py 中,要使用時,直接在其他檔案中導入此檔案中的對象,這個對象即是單例模式的對象,即:from a import singleton。其次是使用裝飾器,具體使用如下:
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)
另外使用類,具體實作如下:
class Singleton(object):
def __init__(self):
pass
@classmethod
def instance(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
Singleton._instance = Singleton(*args, **kwargs)
return Singleton._instance
一般情況,大家以為這樣就完成了單例模式,但是這樣當使用多線程時會存在問題。具體實作如下:
class Singleton(object):
def __init__(self):
pass
@classmethod
def instance(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
Singleton._instance = Singleton(*args, **kwargs)
return Singleton._instance
import threading
def task(arg):
obj = Singleton.instance()
print(obj)
for i in range(10):
t = threading.Thread(target=task,args=[i,])
t.start()
具體的執行結果如下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SZyY2YhdzM1MjNjhDNlNTY1MTYhFWM1IDMlRGNmVDN28CX1AzLcdDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL3M3Lc9CX6MHc0RHaiojIsJye.png)
- 二、Python是如何進行類型轉換的?
Python提供了将變量或值從一種類型轉換成另一種類型的内置函數。int函數能夠将符合數學格式數字型字元串轉換成整數。否則,傳回錯誤資訊。
- 函數int也能夠把浮點數轉換成整數,但浮點數的小數部分被截去
- 函數float将整數和字元串轉換成浮點數
函數str将數字轉換成字元
整數1和浮點數1.0在python中是不同的。雖然它們的值相等的,但卻屬于不同的類型。這兩個數在計算機的存儲形式也是不一樣。具體案例如下:
print(int('34'))
print(int(34.1234))
print(int(-2.46))
print(float('12'))
print(float('1.11111111'))
print(str(98))
print(str('76.765'))
具體執行結果如下:
- 三、Python如何定義一個函數
函數的定義形式如下:
def <name>(arg1, arg2,… argN):
<statements>
函數的名字也必須以字母開頭,可以包括下劃線“ ”,但不能把Python的關鍵字定義成函數的名字。函數内的語句數量是任意的,每個語句至少有一個空格的縮進,以表示此語句屬于這個函數的縮進結束的地方,函數自然結束。
下面定義了一個兩個數相加的函數:
def add(p1, p2):
print(p1, "+", p2, "=", p1+p2)
add(1,2)
具體執行結果如下圖所示:
函數的目的是把一些複雜的操作隐藏,來簡化程式的結構,使其容易閱讀。函數在調用前,必須先定義。也可以在一個函數内部定義函數,内部函數隻有在外部函數調用時才能夠被執行。程式調用函數時,轉到函數内部執行函數内部的語句,函數執行完畢後,傳回到它離開程式的地方,執行程式的下一條語句。
-
四、如何反序的疊代一個序列?
如果是一個list, 最快的解決方案是:
list.reverse()
try:
for x in list:
'do something with x'
finally:
list.reverse()
如果不是list, 最通用但是稍慢的解決方案是:
for i in range(len(sequence)-1, -1, -1):
x = sequence[i]
'<do something with x>'
- 五、Python檔案操作的面試題
如何用Python删除一個檔案?
使用os.remove(filename)或者os.unlink(filename);
Python如何copy一個檔案?
shutil子產品有一個copyfile函數可以實作檔案拷貝
- 六、如何用Python來發送郵件?
可以使用smtplib标準庫。以下代碼可以在支援SMTP監聽器的伺服器上執行;
import sys, smtplib
from click._compat import raw_input
fromaddr = raw_input('From: ')
toaddrs = raw_input('To: ').split(',')
print ('Enter message, end with ^D:')
msg = ''
while 1:
line = sys.stdin.readline()
if not line:
break
msg = msg + line
# 發送郵件部分
server = smtplib.SMTP('localhost')
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
- 七、有兩個序列a,b,大小都為n,序列元素的值任意整形數
無序;要求:通過交換a,b中的元素,使[序列a元素的和]與[序列b元素的和]之間的差最小。将兩序列合并為一個序列,并排序,為序列Source。拿出最大元素Big,次大的元素Small。在餘下的序列S[:-2]進行平分,得到序列max,min。将Small加到max序列,将Big加大min序列,重新計算新序列和,和大的為max,小的為min。具體實作如下:
def abs_test(a,b):
# 假設剛開始就是內插補點最小的
# 此時的內插補點絕對值為:
min = abs(sum(a)-sum(b))
# x,y分别為a,b清單的下标值
x=y=0
# 當a的下标小于a的長度時,依次用b的每一個值和a的值交換
# 比較他們的內插補點絕對值的大小
while x<len(a):
#依次用b的每一個值和目前a的值交換
while y<len(b):
a[x],b[y] = b[y],a[x]
# 交換後2個清單的內插補點絕對值
tmp = abs(sum(a)-sum(b))
# 如果此時的內插補點小,則指派給min
# 否則還将交換回去
if min>tmp:
min = tmp
else:
a[x],b[y] = b[y],a[x]
y += 1
x += 1
y = 0
return a,b
a = [1000, 999, 998, 997, 996, 995]
b = [994, 993, 992, 3, 2, 1]
val = abs_test(a,b)
print(val)
- 八、下面這段段代碼的輸出結果是什麼?請解釋
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)
以上輸出的結果如下:
怎樣修改extendList的定義能夠産生以下預期的行為?
list1 = [10, ‘a’]
list2 = [123]
list3 = [10, ‘a’]
很多人都會誤認為list1=[10],list3=[‘a’],因為他們以為每次extendList被調用時,清單參數的預設值都将被設定為[].但實際上的情況是,新的預設清單隻在函數被定義的那一刻建立一次。
當extendList被沒有指定特定參數list調用時,這組list的值随後将被使用。這是因為帶有預設參數的表達式在函數被定義的時候被計算,不是在調用的時候被計算。是以list1和list3是在同一個預設清單上進行操作(計算)的。而list2是在一個分離的清單上進行操作(計算)的。(通過傳遞一個自有的空清單作為清單參數的值)。
extendList的定義可以作如下修改。盡管,建立一個新的清單,沒有特定的清單參數。下面這段代碼可能能夠産生想要的結果:
def extendList(val, list=None):
if list is None:
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)
以上代碼輸出的結果如下:
- 九、給定以下字典的子類,下面的代碼能夠運作麼?為什麼?
class DefaultDict(dict):
def __missing__(self, key):
return []
d = DefaultDict()
d['florp'] = 127
print(d)
能夠運作。因為當key缺失時,執行DefaultDict類,字典的執行個體将自動執行個體化這個數列。具體執行結果如下:![]()
python面試題彙總(下)
- 十、重新實作str.strip()
def rightStrip(tempStr,splitStr):
endindex = tempStr.rfind(splitStr)
while endindex != -1 and endindex == len(tempStr) - 1:
tempStr = tempStr[:endindex]
endindex = tempStr.rfind(splitStr)
return tempStr
def leftStrip(tempStr,splitStr):
startindex = tempStr.find(splitStr)
while startindex == 0:
tempStr = tempStr[startindex+1:]
startindex = tempStr.find(splitStr)
return tempStr
str = " H "
print (str)
print (leftStrip(str,' '))
print (rightStrip(str,' '))
具體執行的結果如下:
- 十一、super的原理
class A(object):
def __init__(self):
print ("enter A")
super(A, self).__init__() # new print "leave A"
class B(object):
def __init__(self):
print ("enter B")
super(B, self).__init__() # new print "leave B"
class C(A):
def __init__(self):
print ("enter C")
super(C, self).__init__()
print ("leave C")
class D(A):
def __init__(self):
print ("enter D")
super(D, self).__init__()
print ("leave D")
class E(B, C):
def __init__(self):
print ("enter E")
super(E, self).__init__() # change print "leave E"
class F(E, D):
def __init__(self):
print ("enter F")
super(F, self).__init__() # change print "leave F"
- 十二、閉包
常用的裝飾器就是閉包的一種,閉包(Closure)是詞法閉包(Lexical Closure)的簡稱,是引用了自由變量的函數。這個被引用的自由變量将和這個函數一同存在,即使已經離開了創造它的環境也不例外 。
def make_adder(addend):
def adder(augend):
return augend + addend
return adder
p1 = make_adder(4)
p2 = make_adder(5)
print(p1(10))
print(p2(10))
執行結果如下:
- 十三、.給清單中的字典排序
list 對象 alist [{“name”:”a”,”age”:20},{“name”:”b”,”age”:30},{“name”:”c”,”age”:25}]按照 age 從大到小排序。具體實作如下:
alist = [{"name": "a", "age": 20}, {"name": "b", "age": 30}, {"name": "c", "age": 25}]
alist.sort(key=lambda x: x['age'])
print(alist)
- 十四、合并兩個清單排除重複元素
用簡潔的方法合并alist = [‘a’,’b’,’c’,’d’,’e’,’f’] blist = [‘x’,’y’,’z’,’e’,’f’]并且元素不能重複
alist = ['a','b','c','d','e','f']
blist = ['x','y','z','e','f']
def merge_list(*args):
s = set()
for i in args:
s = s.union(i)
print(s)
return s
merge_list(alist,blist)
具體實作結果如下:
- 十五、打亂一個排好序的清單
import random
a = [1, 2, 3, 4, 5, 6]
random.shuffle(a)
print(a)
- 十六、簡單的實作一個棧結構 stack
class Stack: # 定義一個棧
def __init__(self): # 初始化棧為空清單
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item) # append()尾段加入資料
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
s = Stack()
print(s.isEmpty())
s.push(4)
s.push("dog")
s.push(True)
print(s.peek())
print(s.pop())
print(s.peek())
- 十七、輸入一個日期,傳回時一年中的哪一天
from datetime import datetime
def which_day(year,month,day):
return (datetime(year,month,day)-datetime(year,1,1)).days+1
print(which_day(2021,7,4))
- 十八、把字元串”k1:1|k2:2|k3:3”處理成 python 字典的形式:{k1:1,k2:2,k3:3}
def string_to_dict(string):
d = {}
for kv in string.split("|"):
k,v = kv.split(":")
if v.isdigit():
v=int(v)
d[k]=v
return d
print(string_to_dict("k1:1|k2:2|k3:3"))
- 十九、判斷輸入的值是否在矩陣之中(楊氏矩陣)
在一個二維數組之中,每一行都按照從走到右遞增的順序排序,每一列到按照從上到下的順序排序.請完成一個函數,輸入這樣的一個二維手術和一個整數,判斷數組中是否含有該整數
arr = [[1,4,7,10,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]]
def get_num(num,data=None):
while data:
if num > data[0][-1]:
del data[0]
elif num<data[0][-1]:
data = list(zip(*data))
del data[-1]
data = list(zip(*data))
else:
return True
data.clear()
return False
print (get_num(18,arr))
- 二十、擷取最大公約數(歐幾裡得算法)
a= 25
b=15
def max_common(a,b):
while b:
a,b=b,a%b
return a
print(max_common(a, b))
- 二十一、求兩個數的最小公倍數(公式法)
兩個數的乘積等于這兩個數的 最大公約數與最小公倍數的積
a= 25
b=15
def min_common(a,b):
c= a*b
while b:
a,b=b,a%b
return c//a
print(min_common(a, b))
- 二十二、擷取中位數
如果總數個數是奇數,按從小到大的順序,取中間的那個數;如果總數個數是偶數個的話,按從小到大的順序,取中間那兩個數的平均數。
#計算中位數
def mediannum(num):
listnum = [num[i] for i in range(len(num))]
listnum.sort()
lnum = len(num)
if lnum % 2 == 1:
i = int((lnum + 1) / 2)-1
return listnum[i]
else:
i = int(lnum / 2)-1
return (listnum[i] + listnum[i + 1]) / 2
def medin(data):
data.sort()
half = len(data)//2
return (data[half]+data[half])/2
l = [1,3,4,53,2,46,8,42,82]
print (medin(l))
print(mediannum(l))