1. 程式人生 > 其它 >Day 23:Python 中的一些高頻面試題及解答小記

Day 23:Python 中的一些高頻面試題及解答小記

python小知識
#!/usr/bin/env python
# coding: utf-8

# 1)
# 一行程式碼生成 [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
# 找規律
lst = [2*_ -1 for _ in range(1,11)]
lst
  
# 2) # 生成等差數列 # 用range步長就可以 lst = list(range(10,100,5)) lst
# 3) # 一行程式碼求 1 到 10000 內整數和 # sum ret = sum(range(10000)) ret # 4) 累積和 from functools import reduce ret = reduce(lambda
x,y: x+y,range(10000)) ret
# 5) # 打亂一個列表 # random.shuffle() import random a = list(range(10)) print(type(a)) random.shuffle(a) print(a) # 6) # 字典按 value 排序並返回新字典 or 按 key 排序 # python 有內建sorted函式,支援選擇排序指標 d= {'a':12,'b':50,'c':1,'d':20} d = dict(sorted(d.items(),key=lambda item:item[1])) d = dict(sorted(d.items(),key=lambda
item:item[0])) d
# 7) # 如何刪除 list 裡重複元素,並保證元素順序不變 a = [3,2,2,2,1,3] # 既然都用python了,怎麼高效怎麼來 def del_duplicated(lst): ret = [] for _ in lst: if _ not in ret: ret.append(_) return ret del_duplicated(a) # 8) # 找出兩個列表的相同元素和不同元素? # 那就是取交集,和交集的補集 # 用集合的intersection求交方法和difference求差方法很快啊union並集方法
a = [3,2,2,2,1,3] b = [1,4,3,4,5] def ans(lst_1, lst_2): set_1,set_2 = set(lst_1),set(lst_2) intersection = set_1.intersection(set_2) complement = set_1.difference(set_2).union(set_2.difference(set_1)) return intersection, complement c,d = ans(a,b) print(a,b,c,d) # 9) # 字串處理成字典 輸入串 "k0:10|k1:2|k2:11|k3:5",輸出字典 {k0:10,k1:2,...} # 涉及字串的分割 split方法 # 先分| 再按 : 分 m = map(lambda x:x.split(':'),'k0:10|k1:2|k2:11|k3:5'.split('|')) ans = {mi[0]:int(mi[1]) for mi in m } ans # 10) # 輸入日期,判斷這一天是這一年的第幾天 # 需要用到time 或是 datetime中的方法 from datetime import datetime def i_day_of_years(y,m,d): return datetime(y,m,d).date().timetuple().tm_yday ret = i_day_of_years(2021,7,11) ret # 11) # 單機 4G 記憶體,處理 10G 檔案的方法? # ans:按行讀取,使用生成器函式yield方法以節省記憶體 也可以一次IO讀取多行 Pandas的方法可以實現 def python_read(filename): with open(filename,'r',encoding='utf-8') as f: for line in f: yield line if __name__ == '__main__': g = python_read('寫入filename') for c in g: print(c) # process c # 一次IO讀入多行 眾多引數,更加靈活,參考pd.read_csv() 的各種方法 def pandas_read(filename,sep=',',chunksize=5): reader = pd.read_csv(filename,sep=sep,chunksize=chunksize) while True: try: yield reader.get_chunk() except StopIteration: print('---Done---') break if __name__ == '__main__': g = pandas_read('寫入filename',sep="::") for c in g: print(c) # process c # 12) # 統計一個文字中單詞頻次最高的 10 個單詞 # 首先要按行解耦讀入文字,然後得到單詞,需要分隔字串,用正則替換掉沒用的字串,儲存並做統計,取最高rank的10個單詞 from collections import Counter, defaultdict import re def python_read(filename): with open(filename,'r',encoding='utf-8') as f: for line in f: yield line d = defaultdict(int) # 預設生成的字典 def process(line): for word in re.sub('\W+'," ",line).split(): # 先匹配任意字母/數字/下劃線以外的字元替換成空格,再預設按空格分割 d[word] += 1 for line in python_read('寫入filename'): process(line) most_active_word_10 = Counter(d).most_common(10) print(most10) # 13) # 反轉一個整數,例如 -12345 --> -54321 # 轉成字元逆序再轉成int再乘以符號 如果是負的,除去“-”符號再逆序 def reverse_int(x:int): if -10 < x < 10: return x x_str = str(x) def reverse_str(str): return str[::-1] if x_str[0] == "-": temp_str = reverse_str(x_str[1::]) ret = int(temp_str) return -ret return int(reverse_str(x_str)) reverse_int(-531546654) # 14) # 內嵌函式呼叫 def f(): i = 0 def foo(x): return i*x #foo 使用的兩個變數 i 和 x,其中 x 為其形參,i 為 enclosing 域內定義的變數 rtn = [] while i < 3: rtn.append(foo) i += 1 return rtn # 呼叫函式 f for fs in f(): print(fs(10)) # rtn 新增三個函式 foo,但是並未發生呼叫。 # 直到執行 fs(10) 時,內嵌函式 foo 才被呼叫,但是此時的 enclosing 變數 i 取值為 3 # 15) # 函式的正確呼叫 def foo(filename,a=0,b=1,c=2): print('filename: %s \n c: %d'%(filename,c)) ''' A foo('.', 10)錯誤 a被賦值為10 B foo('.', 0,1,10)對 C foo('.',0,1,c=10)對 D foo('.',a=0,1,10)錯 關鍵字引數要在位置引數後面 E foo(filename='.', c=10)對 F foo('.', c=10)對 ''' # 16) # lambda 函式的形參和返回值 def longer(*s): return max(*s, key=lambda x: len(x)) longer({1,3,5,7},{1,5,7},{2,4,6,7,8}) # lambda 函式的形參:s 解包後的元素值,可能取值為:{1,3,5,7}、{1,5,7}、{2,4,6,7,8} 三種。 # lambda 函式的返回值為:元素的長度,可能取值為:{1,3,5,7}、{1,5,7}、{2,4,6,7,8} 的長度 4,3,5。 # 17) # 正則匹配負整數 # 小知識 匹配所有負整數,不包括 0。正則表示式:^-[1-9]\d*$ """ ^- 表示字串以 - 開頭 [1-9] 表示數字 1 到 9,注意不要寫成 \d,因為負整數沒有以 -0 開頭的 \d* 表示數字 0 到 9 出現 0 次、1 次或多次 $ 表示字串以數字結尾 """ import re s = ['-1','-15756','9','-01','10','-'] pat = r'^-[1-9]\d*$' rec = re.compile(pat) rs = [i for i in s if rec.match(i)] print(rs) # 結果 # ['-1', '-15756'] # 18) # 正則匹配負浮點數 # 小知識 匹配所有負的浮點數,正則表示式: ^-[1-9]\d*\.\d*|-0\.\d*[1-9]\d*$ # 例項 -0.12 的正則表示式:^-0.\d*[1-9]\d*$ # 例項 -111.234 的正則表示式:^-[1-9]\d*.\d*$ # 使用 |,綜合兩種情況 import re s = ['-1','-1.5756','-0.00','-000.1','-1000.10'] pat = r'^-[1-9]\d*\.\d*|-0\.\d*[1-9]\d*$' rec = re.compile(pat) rs = [i for i in s if rec.match(i)] print(rs) # 結果 # ['-1.5756', '-1000.10'] # 19) # 求出列表中大於 10 的元素 過濾器 # 使用fliter函式,lambda函式 """ def filter_self(function, iterable): return iter([ item for item in iterable if function(item)]) """ # 過濾掉不滿足函式 function 的元素,重新返回一個新的迭代器。 a = [15,2,7,20,400,10,9,-15,107] al = list(filter(lambda x: x > 10, a)) al # 20) # map對映函式 # map 函式當含有多個列表時,返回長度為最短列表的長度 m = map(lambda x,y: min(x,y), [5, 1, 3, 4], [3,4,3,2,1]) list(m) # 21) # reduce 函式的輸出結果 # reduce實現 規約。 # function函式的引數必須為2,是可迭代物件 iterable 內的連續兩項 # 計算過程,從左側到右側,依次歸約,直到最終為單個值並返回。 from functools import reduce reduce(lambda x,y: x*y+1,[1,2,3,4,5]) # 22) # x = (i for i in range(5)),x 是什麼型別 # x 是生成器型別,與for in相結合使用於迭代 x = (i for i in range(5)) for i in x: print(i) # 23) # 可變型別和不可變型別分別列舉 3 個 # 可變型別:mutable type,常見的有:list、dict、set、deque佇列 等 # 不可變型別:immutable type,常見的有:int、float、str、tuple、frozenset 等 # 小知識:只有不可變型別才能作為字典等的鍵。 # frozenset凍結集合,一旦建立不允許增刪元素 # 24) # is 和 == 有什麼區別? # is 標識號 用來判斷兩個物件的標識號是否相等; # == 物件的值或者內容 用於判斷值或內容是否相等,預設是基於兩個物件的標識號比較。 #p.s. 也就是說,如果 a is b 為 True 且如果按照預設行為,意味著 a==b 也為 True # 25) # 寫一個學生類 Student # 新增一個屬性 id,並實現若 id 相等,則認為是同一位同學的功能。 # 重寫 __eq__ 方法,若 id 相等,返回 True。 class Student: def __init__(self,id,name): self.id = id self.name = name def __eq__(self,student): return self.id == student.id s1 = Student(10,'xiaoming') s2 = Student(20,'xiaohong') s3 = Student(10,'xiaoming2') s1 == s2 s1 == s3 # 26) # 有什麼方法獲取類的所有屬性和方法? 答:dir(物件) dir(Student) a = [1,2,3] dir(a) # 27) # Python 中如何動態獲取和設定物件的屬性? 主要問題是 動態 就是說要先判斷原來沒有的,需要立刻馬上增加一個 class Student: def __init__(self,id,name): self.id = id self.name = name def __eq__(self,student): return self.id == student.id # 使用 hasattr 方法,判斷例項是否有屬性 x: s1 = Student(10,'xiaoming') print(hasattr(s1,'id')) print(hasattr(s1,'age')) # 使用 setattr 動態新增物件的屬性,函式原型:<function setattr(obj, name, value, /)> if not hasattr(Student, 'age'): setattr(Student,'age','beijing') print(hasattr(s1,'age')) # 28) # 實現一個按照 2*i+1 自增的迭代器 # 肯定要重寫__next__方法或者__iter__ from collections.abc import Iterator class AutoIncreass(Iterator): def __init__(self,init,n): self.init = init self.n = n self.__cal = 0 def __iter__(self): return self def __next__(self): if self.__cal == 0: self.__cal += 1 return self.init while self.__cal < self.n: self.init *= 2 self.init += 1 self.__cal += 1 return self.init raise StopIteration # 返回的是一個迭代器物件,用for in 列印 iter = AutoIncreass(1,10) for i in iter: print(i) # 29) # 實現檔案按行讀取和操作資料分離功能 # 首先是檔案按行讀取 ,節省記憶體,yield函式 # 然後是對讀取的這一行資料進行操作 def read_line(filename): with open(filename,'r',encoding='utf-8') as f: for line in f: yield line def process_line(line:str): pass for line in read_line("檔名"): process_line(line) # 30) # 使用 Python 鎖避免髒資料出現的例子 # 會出現同時修改一個全域性變數的情況,叫做 暴露問題,建立一把鎖 locka: # 通過 locka.acquire() 獲得鎖,通過 locka.release() 釋放鎖。 # 多執行緒的程式碼,由於避免髒資料的出現,基本退化為單執行緒程式碼,執行效率被拖累。 import threading import time locka = threading.Lock() a = 0 def add1(): global a try: locka.acquire() # 獲得鎖 tmp = a + 1 time.sleep(0.2) # 模擬 IO 操作 a = tmp finally: locka.release() # 釋放鎖 print('%s adds a to 1: %d'%(threading.current_thread().getName(),a)) threads = [threading.Thread(name='t%d'%(i,),target=add1) for i in range(10)] [t.start() for t in threads] # 31) # 說說死鎖、GIL 鎖、協程 比如,執行緒 A 等待著執行緒 B 釋放鎖 b,同時,執行緒 B 等待著執行緒 A 釋放鎖 a。在這種局面下,執行緒 A 和執行緒 B 都相互等待著,無法執行下去,這就是死鎖。 為了避免死鎖發生,Python 使用 GIL 鎖,確保同一時刻只有一個執行緒在執行,所以其實是偽多執行緒。 Python 裡常常使用協程技術來代替多執行緒。多程序、多執行緒的切換是由系統決定,而協程由我們自己決定。協程無需使用鎖,也就不會發生死鎖。同時,利用協程的協作特點,高效的完成了原程式設計模型只能通過多個執行緒才能完成的任務。 看多執行緒和協程部分筆記:https://www.cnblogs.com/PiaYie/p/14995055.html#_label3