python面試看這一篇就夠了

python-面試通關寶典

有面Python開發方向的,看這一個repo就夠啦?php

語言特性

1.談談對 Python 和其餘語言的區別css

Python屬於解釋型語言,當程序運行時,是一行一行的解釋,並運行,因此調式代碼很方便,開發效率高,
還有龜叔給Python定位是任其自由發展、優雅、明確、簡單,因此在每一個領域都有建樹,全部它有着很是強大的第三方庫,
特色:
語法簡潔優美,功能強大,標準庫與第三方庫都很是強大,並且應用領域也很是廣
可移植性,可擴展性,可嵌入性
缺點:
  運行速度慢,

- 解釋型
    - python/php
- 編譯型
    - c/java/c#
        
- Python弱類型

2.簡述解釋型和編譯型編程語言html

解釋型:就是邊解釋邊執行(Python,php)
編譯型:編譯後再執行(c、java、c#)

3.Python 的解釋器種類以及相關特色?java

CPython

是官方版本的解釋器:CPython。是使用C語言開發的,因此叫CPython。在命令行下運行python就是啓動CPython解釋器。
CPython是使用最廣的Python解釋器。教程的全部代碼也都在CPython下執行。

IPython
IPython是基於CPython之上的一個交互式解釋器,也就是說,IPython只是在交互方式上有所加強,可是執行Python代碼的功能和CPython是徹底同樣的。CPython用>>>做爲提示符,而IPython用In [序號]:做爲提示符。
PyPy

由Python寫的解釋器,它的執行速度是最快。PyPy採用JIT技術,對Python代碼進行動態編譯(注意不是解釋),
絕大部分Python代碼均可以在PyPy下運行,可是PyPy和CPython有一些是不一樣的,這就致使相同的Python代碼在兩種解釋器下執行可能會有不一樣的結果。

Jython
Jython是運行在Java平臺上的Python解釋器,能夠直接把Python代碼編譯成Java字節碼執行。

IronPython
IronPython和Jython相似,只不過IronPython是運行在.Net平臺上的Python解釋器,能夠直接把Python代碼編譯成.Net的字節碼。

小結:
  Python的解釋器不少,但使用最普遍的仍是CPython。若是要和Java或.Net平臺交互,最好的辦法不是用Jython或IronPython,而是經過網絡調用來交互,確保各程序之間的獨立性。

4.說說你知道的Python3 和 Python2 之間的區別?node

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:幾乎是重構後的源碼,規範,清晰,優美。

三、輸出中文的區別
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檢查文件類型

5.Python3 和 Python2 中 int 和 long 區別?python

在python3裏,只有一種整數類型int,大多數狀況下,和python2中的長整型相似。

6.xrange 和 range 的區別?mysql

xrange用法與range徹底相同,所不一樣的是生成的不是一個數組,而是一個生成器。
要生成很大的數字序列的時候,用xrange會比range性能優不少,由於不須要一上來就開闢一塊很大的內存空間,這兩個基本上都是在循環的時候用。

在 Python 3 中,range() 是像 xrange() 那樣實現,xrange()被拋棄。

編碼規範

7.什麼是 PEP8?git

PEP是 Python Enhancement Proposal 的縮寫,翻譯過來就是 Python加強建議書
簡單說就是一種編碼規範,是爲了讓代碼「更好看」,更容易被閱讀
具體可參考:
https://www.python.org/dev/peps/pep-0008/

8.瞭解 Python 之禪麼?程序員

import this

9.瞭解 dosctring 麼?web

Python有一個很奇妙的特性,稱爲 文檔字符串 ,它一般被簡稱爲 docstrings 。DocStrings是一個重要的工具,因爲它幫助你的程序文檔更加簡單易懂,你應該儘可能使用它。你甚至能夠在程序運行的時候,從函數恢復文檔字符串。
使用魔法方法'__doc__'能夠打印docstring的內容

10.瞭解類型註解麼?

def add(x:int, y:int) -> int:
    return x + y
用 : 類型 的形式指定函數的參數類型,用 -> 類型 的形式指定函數的返回值類型

11.例舉你知道 Python 對象的命名規範,例如方法或者類等

類名都使用首字母大寫開頭(Pascal命名風格)的規範;
全局變量全用大寫字母,單詞之間用 _分割;
普通變量用小寫字母,單詞之間用 _分割;
普通函數和普通變量同樣;
私有函數以 __ 開頭(2個下劃線),其餘和普通函數同樣;

12.Python 中的註釋有幾種?

單行註釋,多行註釋,docstring註釋

13.如何優雅的給一個函數加註釋?

在函數邏輯行的首行使用""" xxx """給函數添加註釋,註釋中可包含函數參數的說明,返回值說明等
def foo(bar):
    """
    This is an example.
    :param bar: explain param bar
    """
    return bar

14.如何給變量加註釋?

參數註釋:以冒號(:)標記
返回值註釋:以 -> 標記
示例:
def add(x:int, y:int) -> int:
    return x + y

15.Python 代碼縮進中是否支持 Tab 鍵和空格混用。

支持,Python 並無強制要求你用Tab縮進或者用空格縮進,但在 PEP8中,建議使用4個空格來縮進

16.是否能夠在一句 import 中導入多個庫?

能夠的
import json,random,requests

17.在給 Py 文件命名的時候須要注意什麼?

全小寫,單詞之間使用下劃線分隔

18.例舉幾個規範 Python 代碼風格的工具

pylint,black,pycharm也帶有pep8的代碼規範工具

數據類型

字符串

19.列舉 Python 中的基本數據類型?

Python3 中有六個標準的數據類型:

Number(數字)
String(字符串)
List(列表)
Tuple(元組)
Set(集合)
Dictionary(字典)
Python3 的六個標準數據類型中:

不可變數據(3 個):Number(數字)、String(字符串)、Tuple(元組);
可變數據(3 個):List(列表)、Dictionary(字典)、Set(集合)。

20.如何區別可變數據類型和不可變數據類型

Python3 的六個標準數據類型中:

不可變數據(3 個):Number(數字)、String(字符串)、Tuple(元組);
可變數據(3 個):List(列表)、Dictionary(字典)、Set(集合)。

21.將"hello world"轉換爲首字母大寫"Hello World"

z = 'hello world'
[s.capitalize() for s in z.split(' ')]

22.如何檢測字符串中只含有數字?

# 分爲兩種狀況
# 1.不包含正負號 +-
a = '32323'
a.isdigit()
# 2.含有正負號
import re
re.match(r'[+-]?\d+$',a)

23.將字符串"ilovechina"進行反轉

s = 'ilovechina'
x = list(s)
x.reverse()
''.join(x)

24.Python 中的字符串格式化方式你知道哪些?

# Python3.6以後的版本提供了三種字符串格式化的方式
# 1. %s佔位符
def foo(name):
  return 'hello %s' % name
# 2. format() 
def foo(name):
  return 'hello {}'.format(name)
# f-string
def foo(name):
  return f'hello {name}'

25.有一個字符串開頭和末尾都有空格,好比「 adabdw 」,要求寫一個函數把這個字符串的先後空格都去掉。

s = " adabdw "
s.strip()

26.獲取字符串」123456「最後的兩個字符。

s = '123456'

print(s[-2:])

27.一個編碼爲 GBK 的字符串 S,要將其轉成 UTF-8 編碼的字符串,應如何操做?

s.encode('utf-8')

28.s=「info:xiaoZhang 33 shandong」,用正則切分字符串輸出[‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]

import re
s="info:xiaoZhang 33 shandong"
re.split(r'[:\s]',s)

27.怎樣將字符串轉換爲小寫?

b = 'HHH'
b.lower()

28.單引號、雙引號、三引號的區別?

s = 'hello'
s= "hello"
單引號與雙引號沒有區別,
三引號能夠用來加註釋,所加註釋可使用__doc__查看

29.a = "你好 中國 ",去除多餘空格只留一個空格。

a = "你好 中國 "
s = ' '.join(a.strip().split())

列表

30.已知 AList = [1,2,3,1,2],對 AList 列表元素去重,寫出具體過程。

a_list = [1,2,3,1,2]
ss = set(a_list)

31.如何實現 「1,2,3」 變成 [「1」,「2」,「3」]

s = "1,2,3"
s.split(',')

32.給定兩個 list,A 和 B,找出相同元素和不一樣元素

# 最直接的方法
list_a = [1,2,3,4,5,6]
list_b = [2,3,6]
same_l = []
not_same = []
for i in list_a:
    if i not in list_b:
        not_same.append(i)
for j in list_b:
    if j not in list_a:
        not_same.append(j)
for x in list_a:
  if x in list_b:
       same_l.append(x)
# 奇技淫巧
list_a = [1,2,3,4,5,6]
list_b = [2,3,6]
set1 = set(list_a)
set2 = set(list_b)
# 相同元素
print(set1&set2)
# 不一樣元素
print(set1^set2)

33.[[1,2],[3,4],[5,6]]一行代碼展開該列表,得出[1,2,3,4,5,6]

mm = [[1,2],[3,4],[5,6]]
[j for a in mm for j in a]

34.合併列表[1,5,7,9]和[2,2,6,8]

a = [1,5,7,9]
b = [2,2,6,8]
# 方法1
a.extend(b)
# 方法2
a[0:0] = b

35.如何打亂一個列表的元素?

import random
a = [1,5,7,9]
random.shuffle(a)

字典

36.字典操做中 del 和 pop 有什麼區別

del 操做刪除鍵值對,不返回值;
pop 操做刪除鍵值對的同時,返回鍵所對應的值。

37.按照字典的內的年齡排序

d1 = [
    {'name':'alice', 'age':38},
    {'name':'bob', 'age':18},
    {'name':'Carl', 'age':28},
]
sorted(d1,key=lambda x:x['age'])

38.請合併下面兩個字典 a = {「A」:1,「B」:2},b = {「C」:3,「D」:4}

# python3合併字典有三種方式
# 1.
a = {'a':1,'b':2}
b = {'c':3,'d':4}
c = {}
c.update(a)
c.update(b)
# 2.
c = dict(a,**b)
# 3.
c = {**a,**b} # 官方推薦這種方式

39.如何使用生成式的方式生成一個字典,寫一段功能代碼。

{x:x*x for x in range(6)}

40.如何把元組(「a」,「b」)和元組(1,2),變爲字典{「a」:1,「b」:2}

a = ('a','b')
b = (1,2)
z=zip(a,b)
c = dict(z)

綜合

41.Python 經常使用的數據結構的類型及其特性?

List,tuple,dict,set是比較經常使用的數據結構,queue,heap,deque,ProrityQueue,multiprocessing.Queue等進階的數據結構類型。特性就去查查吧,寫在這裏太長了。

42.如何將元組(「A」,「B」)和元組(1,2),合併成字典{「A」:1,「B」:2}

a = ('A','B')
b = (1,2)
z=zip(a,b)
c = dict(z)

43.Python 裏面如何實現 tuple 和 list 的轉換?

tuple(list) # tuple轉list
list(tuple) # list 轉tuple

44.咱們知道對於列表可使用切片操做進行部分元素的選擇,那麼如何對生成器類型的對象實現相同的功能呢?

使用自帶的itertools庫進行實現,具體實現方式 itertools.islice(生成器對象,起始位置,結束位置),便可實現切片功能。

45.請將[i for i in range(3)]改爲生成器

(i for i in range(3))

46.a="hello"和 b="你好"編碼成 bytes 類型

a.encode()
b.encode()

47.下面的代碼輸出結果是什麼?

a = (1,2,3,[4,5,6,7],8)
a[2] = 2
報錯,元組是不可變對象,不支持修改

48.下面的代碼輸出的結果是什麼?

a = (1,2,3,[4,5,6,7],8)
a[5] = 2
報錯,元組是不可變對象,下標越界

操做類題目

49.Python 交換兩個變量的值

a,b = b,a

50.在讀文件操做的時候會使用 read、readline 或者 readlines,簡述它們各自的做用

read將整個文本都讀取爲一個字符串,佔用內存大,readline讀取爲一個生成器,支持遍歷和迭代,佔用空間小。readlines將文本讀取爲列表,佔用空間大

51.json 序列化時,能夠處理的數據類型有哪些?如何定製支持 datetime 類型?

字符串、數字(整數和浮點數)、字典、列表、布爾值、None。使用strftime將datetime格式化爲標準字符串類型便可。

52.json 序列化時,默認遇到中文會轉換成 unicode,若是想要保留中文怎麼辦?

使用json.dumps函數時,添加參數ensure_ascii=False,若是想顯示的更美觀,能夠添加indent=2參數,會在每一個key值前添加兩個空格。

53.有兩個磁盤文件 A 和 B,各存放一行字母,要求把這兩個文件中的信息合併(按字母順序排列),輸出到一個新文件 C 中。

with open('A.txt','r') as f:
    a = f.readlines()[0]
with open('B.txt','r') as f:
    b = f.readlines()[0]
    a.extend(b).sort()
with open('C.txt','w') as f:
    for i in a:
        f.write(i)

54.若是當前的日期爲 20190530,要求寫一個函數輸出 N 天后的日期,(好比 N 爲 2,則輸出 20190601)。

import datetime
def getday(n):
    y,m,d = 2019,5,30
    the_date = datetime.datetime(y,m,d)
    result_date = the_date + datetime.timedelta(days=n)
    target_date = result_date.strftime('%Y%m%d')
    return target_date

55.寫一個函數,接收整數參數 n,返回一個函數,函數的功能是把函數的參數和 n 相乘並把結果返回。

def mul(n):
  def wrapper(m):
    return n*m
  return wrapper
    
 # 閉包的基本操做

56.下面代碼會存在什麼問題,如何改進?

def strappend(num):
    str='first'
    for i in range(num):
        str+=str(i)
    return str
  # 將str(i)改成str[i]

57.一行代碼輸出 1-100 之間的全部偶數。

[x for x in range(101) if x %2 ==0]

58.with 語句的做用,寫一段代碼?

# with語句用來管理資源,及時關閉文件等操做,避免資源的泄漏
with open('a.txt','r') as f:
    f.read()

59.python 字典和 json 字符串相互轉化方法

json.dumps()   將Python中的對象轉換爲JSON中的字符串對象
json.loads()   將JSON中的字符串對象轉換爲Python中的對象

60.請寫一個 Python 邏輯,計算一個文件中的大寫字母數量

import re
with open('a.txt','r') as f:
    f_content = f.read()
    len_cap = len(re.compile(r'[A-Z]').findall(f_content))

高級特效

70.函數裝飾器有什麼做用?請列舉說明?

函數裝飾器能夠在不修改原函數的條件下,爲原函數添加額外的功能,例如記錄日誌,運行性能,緩存等
以記錄函數運行時間爲例,實現一個裝飾器
import time
def time_it(func):
    def wrapper(func):
        start_time = time.time()
        res = func()
        end_time = time.time()
        return start_time - end_time
    return wrapper

71.Python 垃圾回收機制?

引用計數機制:
python裏每個東西都是對象,它們的核心就是一個結構體:PyObject
 typedef struct_object {
 int ob_refcnt;
 struct_typeobject *ob_type;
} PyObject;

PyObject是每一個對象必有的內容,其中ob_refcnt就是作爲引用計數。當一個對象有新的引用時,它的ob_refcnt就會增長,當引用它的對象被刪除,它的ob_refcnt就會減小
#define Py_INCREF(op) ((op)->ob_refcnt++) //增長計數
#define Py_DECREF(op) \ //減小計數
    if (--(op)->ob_refcnt != 0) \
        ; \
    else \
        __Py_Dealloc((PyObject *)(op))

當引用計數爲0時,該對象生命就結束了。
引用計數機制的優勢:

簡單
實時性:一旦沒有引用,內存就直接釋放了。不用像其餘機制等到特定時機。實時性還帶來一個好處:處理回收內存的時間分攤到了平時

72.魔法函數 __call__怎麼使用?

class Bar:
    def __call__(self, *args, **kwargs):
        print('i am instance method')

b = Bar()  # 實例化
b()  # 實例對象b 能夠做爲函數調用 等同於b.__call__ 使用


# OUT: i am instance method



# 帶參數的類裝飾器
class Bar:

    def __init__(self, p1):
        self.p1 = p1

    def __call__(self, func):
        def wrapper():
            print("Starting", func.__name__)
            print("p1=", self.p1)
            func()
            print("Ending", func.__name__)
        return wrapper


@Bar("foo bar")
def hello():
    print("Hello")

73.如何判斷一個對象是函數仍是方法?

判斷對象是函數或方法應該使用type(obj)

74.@classmethod 和@staticmethod 用法和區別

通常來講,要使用某個類的方法,須要先實例化一個對象再調用方法。

而使用@staticmethod或@classmethod,就能夠不須要實例化,直接類名.方法名()來調用。

這有利於組織代碼,把某些應該屬於某個類的函數給放到那個類裏去,同時有利於命名空間的整潔。



既然@staticmethod和@classmethod均可以直接類名.方法名()來調用,那他們有什麼區別呢

從它們的使用上來看,
@staticmethod不須要表示自身對象的self和自身類的cls參數,就跟使用函數同樣。
@classmethod也不須要self參數,但第一個參數須要是表示自身類的cls參數。
若是在@staticmethod中要調用到這個類的一些屬性方法,只能直接類名.屬性名或類名.方法名。

而@classmethod由於持有cls參數,能夠來調用類的屬性,類的方法,實例化對象等,避免硬編碼
class A(object):
    bar = 1
    def foo(self):
        print 'foo'
 
    @staticmethod
    def static_foo():
        print 'static_foo'
        print A.bar
 
    @classmethod
    def class_foo(cls):
        print 'class_foo'
        print cls.bar
        cls().foo()
 
A.static_foo()
A.class_foo()

75.Python 中的接口如何實現?

#抽象類加抽象方法就等於面向對象編程中的接口
from abc import ABCMeta,abstractmethod

class interface(object):
    __metaclass__ = ABCMeta #指定這是一個抽象類
    @abstractmethod  #抽象方法
    def Lee(self):
        pass

    def Marlon(self):
        pass


class RelalizeInterfaceLee(interface):#必須實現interface中的全部函數,不然會編譯錯誤
    def __init__(self):    
        print '這是接口interface的實現'
    def Lee(self):
        print '實現Lee功能'        
    def Marlon(self):
        pass

76.Python 中的反射了解麼?

經過字符串映射object對象的方法或者屬性
hasattr(obj,name_str): 判斷objec是否有name_str這個方法或者屬性
getattr(obj,name_str): 獲取object對象中與name_str同名的方法或者函數
setattr(obj,name_str,value):object對象設置一個以name_str爲名的value方法或者屬性
delattr(obj,name_str): 刪除object對象中的name_str方法或者屬性

舉個栗子
import requests

class Http(object):


    def get(self,url):
        res = requests.get(url)
        response = res.text
        return response

    def post(self,url):
        res = requests.post(url)
        response = res.text
        return response

# 使用反射後
url = "https://www.jianshu.com/u/14140bf8f6c7"
method = input("請求方法>>>:")
h = Http()

if hasattr(h,method):
    func = getattr(h,method)
    res = func(url)
    print(res)
else:
    print("你的請求方式有誤...")

77.metaclass 做用?以及應用場景?

metaclass我沒怎麼用過,不能亂說誤人子弟,能夠看下這篇博文https://www.cnblogs.com/xybaby/p/7927407.html

78.hasattr() getattr() setattr()的用法

hasattr(obj,name_str): 判斷objec是否有name_str這個方法或者屬性
getattr(obj,name_str): 獲取object對象中與name_str同名的方法或者函數
setattr(obj,name_str,value):object對象設置一個以name_str爲名的value方法或者屬性
delattr(obj,name_str): 刪除object對象中的name_str方法或者屬性

79.請列舉你知道的 Python 的魔法方法及用途。

1. __call__:容許一個類的實例像函數同樣被調用。實質上說,這意味着 x() 與 x._call_() 是相同的
2.__init__:顯示初始化屬性
3.__str__,__repr__,定義類的時候,重寫這兩個方法可讓類更清晰
再就是__setattr__,__getattr__,__delattr__等等

80.如何知道一個 Python 對象的類型?

type(obj)

81.Python 的傳參是傳值仍是傳址?

說傳值或者傳引用都不許確。非要安一個確切的叫法的話,叫傳對象(call by object)
具體能夠參考這篇文章:https://foofish.net/python-function-args.html

82.Python 中的元類(metaclass)使用舉例

參考77.

83.簡述 any()和 all()方法

#any(x)判斷x對象是否爲空對象,若是都爲空、0、false,則返回false,若是不都爲空、0、false,則返回true

#all(x)若是all(x)參數x對象的全部元素不爲0、''、False或者x爲空對象,則返回True,不然返回False
>>> any('123')
True
>>> any([0,1])
True
>>> any([0,'0',''])
True
>>> any([0,''])
False
>>> any([0,'','false'])
True
>>> any([0,'',bool('false')])
True
>>> any([0,'',False])
False
>>> any(('a','b','c'))
True
>>> any(('a','b',''))
True
>>> any((0,False,''))
False
>>> any([])
False
>>> any(())
False
>>> all(['a', 'b', 'c', 'd'])  #列表list,
True
>>> all(['a', 'b', 'c', 'd'])  #列表list,元素都不爲空或0
True
>>> all(['a', 'b', '', 'd'])  #列表list,存在一個爲空的元素
False
>>> all([0, 1,2, 3])  #列表list,存在一個爲0的元素
False
>>> all(('a', 'b', 'c', 'd'))  #元組tuple,元素都不爲空或0
True
>>> all(('a', 'b', '', 'd'))  #元組tuple,存在一個爲空的元素
False
>>> all((0, 1,2, 3))  #元組tuple,存在一個爲0的元素
False
>>> all([]) # 空列表
True
>>> all(()) # 空元組
True
>>> #注意:空元組、空列表返回值爲True,這裏要特別注意

84.filter 方法求出列表全部奇數並構造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

list(filter(lambda x: x%2==1,a))

85.什麼是猴子補丁?

猴子補丁是一個概念,不是python中發明的,其餘動態語言也有這麼個概念。 《松本行弘的程序世界》這本書,裏面專門有一章講了猴子補丁的設計,所謂的猴子補丁的含義是指在動態語言中,不去改變源碼而對功能進行追加和變動

86.在 Python 中是如何管理內存的?

參考71.

87.當退出 Python 時是否釋放全部內存分配?

答案是否認的。那些具備對象循環引用或者全局命名空間引用的變量,在 Python 退出是每每不會被釋放

另外不會釋放 C 庫保留的部份內容。

正則表達式

88.使用正則表達式匹配<html><h1>www.baidu.com</html>中的地址

import re
s = '<html><h1>www.baidu.com</html>'
p = re.compile(r'<html><h1>(.*?)</html>')
result = re.findall(p,s)[0]

a=「張明 98 分」,用 re.sub,將 98 替換爲 100

import re
a="張明 98 分"
pa = re.compile(r'\d+')
re.sub(pa,'100',a)

89.正則表達式匹配中(.*)和(.?)匹配區別?**

加?會將貪婪模式改爲懶惰模式,若是有問號的話,則表示匹配0個或1個問號前面的表達式

90.寫一段匹配郵箱的正則表達式

r'[0-9a-zA-Z_]*@.+\.(com|cn|net)$'

其餘內容

91.解釋一下 python 中 pass 語句的做用?

Python pass 是空語句,是爲了保持程序結構的完整性。

pass 不作任何事情,通常用作佔位語句。

92.簡述你對 input()函數的理解

在python3中,input()獲取用戶輸入,不論用戶輸入的是什麼,獲取到的都是字符串類型的。

93.python 中的 is 和==

is比較的是兩個對象的id值是否相等,也就是比較兩個對象是否爲同一個實例對象,是否指向同一個內存地址。

==比較的是兩個對象的內容是否相等,默認會調用對象的__eq__()方法。

94.Python 中的做用域

L (Local) 局部做用域
E (Enclosing) 閉包函數外的函數中
G (Global) 全局做用域
B (Built-in) 內建做用域

95.三元運算寫法和應用場景?

條件語句比較簡單時可使用三元運算符,最多見的就是 
res = 'test True' if expression is True else 'test False'

96.瞭解 enumerate 麼?

# 遍歷列表時候,攜帶索引index
a = ['a','b','c']
for index,item in a:
    print(index,item)

97.列舉 5 個 Python 中的標準模塊

json,re,random,datetime,codecs

98.如何在函數中設置一個全局變量

使用global關鍵字

99.pathlib 的用法舉例

from pathlib import Path

data_folder = Path("source_data/text_files/")

file_to_open = data_folder / "raw_data.txt"

f = open(file_to_open)

print(f.read())

100.Python 中的異常處理,寫一個簡單的應用場景

class NameTooShortError(ValueError): 
    pass
def validate(name):
    if len(name) < 10:
        raise NameTooShortError(name)
        
# 使用自定義異常類,使得發生異常時的錯誤更容易排查

101.Python 中遞歸的最大次數,那如何突破呢?

python解釋器限制最大的遞歸深度是999,能夠經過
import sys
sys.setrecursionlimit(10000)  # set the maximum depth as 10000
從新設置最大遞歸深度

102.什麼是面向對象的 mro

對於支持繼承的編程語言來講,其方法(屬性)可能定義在當前類,也可能來自於基類,因此在方法調用時就須要對當前類和基類進行搜索以肯定方法所在的位置。而搜索的順序就是所謂的「方法解析順序」(Method Resolution Order,或MRO)。對於只支持單繼承的語言來講,MRO 通常比較簡單;而對於 Python 這種支持多繼承的語言來講,MRO 就複雜不少。

103.isinstance 做用以及應用場景?

來判斷一個對象是不是一個已知的類型
舉個栗子:
 p= 'sfa'
 isinstance(p,str)
 True

104.什麼是斷言?應用場景?

Python 的斷言語句是一種調試工具,用來測試某個斷言條件。若是斷言條件 爲真,則程序將繼續正常執行;但若是條件爲假,則會引起 AssertionError 異常並顯示相關 的錯誤消息。

105.lambda 表達式格式以及應用場景?

d = {'a':2,'b':1,'c':3,'d':'4'}
sorted(d,key=lambda x :x[1]) 
# 將字典d按照值排序

106.新式類和舊式類的區別

Python 有兩種類:經典類(classic class)和新式類(new-style class)。二者的不一樣之處在於新式類繼承自 object。在 Python 2.1 之前,經典類是惟一可用的形式;Python 2.2 引入了新式類,使得類和內置類型更加統一;在 Python 3 中,新式類是惟一支持的類。

107.dir()是幹什麼用的?

dir() 函數不帶參數時,返回當前範圍內的變量、方法和定義的類型列表;帶參數時,返回參數的屬性、方法列表。若是參數包含方法__dir__(),該方法將被調用。若是參數不包含__dir__(),該方法將最大限度地收集參數信息。

108.*一個包裏有三個模塊,demo1.py, demo2.py, demo3.py,但使用 from tools import 導入模塊時,如何保證只有 demo一、demo3 被導入了。

但若想使用from pacakge_1 import *這種形式的寫法,需在  init.py中加上:   all = [‘file_a’, ‘file_b’] #package_1下有file_a.py和file_b.py,在導入時init.py文件將被執行。 
但不建議在 init.py中寫模塊,以保證該文件簡單。不過可在init.py導入咱們須要的模塊,以便避免一個個導入、方便使用。

109.列舉 5 個 Python 中的異常類型以及其含義

1. ArithmeticError 此基類用於派生針對各類算術類錯誤而引起的內置異常: OverflowError, ZeroDivisionError, FloatingPointError
2. BufferError 當與 緩衝區 相關的操做沒法執行時將被引起。
3. LookupError 此基類用於派生當映射或序列所使用的鍵或索引無效時引起的異常: IndexError, KeyError。 這能夠經過 codecs.lookup() 來直接引起
4. ImportError 當 import 語句嘗試加載模塊遇到麻煩時將被引起。 而且當 from ... import 中的 "from list" 存在沒法找到的名稱時也會被引起
5. IndexError 當序列抽取超出範圍時將被引起。 (切片索引會被靜默截短到容許的範圍;若是指定索引不是整數則 TypeError 會被引起

110.copy 和 deepcopy 的區別是什麼?

copy 即所謂的淺拷貝,賦值的時候非遞歸地複製子對象的引用;
deepcopy 即所謂的深拷貝,賦值的時候遞歸複製子對象。
舉個栗子,
xs = [1,2,[2,3,4],3]
ys = xs # 淺拷貝
zs = deepcopy(xs) # 深拷貝
xs[2][0] = 5
print(ys)
[1,2,[2,3,4],3]
print(xs)
[1,2,[5,3,4],3]

print(zs)
[1,2,[5,3,4],3] # 因爲深拷貝已經遞歸複製了子對象,因此內部的List也發生改變

111.**代碼中常常遇到的*args, kwargs 含義及用法。

這兩個是python中的可變參數。*args表示任何多個位置參數,它是一個tuple;**kwargs表示關鍵字參數,它是一個dict。而且同時使用*args和**kwargs時,必須*args參數列要在**kwargs前

112.Python 中會有函數或成員變量包含單下劃線前綴和結尾,和雙下劃線前綴結尾,區別是什麼?

前置單下劃線_var:命名約定,用來表示該名稱僅在內部使用。通常對 Python 解釋器沒 有特殊含義(通配符導入除外),只能做爲對程序員的提示。
後置單下劃線 var_:命名約定,用於避免與 Python 關鍵字發生命名衝突。
前置雙下劃線__var:在類環境中使用時會觸發名稱改寫,對 Python 解釋器有特殊含義。
先後雙下劃線__var__:表示由 Python 語言定義的特殊方法。在自定義的屬性中要避免
使用這種命名方式。

113.w、a+、wb 文件寫入模式的區別

w:寫入時會覆蓋上一次的寫入
a+:追加寫入
wb:以二進制文件形式寫入

114.舉例 sort 和 sorted 的區別

sort()與sorted()的不一樣在於,sort是在原位從新排列列表,而sorted()是產生一個新的列表

115.什麼是負索引?

負索引和正索引不一樣,它是從右邊開始檢索。例如:使用負索引取出列表的最後一個數
lis[-1] # 取出列表的最後一個元素
lis[-2] # 取出列表的倒數第二個元素

116.pprint 模塊是幹什麼的?

print()和pprint()都是python的打印模塊,功能基本同樣,惟一的區別就是pprint()模塊打印出來的數據結構更加完整,每行爲一個數據結構,更加方便閱讀打印輸出結果。特別是對於特別長的數據打印,print()輸出結果都在一行,不方便查看,而pprint()採用分行打印輸出,因此對於數據結構比較複雜、數據長度較長的數據,適合採用pprint()打印方式

117.解釋一下 Python 中的賦值運算符

在python中,使用 = 能夠給變量賦值。
在算術運算時,爲了簡化代碼的編寫,Python還提供了一系列與算術運算符對應的賦值運算符
例如,c += a 等效於 c=c+a

118.解釋一下 Python 中的邏輯運算符

and, or, not

119.講講 Python 中的位運算符

&	按位與運算符:參與運算的兩個值,若是兩個相應位都爲1,則該位的結果爲1,不然爲0	(a & b) 輸出結果 12 ,二進制解釋: 0000 1100
|	按位或運算符:只要對應的二個二進位有一個爲1時,結果位就爲1	(a | b) 輸出結果 61 ,二進制解釋: 0011 1101
^	按位異或運算符:當兩對應的二進位相異時,結果爲1	(a ^ b) 輸出結果 49 ,二進制解釋: 0011 0001
~	按位取反運算符:對數據的每一個二進制位取反,即把1變爲0,把0變爲1	(~a ) 輸出結果 -61 ,二進制解釋: 1100 0011, 在一個有符號二進制數的補碼形式。
<<	左移動運算符:運算數的各二進位所有左移若干位,由」<<」右邊的數指定移動的位數,高位丟棄,低位補0	a << 2 輸出結果 240 ,二進制解釋: 1111 0000
>>	右移動運算符:把」>>」左邊的運算數的各二進位所有右移若干位,」>>」右邊的數指定移動的位數	a >> 2 輸出結果 15 ,二進制解釋: 0000 1111

120.在 Python 中如何使用多進制數字?

一、二進制數字由0和1組成,咱們使用0b或0B前綴表示二進制數

print(int(0b1010))#10
二、使用bin()函數將一個數字轉換爲它的二進制形式

print(bin(0xf))#0b1111
三、八進制數由數字0-7組成,用前綴0o或0O表示8進制數

print(oct(8))#0o10
四、十六進數由數字0-15組成,用前綴0x或者0X表示16進制數

print(hex(16))#0x10
print(hex(15))#0xf

121.怎樣聲明多個變量並賦值?

a,b = 1,2

算法和數據結構

122.已知:

AList = [1,2,3]
BSet = {1,2,3}

(1) 從 AList 和 BSet 中 查找 4,最壞時間複雜度那個大?

查找列表最壞時間複雜度是O(n),查找字典是O(1),由於字典的數據結構是散列表

(2) 從 AList 和 BSet 中 插入 4,最壞時間複雜度那個大?

插入的操做都是O(1)

123.用 Python 實現一個二分查找的函數

def binary_search(item,arr):
    start = 0
    end = len(arr) - 1
    while start <= end:
        mid = (start + end) // 2
        if item == arr[mid]:
            return True
        elif item < arr[mid]:
            end = mid - 1
        else:
            start = mid + 1
array = [1,2,3,4,5,6]
print(binary_search(2,array))

124.python 單例模式的實現方法

單例模式(Singleton Pattern)是一種經常使用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你但願在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。

好比,某個服務器程序的配置信息存放在一個文件中,客戶端經過一個 AppConfig 的類來讀取配置文件的信息。若是在程序運行期間,有不少地方都須要使用配置文件的內容,也就是說,不少地方都須要建立 AppConfig 對象的實例,這就致使系統中存在多個 AppConfig 的實例對象,而這樣會嚴重浪費內存資源,尤爲是在配置文件內容不少的狀況下。事實上,相似 AppConfig 這樣的類,咱們但願在程序運行期間只存在一個實例對象
1.使用裝飾器實現單例模式
def singleton(cls):
    _instance = {}
    def _singleton(*args,**kargs):
        if cls not in _instance:
            _instance[cls] = cls(*args,**args)
        return _instance[cls]
    return _singleton
  
2.使用類實現單例模式
import threading
class Singleton(object):
    _instance_lock = threading.Lock()

    def __init__(self):
        pass


    def __new__(cls, *args, **kwargs):
        if not hasattr(Singleton, "_instance"):
            with Singleton._instance_lock:
                if not hasattr(Singleton, "_instance"):
                    Singleton._instance = object.__new__(cls)  
        return Singleton._instanc

125.使用 Python 實現一個斐波那契數列

# 不少人上來就寫下面這種解法
def fibnaqie(n):
    if n < 2:
        return n
    return fibnaqie(n - 1) + fibnaqie(n - 2)
# 這種解法時間複雜度高,並且通常不是面試官最想要的答案

# 下面這種優化的版本
def fib2(n):
    fib_n = 0
    fib_one = 1
    fib_two = 0
    res = [0, 1]
    if n < 2:
        return res[n]
    for i in range(2, n + 1):
        fib_n = fib_one + fib_two
        fib_two = fib_one
        fib_one = fib_n
    return fib_n
# 因此適當地選擇遞歸仍是迭代,要看具體狀況,處理樹,或者圖的遍歷的時候,遞歸仍是比迭代優先考慮的

126.找出列表中的重複數字

def find_duplicate(arr):
    not_dup = set()
    dup = set()
    for x in arr:
        if x not in not_dup:
            not_dup.add(x)
        else:
            dup.add(x)
    return dup


if __name__ == '__main__':
    array = [1, 2, 3, 4, 4, 4, 4]
    print(find_duplicate(array))

127.找出列表中的單個數字

a = ['a', 1, 2, 'b']
for x in a:
    if str(x).isdigit():
        print(x)

128.寫一個冒泡排序

def bubble_sort(arr):
    n = len(arr)
    if len(arr) < 2:
        return arr
    for i in range(n - 1):
        count = 0
        for j in range(n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                count += 1
        if count == 0:
            return arr
    return arr


if __name__ == '__main__':
    arr = [2, 1, 5, 3, 6]
    arr1 = [1, 2, 3, 4, 5]
    print(bubble_sort(arr1))

129.寫一個快速排序

def quick_sort(arr):
    if len(arr) < 2:
        return arr
    else:
        pivot = arr[0]
        less = [i for i in arr[1:] if i <= pivot]
        more = [i for i in arr[1:] if i > pivot]
    return quick_sort(less) + [pivot] + quick_sort(more)


if __name__ == '__main__':
    array = [2, 1, 6, 3, 4, 5]
    print(quick_sort(array))

130.寫一個拓撲排序

# 使用循環進行拓撲排序
def topoSort(G):
    # 初始化計算被指向節點的字典
    cnt = dict((u, 0) for u in G.keys())
    import pdb;pdb.set_trace()
    # 若某節點被其餘節點指向,該節點計算量+1
    for u in G:
        for v in G[u]:
            cnt[v] += 1
    # 收集被指向數爲0的節點,此時Q只有一個節點,即起始節點a
    Q = [u for u in cnt.keys() if cnt[u] == 0]
    # 記錄結果
    seq = []
    while Q:
        s = Q.pop()
        seq.append(s)
        for u in G[s]:
            cnt[u] -= 1
            if cnt[u] == 0:
                Q.append(u)
    return seq


# 有向無環圖的鄰接字典
G = {
    'a': {'b', 'f'},
    'b': {'c', 'd', 'f'},
    'c': {'d'},
    'd': {'e', 'f'},
    'e': {'f'},
    'f': {}
}

res = topoSort(G)
print(res)

131.python 實現一個二進制計算

''' 以實現二進制加法爲例 給定兩個二進制字符串,返回他們的和(用二進制表示)。 輸入爲非空字符串且只包含數字 1 和 0。 輸入: a = 「11」, b = 「1」 輸出: 「100」 '''


def binary_plus(a, b):
    a, b = int('0b' + a, 2), int('0b'+b, 2)
    return bin(a + b)[2:]


if __name__ == '__main__':
    a = '11'
    b = '1'
    print(binary_plus(a, b))

# 解釋一下,class int(x, base) 
x–字符串或數字 
base–進制數,默認十進制。 
bin()函數返回一個整型int或者長整數long int的二進制表示,bin()運算返回的是二進制。因此前兩位是二進制的標誌,須要[2:]去除

132.有一組「+」和「-」符號,要求將「+」排到左邊,「-」排到右邊,寫出具體的實現方法。

def some_sort(arr):
    list_a = []
    list_b = []
    for x in arr:
        if x == '+':
            list_a.append(x)
        else:
            list_b.append(x)
    list_a.extend(list_b)
    print(list_a)
    return list_a

133.單鏈表反轉

class ListNode:
    def __init__(self, val):
        self.val = val
        self.next = None


def reverse_node(head):
    p = head
    q = head.next
    head.next = None
    while q:
        r = q.next
        q.next = p
        p = q
        q = r
    head = p
    return head


if __name__ == '__main__':
    l1 = ListNode(3)
    l1.next = ListNode(2)
    l1.next.next = ListNode(1)

    l = reverse_node(l1)
    print(l.val, l.next.val, l.next.next.val)
# 1,2,3

134.交叉鏈表求交點

'''先遍歷兩個鏈表,獲知兩個鏈表各自的長度,日後調整較長鏈表的指針,使之與較短鏈表的起始指針對齊,而後兩個鏈表同時日後掃描,直至兩者的節點相同,證實該節點是相交節點,不然返回 None,代表兩個鏈表不相交,時間複雜度o(n),空間複雜度0(1)'''
class ListNode:
    def __init__(self, val):
        self.val = val
        self.next = None


def solution(head_a, head_b):
    def get_list_length(head):
        len = 0
        while head:
            len += 1
            head = head.next
        return head

    def forward_long_list(long_len, short_len, head):
        delta = long_len - short_len
        while delta and head:
            head = head.next
            delta -= 1
        return head

    def main_func(head_a, head_b):
        head_a_len = get_list_length(head_a)
        head_b_len = get_list_length(head_b)
        if head_a_len > head_b_len:
            head_a = forward_long_list(head_a_len, head_b_len, head_a)
        else:
            head_b = forward_long_list(head_a_len, head_b_len, head_b)
        while head_a and head_b:
            if head_a == head_b:
                return head_a
            head_a = head_a.next
            head_b = head_b.next
        return None

    return main_func(head_a, head_b)

135.用隊列實現棧

class Stack:
    def __init__(self):
        self.queue_a = []
        self.queue_b = []

    def push(self, val):
        self.queue_a.append(val)

    def pop(self):
        if len(self.queue_a) == 0:
            return None
          # 核心思想就是留一個元素在隊列a中,最後交換隊列a,b,再從b中取棧頂元素
        while len(self.queue_a) != 1:
            self.queue_b.append(self.queue_a.pop(0))
        self.queue_a, self.queue_b = self.queue_b, self.queue_a
        return self.queue_b.pop()


test_stack = Stack()
for i in range(5):
    test_stack.push(i)
for i in range(5):
    print(test_stack.pop())

136.找出數據流的中位數

# 中位數是有序列表中間的數。若是列表長度是偶數,中位數則是中間兩個數的平均值
# 若是是奇數,則中位數就是中間的數字
def find_zhongwei(arr):
    arr.sort()
    if len(ar) == 0:
        return
    if len(ar) == 1:
        return ar[0]
    mid = len(arr) // 2
    if len(arr) % 2 == 0:
        return (arr[mid - 1] + arr[len(arr) / 2]) / 2
    else:
        return arr[mid]


if __name__ == '__main__':
    ar = [2, 1, 5, 3, 4]
    print(find_zhongwei(ar))

137.二叉搜索樹中第 K 小的元素

# 問題本質:對二叉樹進行中序遍歷,中序排序後,返回第K-1個值
class Solution(object):
    def kthSmallest(self, root, k):
        """ :type root: TreeNode :type k: int :rtype: int """
        def inorderTraversal(root):
            if root is None:
                return []
            res = []
            res.extend(inorderTraversal(root.left))
            res.append(root.val)
            res.extend(inorderTraversal(root.right))
            return res
        return inorderTraversal(root)[k - 1]

爬蟲相關

138.在 requests 模塊中,requests.content 和 requests.text 什麼區別

resp.text返回的是Unicode型的數據。

resp.content返回的是bytes型也就是二進制的數據。
也就是說,若是你想取文本,能夠經過r.text。

若是想取圖片,文件,則能夠經過r.content。

(resp.json()返回的是json格式數據)

139.簡要寫一下 lxml 模塊的使用方法框架

Python 標準庫中自帶了 xml 模塊,可是性能不夠好,並且缺少一些人性化的 API,相比之下,第三方庫 lxml 是用 Cython 實現的,並且增長了不少實用的功能,可謂爬蟲處理網頁數據的一件利器。lxml 大部分功能都存在 lxml.etree中.
能夠看一下官方文檔,https://lxml.de/index.html

140.說一說 scrapy 的工做流程

141.scrapy 的去重原理

1.須要將dont_filter設置爲False開啓去重,默認是False,開啓去重;

2.對於每個url的請求,調度器都會根據請求得相關信息加密獲得一個指紋信息,而且將指紋信息和set()集合中的指紋信息進行比對,若是set()集合中已經存在這個數據,就不在將這個Request放入隊列中。若是set()集合中沒有存在這個加密後的數據,就將這個Request對象放入隊列中,等待被調度

142.scrapy 中間件有幾種類,你用過哪些中間件

scrapy自帶兩種中間件,下載器中間件(DownloaderMiddleware),爬蟲中間件(spiderMiddleware)
DownloaderMiddleware的做用是在request以前或者response以後,對spider進行配置處理,例如動態更換ip,更換user-agent,更換cookie等
Spider中間件是介入到Scrapy的spider處理機制的鉤子框架,您能夠添加代碼來處理髮送給 Spiders 的response及spider產生的item和request。

143.你寫爬蟲的時候都遇到過什麼反爬蟲措施,你是怎麼解決的?

能夠看看這篇博文https://blog.csdn.net/weixin_33768481/article/details/87273454

144.爲何會用到代理?

單一ip頻繁重複請求同一個網站會被封掉

145.代理失效了怎麼處理?

構建代理池,動態更換ip

146.列出你知道 header 的內容以及信息

user-agent
referer
content-type
content-length
.....
詳情能夠看這篇https://kb.cnblogs.com/page/92320/

147.說一說打開瀏覽器訪問 www.baidu.com 獲取到結果,整個流程。

可參考這篇博文https://www.jianshu.com/p/d616d887953a

148.爬取速度過快出現了驗證碼怎麼處理

比較簡單的驗證碼,能夠用Python的PIL庫(from PIL import Image),tesserocr模塊;
比較複雜的話能夠引入機器學習模型,可是成本會比較高,最好仍是使用高質量的代理ip,避免觸發驗證碼。

149.scrapy 和 scrapy-redis 有什麼區別?爲何選擇 redis 數據庫?

1) scrapy是一個Python爬蟲框架,爬取效率極高,具備高度定製性,可是不支持分佈式。而scrapy-redis一套基於redis數據庫、運行在scrapy框架之上的組件,可讓scrapy支持分佈式策略,Slaver端共享Master端redis數據庫裏的item隊列、請求隊列和請求指紋集合。

2) 爲何選擇redis數據庫,由於redis支持主從同步,並且數據都是緩存在內存中的,因此基於redis的分佈式爬蟲,對請求和數據的高頻讀取效率很是高。

150.分佈式爬蟲主要解決什麼問題

1)ip

2)帶寬

3)cpu

4)io

151.寫爬蟲是用多進程好?仍是多線程好? 爲何?

IO密集型代碼(文件處理、網絡爬蟲等),多線程可以有效提高效率(單線程下有IO操做會進行IO等待,形成沒必要要的時間浪費,而開啓多線程能在線程A等待時,自動切換到線程B,能夠不浪費CPU的資源,從而能提高程序執行效率)。在實際的數據採集過程當中,既考慮網速和響應的問題,也須要考慮自身機器的硬件狀況,來設置多進程或多線程

152.解析網頁的解析器使用最多的是哪幾個

xpath,css-selector,beautifulSoup

153.須要登陸的網頁,如何解決同時限制 ip,cookie,session(其中有一些是動態生成的)在不使用動態爬取的狀況下?

解決限制IP可使用代理IP地址池、服務器;

不適用動態爬取的狀況下可使用反編譯JS文件獲取相應的文件,或者換用其餘平臺(好比手機端)看看是否能夠獲取相應的json文件

154.驗證碼的解決

圖形驗證碼:干擾、雜色不是特別多的圖片可使用開源庫Tesseract進行識別,太過複雜的須要藉助第三方打碼平臺

點擊和拖動滑塊驗證碼能夠藉助selenium、無圖形界面瀏覽器(chromedirver或者phantomjs)和pillow包來模擬人的點擊和滑動操做,pillow能夠根據色差識別須要滑動的位置

155.使用最多的數據庫(mysql,mongodb,redis 等),對他的理解?

這個自由發揮了,多看下MySQL和MongoDB的使用,瞭解Redis的基本數據結構

網絡編程

156.TCP 和 UDP 的區別?

TCP協議和UDP協議特性區別總結:
     1. TCP協議在傳送數據段的時候要給段標號;UDP協議不
     2. TCP協議可靠;UDP協議不可靠
     3. TCP協議是面向鏈接;UDP協議採用無鏈接
     4. TCP協議負載較高,採用虛電路;UDP採用無鏈接
     5. TCP協議的發送方要確認接收方是否收到數據段(3次握手協議)
     6. TCP協議採用窗口技術和流控制

157.簡要介紹三次握手和四次揮手

https://mp.weixin.qq.com/s/jLkhjM7wOpZuWgJdAXis1A
這篇博文講的不錯,能夠參考一下

另外,time_wait狀態的做用在面試中也是常問的,能夠參考下面這篇,https://www.iteblog.com/archives/169.html

158.什麼是粘包? socket 中形成粘包的緣由是什麼? 哪些狀況會發生粘包現象?

基於TCP的socket編程中,發送端爲了將多個發往接收端的包,更有效的發到對方,使用了優化方法(Nagle算法),將屢次間隔較小、數據量小的數據包,合併成一個大的數據包發送(把發送端的緩衝區填滿一次性發送)

形成粘包的緣由:
1 發送端須要等緩衝區滿才發送出去,形成粘包
2 接收方不及時接收緩衝區的包,形成多個包接收

併發

159.舉例說明 conccurent.future 的中線程池的用法

concurrent.futures模塊的基礎是Exectuor,Executor是一個抽象類,它不能被直接使用。可是它提供的兩個子類ThreadPoolExecutor和ProcessPoolExecutor倒是很是有用,顧名思義二者分別被用來建立線程池和進程池的代碼。咱們能夠將相應的tasks直接放入線程池/進程池,不須要維護Queue來操心死鎖的問題,線程池/進程池會自動幫咱們調度。
example1.py


from
concurrent.futures
import
ThreadPoolExecutor


import
time


def
return_future_result(message):


    time.sleep(2)


    return
message


pool
=
ThreadPoolExecutor(max_workers=2)  #
 建立一個最大可容納2個task的線程池


future1
=
pool.submit(return_future_result,
("hello"))  #
 往線程池裏面加入一個task


future2
=
pool.submit(return_future_result,
("world"))  #
 往線程池裏面加入一個task


print(future1.done())  #
 判斷task1是否結束


time.sleep(3)


print(future2.done())  #
 判斷task2是否結束


print(future1.result())  #
 查看task1返回的結果


print(future2.result())  #
 查看task2返回的結果

160.說一說多線程,多進程和協程的區別。

這個問題雖然被問爛了,可是仍是可能會問,不過網上都是答案,搜搜看下就行

161.簡述 GIL

在CPython解釋器中,全局解釋鎖GIL是在於執行Python字節碼時爲了保護訪問Python對象而阻止多個線程執行的一把互斥鎖。這把鎖的存在在主要是由於CPython解釋器的內存管理不是線程安全的。然而直到今天GIL依舊存在,如今的不少功能已經習慣於依賴它做爲執行的保證
因爲GIL的存在,當線程被操做系統喚醒後,必須拿到GIL鎖後才能執行代碼,也就是說同一時刻永遠只有一個線程在執行,這就致使若是咱們的程序是CPU密集運算型的任務,那麼使用Python多線程是不能提升效率的

162.進程之間如何通訊

共享內存,信號量,互斥鎖,消息隊列等

163.IO 多路複用的做用?

I/O多路複用就經過一種機制,能夠監視多個描述符,一旦某個描述符就緒(通常是讀就緒或者寫就緒),可以通知程序進行相應的讀寫操做。但select,poll,epoll本質上都是同步I/O,由於他們都須要在讀寫事件就緒後本身負責進行讀寫,也就是說這個讀寫過程是阻塞的,而異步I/O則無需本身負責進行讀寫,異步I/O的實現會負責把數據從內核拷貝到用戶空間

164.select、poll、epoll 模型的區別?

可參考這篇博文,https://www.cnblogs.com/Anker/p/3265058.html

165.什麼是併發和並行?

併發的實質是一個物理CPU(也能夠多個物理CPU) 在若干道程序之間多路複用,併發性是對有限物理資源強制行使多用戶共享以提升效率
並行」指兩個或兩個以上事件或活動在同一時刻發生。在多道程序環境下,並行性使多個程序同一時刻可在不一樣CPU上同時執行

167.解釋什麼是異步非阻塞?

當一個異步過程調用發出後,調用者不會馬上獲得結果。
實際處理這個調用的部件是在調用發出後,
經過狀態、通知來通知調用者,或經過回調函數處理這個調用
非阻塞的意思是,不能馬上獲得結果以前,該函數不會阻塞當前線程,而會馬上返回

168.threading.local 的做用?

Python提供了 threading.local 類,將這個類實例化獲得一個全局對象,可是不一樣的線程使用這個對象存儲的數據其它線程不可見(本質上就是不一樣的線程使用這個對象時爲其建立一個獨立的字典)

Git 面試題

169.說說你知道的 git 命令

git clone;
git push
git status;
git commit;
...

170.git 如何查看某次提交修改的內容x

知道commit id的狀況下:
1. 獲取commit id
   git log 

2. 查看commit內容
   git show commit_id

查看最近n次提交的修改
   git log -p -n
指定n爲1則能夠查看最近一次修改的內容
相關文章
相關標籤/搜索