2019 Python100道 面试 题,你会几道?
0 遇到過得反爬蟲策略以及解決方法?
1.通過headers反爬蟲
2.基于用戶行為的發爬蟲:(同一IP短時間內訪問的頻率)
3.動態網頁反爬蟲(通過ajax請求數據,或者通過JavaScript生成)
4.對部分數據進行加密處理的(數據是亂碼)
解決方法:
對于基本網頁的抓取可以自定義headers,添加headers的數據
使用多個代理ip進行抓取或者設置抓取的頻率降低一些,
動態網頁的可以使用selenium + phantomjs 進行抓取
對部分數據進行加密的,可以使用selenium進行截圖,使用python自帶的pytesseract庫進行識別,但是比較慢最直接的方法是找到加密的方法進行逆向推理。
1 urllib 和 urllib2 的區別?
- urllib 和urllib2都是接受URL請求的相關模塊,但是urllib2可以接受一個Request類的實例來設置URL請求的headers,urllib僅可以接受URL。urllib不可以偽裝你的User-Agent字符串。
- urllib提供urlencode()方法用來GET查詢字符串的產生,而urllib2沒有。這是為何urllib常和urllib2一起使用的原因。
2 列舉網絡爬蟲所用到的網絡數據包,解析包?
- 網絡數據包 urllib、urllib2、requests
- 解析包 re、xpath、beautiful soup、lxml
3 簡述一下爬蟲的步驟?
4 遇到反爬機制怎么處理?
反爬機制:
headers方向
判斷User-Agent、判斷Referer、判斷Cookie。
將瀏覽器的headers信息全部添加進去
注意:Accept-Encoding;gzip,deflate需要注釋掉
5 常見的HTTP方法有哪些?
- GET:請求指定的頁面信息,返回實體主體;
- HEAD:類似于get請求,只不過返回的響應中沒有具體的內容,用于捕獲報頭;
- POST:向指定資源提交數據進行處理請求(比如表單提交或者上傳文件),。數據被包含在請求體中。
- PUT:從客戶端向服務端傳送數據取代指定的文檔的內容;
- DELETE:請求刪除指定的頁面;
- CONNNECT:HTTP1.1協議中預留給能夠將連接方式改為管道方式的代理服務器;
- OPTIONS:允許客戶端查看服務器的性能;
TRACE:回顯服務器的請求,主要用于測試或者診斷。
6 說一說redis-scrapy中redis的作用?
它是將scrapy框架中Scheduler替換為redis數據庫,實現隊列管理共享。
優點:
7 遇到的反爬蟲策略以及解決方法?
8 如果讓你來防范網站爬蟲,你應該怎么來提高爬取的難度 ?
9 scrapy分為幾個組成部分?分別有什么作用?
分為5個部分;Spiders(爬蟲類),Scrapy Engine(引擎),Scheduler(調度器),Downloader(下載器),Item Pipeline(處理管道)。
- Spiders:開發者自定義的一個類,用來解析網頁并抓取指定url返回的內容。
- Scrapy Engine:控制整個系統的數據處理流程,并進行事務處理的觸發。
- Scheduler:接收Engine發出的requests,并將這些requests放入到處理列隊中,以便之后engine需要時再提供。
- Download:抓取網頁信息提供給engine,進而轉發至Spiders。
- Item Pipeline:負責處理Spiders類提取之后的數據。
比如清理HTML數據、驗證爬取的數據(檢查item包含某些字段)、查重(并丟棄)、將爬取結果保存到數據庫中
10 簡述一下scrapy的基本流程?
scrapy分為9個步驟:
11 python3.5語言中enumerate的意思是
對于一個可迭代的(iterable)/可遍歷的對象(如列表、字符串),enumerate將其組成一個索引序列,利用它可以同時獲得索引和值
enumerate多用于在for循環中得到計數
12 你是否了解谷歌的無頭瀏覽器?
無頭瀏覽器即headless browser,是一種沒有界面的瀏覽器。既然是瀏覽器那么瀏覽器該有的東西它都應該有,只是看不到界面而已。
Python中selenium模塊中的PhantomJS即為無界面瀏覽器(無頭瀏覽器):是基于QtWebkit的無頭瀏覽器。
13 scrapy和scrapy-redis的區別?
scrapy是一個爬蟲通用框架,但不支持分布式,scrapy-redis是為了更方便的實現scrapy分布式爬蟲,而提供了一些以redis為基礎的組件
為什么會選擇redis數據庫?
因為redis支持主從同步,而且數據都是緩存在內存中,所以基于redis的分布式爬蟲,對請求和數據的高頻讀取效率非常高
什么是主從同步?
在Redis中,用戶可以通過執行SLAVEOF命令或者設置slaveof選項,讓一個服務器去復制(replicate)另一個服務器,我們稱呼被復制的服務器為主服務器(master),而對主服務器進行復制的服務器則被稱為從服務器(slave),當客戶端向從服務器發送SLAVEOF命令,要求從服務器復制主服務器時,從服務器首先需要執行同步操作,也即是,將從服務器的數據庫狀態更新至主服務器當前所處的數據庫狀態
14 scrapy的優缺點?為什么要選擇scrapy框架?
優點:
采取可讀性更強的xpath代替正則 強大的統計和log系統 同時在不同的url上爬行 支持shell方式,方便獨立調試 寫middleware,方便寫一些統一的過濾器 通過管道的方式存入數據庫
缺點:
基于python爬蟲框架,擴展性比較差,基于twisted框架,運行中exception是不會干掉reactor,并且異步框架出錯后是不會停掉其他任務的,數據出錯后難以察覺
15 scrapy和requests的使用情況?
requests 是 polling 方式的,會被網絡阻塞,不適合爬取大量數據
scapy 底層是異步框架 twisted ,并發是最大優勢
16 描述一下scrapy框架的運行機制?
從start_urls里面獲取第一批url發送請求,請求由請求引擎給調度器入請求對列,獲取完畢后,調度器將請求對列交給下載器去獲取請求對應的響應資源,并將響應交給自己編寫的解析方法做提取處理,如果提取出需要的數據,則交給管道處理,如果提取出url,則繼續執行之前的步驟,直到多列里沒有請求,程序結束。
17 寫爬蟲使用多進程好,還是用多線程好?
IO密集型代碼(文件處理、網絡爬蟲等),多線程能夠有效提升效率(單線程下有IO操作會進行IO等待,造成不必要的時間浪費,而開啟多線程能在線程A等待時,自動切換到線程B,可以不浪費CPU的資源,從而能提升程序執行效率)。在實際的數據采集過程中,既考慮網速和響應的問題,也需要考慮自身機器的硬件情況,來設置多進程或多線程
18 常見的反爬蟲和應對方法?
19 分布式爬蟲主要解決什么問題?
面對海量待抓取網頁,只有采用分布式架構,才有可能在較短時間內完成一輪抓取工作。
它的開發效率是比較快而且簡單的。
20 如何提高爬取效率?
爬蟲下載慢主要原因是阻塞等待發往網站的請求和網站返回
1,采用異步與多線程,擴大電腦的cpu利用率;2,采用消息隊列模式3,提高帶寬21 說說什么是爬蟲協議?
Robots協議(也稱為爬蟲協議、爬蟲規則、機器人協議等)也就是robots.txt,網站通過robots協議告訴搜索引擎哪些頁面可以抓取,哪些頁面不能抓取。
Robots協議是網站國際互聯網界通行的道德規范,其目的是保護網站數據和敏感信息、確保用戶個人信息和隱私不被侵犯。因其不是命令,故需要搜索引擎自覺遵守。
22 如果對方網站反爬取,封IP了怎么辦?
23 有一個jsonline格式的文件file
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' def get_lines():with open('file.txt','rb') as f:return f.readlines()if __name__ == '__main__':for e in get_lines():process(e) # 處理每一行數據現在要處理一個大小為10G的文件,但是內存只有4G,如果在只修改get_lines 函數而其他代碼保持不變的情況下,應該如何實現?需要考慮的問題都有那些?
def get_lines():with open('file.txt','rb') as f:for i in f:yield iPandaaaa906提供的方法
from mmap import mmapdef get_lines(fp):with open(fp,"r+") as f:m = mmap(f.fileno(), 0)tmp = 0for i, char in enumerate(m):if char==b"\n":yield m[tmp:i+1].decode()tmp = i+1if __name__=="__main__":for i in get_lines("fp_some_huge_file"):print(i)要考慮的問題有:內存只有4G無法一次性讀入10G文件,需要分批讀入分批讀入數據要記錄每次讀入數據的位置。分批每次讀取數據的大小,太小會在讀取操作花費過多時間。
https://stackoverflow.com/questions/30294146/python-fastest-way-to-process-large-file
24 補充缺失的代碼
def print_directory_contents(sPath): """ 這個函數接收文件夾的名稱作為輸入參數 返回該文件夾中文件的路徑 以及其包含文件夾中文件的路徑 遇到問題沒人解答? 小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! """ import os for s_child in os.listdir(s_path):s_child_path = os.path.join(s_path, s_child)if os.path.isdir(s_child_path):print_directory_contents(s_child_path)else:print(s_child_path)25 輸入日期, 判斷這一天是這一年的第幾天?
import datetime def dayofyear():year = input("請輸入年份: ")month = input("請輸入月份: ")day = input("請輸入天: ")date1 = datetime.date(year=int(year),month=int(month),day=int(day))date2 = datetime.date(year=int(year),month=1,day=1)return (date1-date2).days+126 打亂一個排好序的list對象alist?
import random alist = [1,2,3,4,5] random.shuffle(alist) print(alist)27 現有字典 d= {‘a’:24,‘g’:52,‘i’:12,‘k’:33}請按value值進行排序?
sorted(d.items(),key=lambda x:x[1])28 字典推導式
d = {key:value for (key,value) in iterable}29 請反轉字符串 “aStr”?
print("aStr"[::-1])30 將字符串 “k:1 |k1:2|k2:3|k3:4”,處理成字典
str1 = "k:1|k1:2|k2:3|k3:4" def str2dict(str1):dict1 = {}for iterms in str1.split('|'):key,value = iterms.split(':')dict1[key] = valuereturn dict1 #字典推導式 d = {k:int(v) for t in str1.split("|") for k, v in (t.split(":"), )}31 請按alist中元素的age由大到小排序
alist = [{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}] def sort_by_age(list1):return sorted(alist,key=lambda x:x['age'],reverse=True)32 下面代碼的輸出結果將是什么?
list = ['a','b','c','d','e'] print(list[10:])代碼將輸出[],不會產生IndexError錯誤,就像所期望的那樣,嘗試用超出成員的個數的index來獲取某個列表的成員。例如,嘗試獲取list[10]和之后的成員,會導致IndexError。然而,嘗試獲取列表的切片,開始的index超過了成員個數不會產生IndexError,而是僅僅返回一個空列表。這成為特別讓人惡心的疑難雜癥,因為運行的時候沒有錯誤產生,導致Bug很難被追蹤到。
33 寫一個列表生成式,產生一個公差為11的等差數列
print([x*11 for x in range(10)])34 給定兩個列表,怎么找出他們相同的元素和不同的元素?
list1 = [1,2,3] list2 = [3,4,5] set1 = set(list1) set2 = set(list2) print(set1 & set2) print(set1 ^ set2)35 請寫出一段python代碼實現刪除list里面的重復元素?
l1 = ['b','c','d','c','a','a'] l2 = list(set(l1)) print(l2)用list類的sort方法:
l1 = ['b','c','d','c','a','a'] l2 = list(set(l1)) l2.sort(key=l1.index) print(l2)也可以這樣寫:
l1 = ['b','c','d','c','a','a'] l2 = sorted(set(l1),key=l1.index) print(l2)也可以用遍歷:
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' l1 = ['b','c','d','c','a','a'] l2 = [] for i in l1:if not i in l2:l2.append(i) print(l2)36 給定兩個list A,B ,請用找出A,B中相同與不同的元素
A,B 中相同元素:print(set(A)&set(B)) A,B 中不同元素: print(set(A)^set(B))37 python新式類和經典類的區別?
a. 在python里凡是繼承了object的類,都是新式類
b. Python3里只有新式類
c. Python2里面繼承object的是新式類,沒有寫父類的是經典類
d. 經典類目前在Python里基本沒有應用
38 python中內置的數據結構有幾種?
a. 整型 int、 長整型 long、浮點型 float、 復數 complex
b. 字符串 str、 列表 list、 元祖 tuple
c. 字典 dict 、 集合 set
d. Python3 中沒有 long,只有無限精度的 int
39 python如何實現單例模式?請寫出兩種實現方式?
第一種方法:使用裝飾器
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' def singleton(cls):instances = {}def wrapper(*args, **kwargs):if cls not in instances:instances[cls] = cls(*args, **kwargs)return instances[cls]return wrapper@singleton class Foo(object):pass foo1 = Foo() foo2 = Foo() print(foo1 is foo2) # True第二種方法:使用基類
New 是真正創建實例對象的方法,所以重寫基類的new 方法,以此保證創建對象的時候只生成一個實例
第三種方法:元類,元類是用于創建類對象的類,類對象創建實例對象時一定要調用call方法,因此在調用call時候保證始終只創建一個實例即可,type是python的元類
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' class Singleton(type):def __call__(cls, *args, **kwargs):if not hasattr(cls, '_instance'):cls._instance = super(Singleton, cls).__call__(*args, **kwargs)return cls._instance# Python2 class Foo(object):__metaclass__ = Singleton# Python3 class Foo(metaclass=Singleton):passfoo1 = Foo() foo2 = Foo() print(foo1 is foo2) # True40 反轉一個整數,例如-123 --> -321
class Solution(object):def reverse(self,x):if -10<x<10:return xstr_x = str(x)if str_x[0] !="-":str_x = str_x[::-1]x = int(str_x)else:str_x = str_x[1:][::-1]x = int(str_x)x = -xreturn x if -2147483648<x<2147483647 else 0 if __name__ == '__main__':s = Solution()reverse_int = s.reverse(-120)print(reverse_int)41 設計實現遍歷目錄與子目錄,抓取.pyc文件?
第一種方法:
import osdef get_files(dir,suffix):res = []for root,dirs,files in os.walk(dir):for filename in files:name,suf = os.path.splitext(filename)if suf == suffix:res.append(os.path.join(root,filename))print(res)get_files("./",'.pyc')第二種方法:
import osdef pick(obj):if ob.endswith(".pyc"):print(obj)def scan_path(ph):file_list = os.listdir(ph)for obj in file_list:if os.path.isfile(obj):pick(obj)elif os.path.isdir(obj):scan_path(obj)if __name__=='__main__':path = input('輸入目錄')scan_path(path)第三種方法
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' from glob import iglobdef func(fp, postfix):for i in iglob(f"{fp}/**/*{postfix}", recursive=True):print(i)if __name__ == "__main__":postfix = ".pyc"func("K:\Python_script", postfix)42 Python-遍歷列表時刪除元素的正確做法
遍歷在新在列表操作,刪除時在原來的列表操作
a = [1,2,3,4,5,6,7,8] print(id(a)) print(id(a[:])) for i in a[:]:if i>5:passelse:a.remove(i)print(a) print('-----------') print(id(a)) #filter a=[1,2,3,4,5,6,7,8] b = filter(lambda x: x>5,a) print(list(b))列表解析
a=[1,2,3,4,5,6,7,8] b = [i for i in a if i>5] print(b)倒序刪除
因為列表總是‘向前移’,所以可以倒序遍歷,即使后面的元素被修改了,還沒有被遍歷的元素和其坐標還是保持不變的
43 字符串的操作題目
全字母短句 PANGRAM 是包含所有英文字母的句子,比如:A QUICK BROWN FOX JUMPS OVER THE LAZY DOG. 定義并實現一個方法 get_missing_letter, 傳入一個字符串采納數,返回參數字符串變成一個 PANGRAM 中所缺失的字符。應該忽略傳入字符串參數中的大小寫,返回應該都是小寫字符并按字母順序排序(請忽略所有非 ACSII 字符)
下面示例是用來解釋,雙引號不需要考慮:
(0)輸入: “A quick brown for jumps over the lazy dog”
返回:""
(1)輸入: “A slow yellow fox crawls under the proactive dog”
返回: “bjkmqz”
(2)輸入: “Lions, and tigers, and bears, oh my!”
返回: “cfjkpquvwxz”
(3)輸入: “”
返回:“abcdefghijklmnopqrstuvwxyz”
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' def get_missing_letter(a):s1 = set("abcdefghijklmnopqrstuvwxyz")s2 = set(a)ret = "".join(sorted(s1-s2))return retprint(get_missing_letter("python"))44 可變類型和不可變類型
1,可變類型有list,dict.不可變類型有string,number,tuple.
2,當進行修改操作時,可變類型傳遞的是內存中的地址,也就是說,直接修改內存中的值,并沒有開辟新的內存。
3,不可變類型被改變時,并沒有改變原內存地址中的值,而是開辟一塊新的內存,將原地址中的值復制過去,對這塊新開辟的內存中的值進行操作。
45 is和==有什么區別?
is:比較的是兩個對象的id值是否相等,也就是比較倆對象是否為同一個實例對象。是否指向同一個內存地址
== :比較的兩個對象的內容/值是否相等,默認會調用對象的eq()方法
46 求出列表所有奇數并構造新列表
a = [1,2,3,4,5,6,7,8,9,10] res = [ i for i in a if i%2==1] print(res)47 用一行python代碼寫出1+2+3+10248
from functools import reduce #1.使用sum內置求和函數 num = sum([1,2,3,10248]) print(num) #2.reduce 函數 num1 = reduce(lambda x,y :x+y,[1,2,3,10248]) print(num1)48 Python中變量的作用域?(變量查找順序)
函數作用域的LEGB順序
1.什么是LEGB?
L:local 函數內部作用域
E: enclosing 函數內部與內嵌函數之間
G: global 全局作用域
B:build-in 內置作用
python在函數里面的查找分為4種,稱之為LEGB,也正是按照這是順序來查找的
49 字符串 "123" 轉換成 123,不使用內置api,例如 int()
方法一:利用 str 函數
def atoi(s):num = 0for v in s:for j in range(10):if v == str(j):num = num * 10 + jreturn num方法二:利用 ord 函數
def atoi(s):num = 0for v in s:num = num * 10 + ord(v) - ord('0')return num方法三: 利用 eval 函數
def atoi(s):num = 0for v in s:t = "%s * 1" % vn = eval(t)num = num * 10 + nreturn num方法四: 結合方法二,使用 reduce,一行解決
from functools import reduce def atoi(s):return reduce(lambda num, v: num * 10 + ord(v) - ord('0'), s, 0)50 Given an array of integers
給定一個整數數組和一個目標值,找出數組中和為目標值的兩個數。你可以假設每個輸入只對應一種答案,且同樣的元素不能被重復利用。示例:給定nums = [2,7,11,15],target=9 因為 nums[0]+nums[1] = 2+7 =9,所以返回[0,1]
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' class Solution:def twoSum(self,nums,target):""":type nums: List[int]:type target: int:rtype: List[int]"""d = {}size = 0while size < len(nums):if target-nums[size] in d:if d[target-nums[size]] <size:return [d[target-nums[size]],size]else:d[nums[size]] = sizesize = size +1 solution = Solution() list = [2,7,11,15] target = 9 nums = solution.twoSum(list,target) print(nums)給列表中的字典排序:假設有如下list對象,alist=[{“name”:“a”,“age”:20},{“name”:“b”,“age”:30},{“name”:“c”,“age”:25}],將alist中的元素按照age從大到小排序 alist=[{“name”:“a”,“age”:20},{“name”:“b”,“age”:30},{“name”:“c”,“age”:25}]
alist_sort = sorted(alist,key=lambda e: e.__getitem__('age'),reverse=True)51 python代碼實現刪除一個list里面的重復元素
def distFunc1(a):"""使用集合去重"""a = list(set(a))print(a)def distFunc2(a):"""將一個列表的數據取出放到另一個列表中,中間作判斷"""list = []for i in a:if i not in list:list.append(i)#如果需要排序的話用sortlist.sort()print(list)def distFunc3(a):"""使用字典"""b = {}b = b.fromkeys(a)c = list(b.keys())print(c)if __name__ == "__main__":a = [1,2,4,2,4,5,7,10,5,5,7,8,9,0,3]distFunc1(a)distFunc2(a)distFunc3(a)52 統計一個文本中單詞頻次最高的10個單詞?
import re# 方法一 def test(filepath):distone = {}with open(filepath) as f:for line in f:line = re.sub("\W+", " ", line)lineone = line.split()for keyone in lineone:if not distone.get(keyone):distone[keyone] = 1else:distone[keyone] += 1num_ten = sorted(distone.items(), key=lambda x:x[1], reverse=True)[:10]num_ten =[x[0] for x in num_ten]return num_ten# 方法二 # 使用 built-in 的 Counter 里面的 most_common import re from collections import Counterdef test2(filepath):with open(filepath) as f:return list(map(lambda c: c[0], Counter(re.sub("\W+", " ", f.read()).split()).most_common(10)))53 請寫出一個函數滿足以下條件
該函數的輸入是一個僅包含數字的list,輸出一個新的list,其中每一個元素要滿足以下條件:
1、該元素是偶數
2、該元素在原list中是在偶數的位置(index是偶數)
def num_list(num):return [i for i in num if i %2 ==0 and num.index(i)%2==0]num = [0,1,2,3,4,5,6,7,8,9,10] result = num_list(num) print(result)54 使用單一的列表生成式來產生一個新的列表
該列表只包含滿足以下條件的值,元素為原始列表中偶數切片
list_data = [1,2,5,8,10,3,18,6,20] res = [x for x in list_data[::2] if x %2 ==0] print(res)55 用一行代碼生成[1,4,9,16,25,36,49,64,81,100]
[x * x for x in range(1,11)]56 輸入某年某月某日,判斷這一天是這一年的第幾天?
import datetimey = 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))57 兩個有序列表,l1,l2,對這兩個列表進行合并不可使用extend
def loop_merge_sort(l1,l2):tmp = []while len(l1)>0 and len(l2)>0:if l1[0] <l2[0]:tmp.append(l1[0])del l1[0]else:tmp.append(l2[0])del l2[0]while len(l1)>0:tmp.append(l1[0])del l1[0]while len(l2)>0:tmp.append(l2[0])del l2[0]return tmp58 給定一個任意長度數組,實現一個函數
讓所有奇數都在偶數前面,而且奇數升序排列,偶數降序排序,如字符串’1982376455’,變成’1355798642’
# 方法一 def func1(l):if isinstance(l, str):l = [int(i) for i in l]l.sort(reverse=True)for i in range(len(l)):if l[i] % 2 > 0:l.insert(0, l.pop(i))print(''.join(str(e) for e in l))# 方法二 def func2(l):print("".join(sorted(l, key=lambda x: int(x) % 2 == 0 and 20 - int(x) or int(x))))59 寫一個函數找出一個整數數組中,第二大的數
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' def find_second_large_num(num_list):"""找出數組第2大的數字"""# 方法一# 直接排序,輸出倒數第二個數即可tmp_list = sorted(num_list)print("方法一\nSecond_large_num is :", tmp_list[-2])# 方法二# 設置兩個標志位一個存儲最大數一個存儲次大數# two 存儲次大值,one 存儲最大值,遍歷一次數組即可,先判斷是否大于 one,若大于將 one 的值給 two,將 num_list[i] 的值給 one,否則比較是否大于two,若大于直接將 num_list[i] 的值給two,否則passone = num_list[0]two = num_list[0]for i in range(1, len(num_list)):if num_list[i] > one:two = oneone = num_list[i]elif num_list[i] > two:two = num_list[i]print("方法二\nSecond_large_num is :", two)# 方法三# 用 reduce 與邏輯符號 (and, or)# 基本思路與方法二一樣,但是不需要用 if 進行判斷。from functools import reducenum = reduce(lambda ot, x: ot[1] < x and (ot[1], x) or ot[0] < x and (x, ot[1]) or ot, num_list, (0, 0))[0]print("方法三\nSecond_large_num is :", num)if __name__ == '__main___':num_list = [34, 11, 23, 56, 78, 0, 9, 12, 3, 7, 5]find_second_large_num(num_list)60 閱讀一下代碼他們的輸出結果是什么?
def multi():return [lambda x : i*x for i in range(4)] print([m(3) for m in multi()])正確答案是[9,9,9,9],而不是[0,3,6,9]產生的原因是Python的閉包的后期綁定導致的,這意味著在閉包中的變量是在內部函數被調用的時候被查找的,因為,最后函數被調用的時候,for循環已經完成, i 的值最后是3,因此每一個返回值的i都是3,所以最后的結果是[9,9,9,9]
61 統計一段字符串中字符出現的次數
# 方法一 def count_str(str_data):"""定義一個字符出現次數的函數"""dict_str = {} for i in str_data:dict_str[i] = dict_str.get(i, 0) + 1return dict_str dict_str = count_str("AAABBCCAC") str_count_data = "" for k, v in dict_str.items():str_count_data += k + str(v) print(str_count_data)# 方法二 from collections import Counterprint("".join(map(lambda x: x[0] + str(x[1]), Counter("AAABBCCAC").most_common())))62 Python中類方法、類實例方法、靜態方法有何區別?
類方法: 是類對象的方法,在定義時需要在上方使用 @classmethod 進行裝飾,形參為cls,表示類對象,類對象和實例對象都可調用
類實例方法: 是類實例化對象的方法,只有實例對象可以調用,形參為self,指代對象本身;
靜態方法: 是一個任意函數,在其上方使用 @staticmethod 進行裝飾,可以用對象直接調用,靜態方法實際上跟該類沒有太大關系
63 遍歷一個object的所有屬性,并print每一個屬性名?
class Car:def __init__(self,name,loss): # loss [價格,油耗,公里數]self.name = nameself.loss = lossdef getName(self):return self.namedef getPrice(self):# 獲取汽車價格return self.loss[0]def getLoss(self):# 獲取汽車損耗值return self.loss[1] * self.loss[2]Bmw = Car("寶馬",[60,9,500]) # 實例化一個寶馬車對象 print(getattr(Bmw,"name")) # 使用getattr()傳入對象名字,屬性值。 print(dir(Bmw)) # 獲Bmw所有的屬性和方法64 寫一個類,并讓它盡可能多的支持操作符?
class Array:__list = []def __init__(self):print "constructor"def __del__(self):print "destruct"def __str__(self):return "this self-defined array class"def __getitem__(self,key):return self.__list[key]def __len__(self):return len(self.__list)def Add(self,value):self.__list.append(value)def Remove(self,index):del self.__list[index]def DisplayItems(self):print "show all items---"for item in self.__list:print item65 關于Python內存管理,下列說法錯誤的是 B
A,變量不必事先聲明 B,變量無須先創建和賦值而直接使用
C,變量無須指定類型 D,可以使用del釋放資源
66 Python的內存管理機制及調優手段?
內存管理機制: 引用計數、垃圾回收、內存池
引用計數:引用計數是一種非常高效的內存管理手段,當一個Python對象被引用時其引用計數增加1,
當其不再被一個變量引用時則計數減1,當引用計數等于0時對象被刪除。弱引用不會增加引用計數
垃圾回收:
1.引用計數
引用計數也是一種垃圾收集機制,而且也是一種最直觀、最簡單的垃圾收集技術。當Python的某個對象的引用計數降為0時,說明沒有任何引用指向該對象,該對象就成為要被回收的垃圾了。比如某個新建對象,它被分配給某個引用,對象的引用計數變為1,如果引用被刪除,對象的引用計數為0,那么該對象就可以被垃圾回收。不過如果出現循環引用的話,引用計數機制就不再起有效的作用了。
2.標記清除
調優手段
1.手動垃圾回收
2.調高垃圾回收閾值
3.避免循環引用
67 內存泄露是什么?如何避免?
內存泄漏指由于疏忽或錯誤造成程序未能釋放已經不再使用的內存。內存泄漏并非指內存在物理上的消失,而是應用程序分配某段內存后,由于設計錯誤,導致在釋放該段內存之前就失去了對該段內存的控制,從而造成了內存的浪費。
有__del__()函數的對象間的循環引用是導致內存泄露的主兇。不使用一個對象時使用: del object 來刪除一個對象的引用計數就可以有效防止內存泄露問題。
通過Python擴展模塊gc 來查看不能回收的對象的詳細信息。
可以通過 sys.getrefcount(obj) 來獲取對象的引用計數,并根據返回值是否為0來判斷是否內存泄露
68 python常見的列表推導式?
[表達式 for 變量 in 列表] 或者 [表達式 for 變量 in 列表 if 條件]
69 簡述read、readline、readlines的區別?
read 讀取整個文件
readline 讀取下一行
readlines 讀取整個文件到一個迭代器以供我們遍歷
70 什么是Hash(散列函數)?
散列函數(英語:Hash function)又稱散列算法、哈希函數,是一種從任何一種數據中創建小的數字“指紋”的方法。散列函數把消息或數據壓縮成摘要,使得數據量變小,將數據的格式固定下來。該函數將數據打亂混合,重新創建一個叫做散列值(hash values,hash codes,hash sums,或hashes)的指紋。散列值通常用一個短的隨機字母和數字組成的字符串來代表
71 python函數重載機制?
函數重載主要是為了解決兩個問題。
1。可變參數類型。
2。可變參數個數。
另外,一個基本的設計原則是,僅僅當兩個函數除了參數類型和參數個數不同以外,其功能是完全相同的,此時才使用函數重載,如果兩個函數的功能其實不同,那么不應當使用重載,而應當使用一個名字不同的函數。
好吧,那么對于情況 1 ,函數功能相同,但是參數類型不同,python 如何處理?答案是根本不需要處理,因為 python 可以接受任何類型的參數,如果函數的功能相同,那么不同的參數類型在 python 中很可能是相同的代碼,沒有必要做成兩個不同函數。
那么對于情況 2 ,函數功能相同,但參數個數不同,python 如何處理?大家知道,答案就是缺省參數。對那些缺少的參數設定為缺省參數即可解決問題。因為你假設函數功能相同,那么那些缺少的參數終歸是需要用的。
好了,鑒于情況 1 跟 情況 2 都有了解決方案,python 自然就不需要函數重載了。
72 手寫一個判斷時間的裝飾器
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' import datetimeclass TimeException(Exception):def __init__(self, exception_info):super().__init__()self.info = exception_infodef __str__(self):return self.infodef timecheck(func):def wrapper(*args, **kwargs):if datetime.datetime.now().year == 2019:func(*args, **kwargs)else:raise TimeException("函數已過時")return wrapper@timecheck def test(name):print("Hello {}, 2019 Happy".format(name))if __name__ == "__main__":test("backbp")73 使用Python內置的filter()方法來過濾?
list(filter(lambda x: x % 2 == 0, range(10)))74 編寫函數的4個原則
1.函數設計要盡量短小
2.函數聲明要做到合理、簡單、易于使用
3.函數參數設計應該考慮向下兼容
4.一個函數只做一件事情,盡量保證函數語句粒度的一致性
75 函數調用參數的傳遞方式是值傳遞還是引用傳遞?
Python的參數傳遞有:位置參數、默認參數、可變參數、關鍵字參數。
函數的傳值到底是值傳遞還是引用傳遞、要分情況:
不可變參數用值傳遞:像整數和字符串這樣的不可變對象,是通過拷貝進行傳遞的,因為你無論如何都不可能在原處改變不可變對象。
可變參數是引用傳遞:比如像列表,字典這樣的對象是通過引用傳遞、和C語言里面的用指針傳遞數組很相似,可變對象能在函數內部改變。
76 如何在function里面設置一個全局變量
globals() # 返回包含當前作用余全局變量的字典。 global 變量 設置使用全局變量77 對缺省參數的理解 ?
缺省參數指在調用函數的時候沒有傳入參數的情況下,調用默認的參數,在調用函數的同時賦值時,所傳入的參數會替代默認參數。
*args是不定長參數,它可以表示輸入參數是不確定的,可以是任意多個。
**kwargs是關鍵字參數,賦值的時候是以鍵值對的方式,參數可以是任意多對在定義函數的時候
不確定會有多少參數會傳入時,就可以使用兩個參數
78 帶參數的裝飾器?
帶定長參數的裝飾器
def new_func(func):def wrappedfun(username, passwd):if username == 'root' and passwd == '123456789':print('通過認證')print('開始執行附加功能')return func()else:print('用戶名或密碼錯誤')returnreturn wrappedfun@new_func def origin():print('開始執行函數') origin('root','123456789')帶不定長參數的裝飾器
def new_func(func):def wrappedfun(*parts):if parts:counts = len(parts)print('本系統包含 ', end='')for part in parts:print(part, ' ',end='')print('等', counts, '部分')return func()else:print('用戶名或密碼錯誤')return func()return wrappedfun79 為什么函數名字可以當做參數用?
Python中一切皆對象,函數名是函數在內存中的空間,也是一個對象
80 Python中pass語句的作用是什么?
在編寫代碼時只寫框架思路,具體實現還未編寫就可以用pass進行占位,是程序不報錯,不會進行任何操作。
81 有這樣一段代碼,print c會輸出什么,為什么?
a = 10 b = 20 c = [a] a = 15答:10對于字符串,數字,傳遞是相應的值
82 交換兩個變量的值?
a, b = b, a83 map函數和reduce函數?
map(lambda x: x * x, [1, 2, 3, 4]) # 使用 lambda # [1, 4, 9, 16] reduce(lambda x, y: x * y, [1, 2, 3, 4]) # 相當于 ((1 * 2) * 3) * 4 # 2484 回調函數,如何通信的?
回調函數是把函數的指針(地址)作為參數傳遞給另一個函數,將整個函數當作一個對象,賦值給調用的函數。
85 Python主要的內置數據類型都有哪些?print dir( ‘a ’) 的輸出?
內建類型:布爾類型,數字,字符串,列表,元組,字典,集合
輸出字符串’a’的內建方法
86 map(lambda x:xx,[y for y in range(3)])的輸出?
[0, 1, 4]87 hasattr() getattr() setattr() 函數使用詳解?
hasattr(object,name)函數:
判斷一個對象里面是否有name屬性或者name方法,返回bool值,有name屬性(方法)返回True,否則返回False。
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' 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)getattr(object, name[,default])函數:
獲取對象object的屬性或者方法,如果存在則打印出來,如果不存在,打印默認值,默認值可選。注意:如果返回的是對象的方法,則打印結果是:方法的內存地址,如果需要運行這個方法,可以在后面添加括號().
functiondemo = function_demo() getattr(functiondemo, "name")# 獲取name屬性,存在就打印出來 --- demo getattr(functiondemo, "run") # 獲取run 方法,存在打印出方法的內存地址 getattr(functiondemo, "age") # 獲取不存在的屬性,報錯 getattr(functiondemo, "age", 18)# 獲取不存在的屬性,返回一個默認值setattr(object, name, values)函數:
給對象的屬性賦值,若屬性不存在,先創建再賦值
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綜合使用
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", "北京首都"))print(addr)88 一句話解決階乘函數?
reduce(lambda x,y : x*y,range(1,n+1))89 對設計模式的理解,簡述你了解的設計模式?
設計模式是經過總結,優化的,對我們經常會碰到的一些編程問題的可重用解決方案。一個設計模式并不像一個類或一個庫那樣能夠直接作用于我們的代碼,反之,設計模式更為高級,它是一種必須在特定情形下實現的一種方法模板。
常見的是工廠模式和單例模式
90 請手寫一個單例
#python2 class A(object):__instance = Nonedef __new__(cls,*args,**kwargs):if cls.__instance is None:cls.__instance = objecet.__new__(cls)return cls.__instanceelse:return cls.__instance91 單例模式的應用場景有那些?
單例模式應用的場景一般發現在以下條件下:
資源共享的情況下,避免由于資源操作時導致的性能或損耗等,如日志文件,應用配置。
控制資源的情況下,方便資源之間的互相通信。如線程池等,1,網站的計數器 2,應用配置 3.多線程池 4數據庫配置 數據庫連接池 5.應用程序的日志應用…
92 用一行代碼生成[1,4,9,16,25,36,49,64,81,100]
print([x*x for x in range(1, 11)])93 對裝飾器的理解,并寫出一個計時器記錄方法執行性能的裝飾器?
裝飾器本質上是一個callable object ,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值也是一個函數對象。
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴, 互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' import time from functools import wrapsdef timeit(func):@wraps(func)def wrapper(*args, **kwargs):start = time.clock()ret = func(*args, **kwargs)end = time.clock()print('used:',end-start)return retreturn wrapper @timeit def foo():print('in foo()'foo())94 解釋以下什么是閉包?
在函數內部再定義一個函數,并且這個函數用到了外邊函數的變量,那么將這個函數以及用到的一些變量稱之為閉包。
95 函數裝飾器有什么作用?
裝飾器本質上是一個callable object,它可以在讓其他函數在不需要做任何代碼的變動的前提下增加額外的功能。裝飾器的返回值也是一個函數的對象,它經常用于有切面需求的場景。比如:插入日志,性能測試,事務處理,緩存。權限的校驗等場景,有了裝飾器就可以抽離出大量的與函數功能本身無關的雷同代碼并發并繼續使用。
詳細參考:https://manjusaka.itscoder.com/2018/02/23/something-about-decorator/
96 生成器,迭代器的區別?
迭代器是遵循迭代協議的對象。用戶可以使用 iter() 以從任何序列得到迭代器(如 list, tuple, dictionary, set 等)。另一個方法則是創建一個另一種形式的迭代器 —— generator 。要獲取下一個元素,則使用成員函數 next()(Python 2)或函數 next() function (Python 3) 。當沒有元素時,則引發 StopIteration 此例外。若要實現自己的迭代器,則只要實現 next()(Python 2)或 __next__()( Python 3)
生成器(Generator),只是在需要返回數據的時候使用yield語句。每次next()被調用時,生成器會返回它脫離的位置(它記憶語句最后一次執行的位置和所有的數據值)
區別:生成器能做到迭代器能做的所有事,而且因為自動創建iter()和next()方法,生成器顯得特別簡潔,而且生成器也是高效的,使用生成器表達式取代列表解析可以同時節省內存。除了創建和保存程序狀態的自動方法,當發生器終結時,還會自動拋出StopIteration異常。
97 X是什么類型?
X= (i for i in range(10))
X是 generator類型
98 請用一行代碼 實現將1-N 的整數列表以3為單位分組
N =100 print ([[x for x in range(1,100)] [i:i+3] for i in range(0,100,3)])99 Python中yield的用法?
yield就是保存當前程序執行狀態。你用for循環的時候,每次取一個元素的時候就會計算一次。用yield的函數叫generator,和iterator一樣,它的好處是不用一次計算所有元素,而是用一次算一次,可以節省很多空間,generator每次計算需要上一次計算結果,所以用yield,否則一return,上次計算結果就沒了
總結
以上是生活随笔為你收集整理的2019 Python100道 面试 题,你会几道?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python range()的解释和可视
- 下一篇: 使用 ctypes 将 Python 运