從今天開始,陸續分享一些 Python 相關的面試題,在學習的路上,與君共勉!java
各位 Python 大佬請繞過啊!!固然若是能給些指點,那就再好不過了!python
基礎篇(一)面試
Python 語言簡單易懂,上手容易,隨着 AI 風潮,愈來愈火。正則表達式
編譯型語言:把作好的源程序所有編譯成二進制的可運行程序。而後,可直接運行這個程序。如:C,C++算法
解釋型語言:把作好的源程序翻譯一句,而後執行一句,直至結束!如:Python, (Java 有些特殊,java程序也須要編譯,可是沒有直接編譯稱爲機器語言,而是編譯稱爲字節碼,而後用解釋方式執行字節碼。)編程
字符串(str):字符串是用引號括起來的任意文本,是編程語言中最經常使用的數據類型。json
列表(list):列表是有序的集合,能夠向其中添加或刪除元素。bash
元組(tuple):元組也是有序集合,可是是沒法修改的。即元組是不可變的。微信
字典(dict):字典是無序的集合,是由 key-value 組成的。app
集合(set):是一組 key 的集合,每一個元素都是惟一,不重複且無序的。
mystr='luobodazahui'
mystr[1:3]
複製代碼
output
'uo'
複製代碼
mystr2 = "welcome to luobodazahui, dear {name}"
mystr2.format(name="baby")
複製代碼
output
'welcome to luobodazahui, dear baby'
複製代碼
能夠用來鏈接字符串,將字符串、元組、列表中的元素以指定的字符(分隔符)鏈接生成一個新的字符串。
mylist = ['luo', 'bo', 'da', 'za', 'hui']
mystr3 = '-'.join(mylist)
print(mystr3)
複製代碼
outout
'luo-bo-da-za-hui'
複製代碼
String.replace(old,new,count) 將字符串中的 old 字符替換爲 New 字符,count 爲替換的個數
mystr4 = 'luobodazahui-haha'
print(mystr4.replace('haha', 'good'))
複製代碼
output
luobodazahui-good
複製代碼
切割字符串,獲得一個列表。
mystr5 = 'luobo,dazahui good'
# 以空格分割
print(mystr5.split())
# 以h分割
print(mystr5.split('h'))
# 以逗號分割
print(mystr5.split(','))
複製代碼
output
['luobo,dazahui', 'good']
['luobo,daza', 'ui good']
['luobo', 'dazahui good']
複製代碼
同字符串
向列表中國添加元素
mylist1 = [1, 2]
mylist2 = [3, 4]
mylist3 = [1, 2]
mylist1.append(mylist2)
print(mylist1)
mylist3.extend(mylist2)
print(mylist3)
複製代碼
outout
[1, 2, [3, 4]]
[1, 2, 3, 4]
複製代碼
del:根據下標進行刪除
pop:刪除最後一個元素
remove:根據元素的值進行刪除
mylist4 = ['a', 'b', 'c', 'd']
del mylist4[0]
print(mylist4)
mylist4.pop()
print(mylist4)
mylist4.remove('c')
print(mylist4)
複製代碼
output
['b', 'c', 'd']
['b', 'c']
['b']
複製代碼
sort:是將list按特定順序從新排列,默認爲由小到大,參數 reverse=True 可改成倒序,由大到小。
reverse:是將list逆置。
mylist5 = [1, 5, 2, 3, 4]
mylist5.sort()
print(mylist5)
mylist5.reverse()
print(mylist5)
複製代碼
output
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]
複製代碼
dict.clear()
dict1 = {'key1':1, 'key2':2}
dict1.clear()
print(dict1)
複製代碼
output
{}
複製代碼
使用 pop 方法來指定刪除字典中的某一項
dict1 = {'key1':1, 'key2':2}
d1 = dict1.pop('key1')
print(d1)
print(dict1)
複製代碼
output
1
{'key2': 2}
複製代碼
dict2 = {'key1':1, 'key2':2}
mykey = [key for key in dict2]
print(mykey)
myvalue = [value for value in dict2.values()]
print(myvalue)
key_value = [(k, v) for k, v in dict2.items() ]
print(key_value)
複製代碼
output
['key1', 'key2']
[1, 2]
[('key1', 1), ('key2', 2)]
複製代碼
用於建立一個新字典,以序列中元素作字典的鍵,value 爲字典全部鍵對應的初始值
keys = ['zhangfei', 'guanyu', 'liubei', 'zhaoyun']
dict.fromkeys(keys, 0)
複製代碼
output
{'zhangfei': 0, 'guanyu': 0, 'liubei': 0, 'zhaoyun': 0}
複製代碼
計算機在最初的設計中,採用了8個比特(bit)做爲一個字節(byte)的方式。一個字節能表示的最大的整數就是255(二進制11111111=十進制255),若是要表示更大的整數,就必須用更多的字節。 最先,計算機只有 ASCII 編碼,即只包含大小寫英文字母、數字和一些符號,這些對於其餘語言,如中文,日文顯然是不夠用的。後來又發明了Unicode,Unicode把全部語言都統一到一套編碼裏,這樣就不會再有亂碼問題了。當須要保存到硬盤或者須要傳輸的時候,就轉換爲UTF-8編碼。UTF-8 是隸屬於 Unicode 的可變長的編碼方式。 在 Python 中,以 Unicode 方式編碼的字符串,可使用 encode() 方法來編碼成指定的 bytes,也能夠經過 decode() 方法來把 bytes 編碼成字符串。
encode
"中文".encode('utf-8')
複製代碼
output
b'\xe4\xb8\xad\xe6\x96\x87'
複製代碼
decode
b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
複製代碼
output
'中文'
複製代碼
a = 1
b = 2
a, b = b, a
print(a, b)
複製代碼
output
2 1
複製代碼
先來看個例子
c = d = [1,2]
e = [1,2]
print(c is d)
print(c == d)
print(c is e)
print(c == e)
複製代碼
output
True
True
False
True
複製代碼
== 是比較操做符,只是判斷對象的值(value)是否一致,而 is 則判斷的是對象之間的身份(內存地址)是否一致。對象的身份,能夠經過 id() 方法來查看。
id(c)
id(d)
id(e)
複製代碼
output
188748080
288748080
388558288
複製代碼
能夠看出,只有 id 一致時,is 比較纔會返回 True,而當 value 一致時,== 比較就會返回 True
位置參數,默認參數,可變參數,關鍵字參數
容許咱們在調用函數的時候傳入多個實參
def test(*arg, **kwarg):
if arg:
print("arg:", arg)
if kwarg:
print("kearg:", kwarg)
test('ni', 'hao', key='world')
複製代碼
output
arg: ('ni', 'hao')
kearg: {'key': 'world'}
複製代碼
能夠看出, *arg會把位置參數轉化爲tuple **kwarg會把關鍵字參數轉化爲dict
sum(range(1, 101))
複製代碼
import time
import datetime
print(datetime.datetime.now())
print(time.strftime('%Y-%m-%d %H:%M:%S'))
複製代碼
output
12019-06-07 18:12:11.165330
22019-06-07 18:12:11
複製代碼
簡單列舉10條:
儘可能以避免單獨使用小寫字母'l',大寫字母'O',以及大寫字母'I'等容易混淆的字母。
函數命名使用所有小寫的方式,可使用下劃線。
常量命名使用所有大寫的方式,可使用下劃線。
使用 has 或 is 前綴命名布爾元素,如: is_connect = True; has_member = False
不要在行尾加分號, 也不要用分號將兩條命令放在同一行。
不要使用反斜槓鏈接行。
頂級定義之間空2行, 方法定義之間空1行,頂級定義之間空兩行。
若是一個類不繼承自其它類, 就顯式的從 object 繼承。
內部使用的類、方法或變量前,需加前綴'_'代表此爲內部使用的。
要用斷言來實現靜態類型檢測。
import copy
list1 = [1, 2, 3, [1, 2]]
list2 = copy.copy(list1)
list2.append('a')
list2[3].append('a')
print(list1, list2)
複製代碼
output
[1, 2, 3, [1, 2, 'a']] [1, 2, 3, [1, 2, 'a'], 'a']
複製代碼
可以看出,淺拷貝只成功」獨立「拷貝了列表的外層,而列表的內層列表,仍是共享的
import copy
list1 = [1, 2, 3, [1, 2]]
list3 = copy.deepcopy(list1)
list3.append('a')
list3[3].append('a')
print(list1, list3)
複製代碼
output
[1, 2, 3, [1, 2]] [1, 2, 3, [1, 2, 'a'], 'a']
複製代碼
深拷貝使得兩個列表徹底獨立開來,每個列表的操做,都不會影響到另外一個。
def num():
return [lambda x:i*x for i in range(4)]
print([m(1) for m in num()])
複製代碼
output
[3, 3, 3, 3]
複製代碼
經過運行結果,能夠看出 i 的取值爲3,很神奇
可變數據類型:list、dict、set
不可變數據類型:int/float、str、tuple
for i in range(1, 10):
for j in range(1, i+1):
print("%s*%s=%s " %(i, j, i*j), end="")
print()
複製代碼
output
11*1=1
22*1=2 2*2=4
33*1=3 3*2=6 3*3=9
44*1=4 4*2=8 4*3=12 4*4=16
55*1=5 5*2=10 5*3=15 5*4=20 5*5=25
66*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
77*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
88*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
99*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
複製代碼
print 函數,默認是會換行的,其有一個默認參數 end,若是像例子中,咱們把 end 參數顯示的置爲"",那麼 print 函數執行完後,就不會換行了,這樣就達到了九九乘法表的效果了。
filter 函數用於過濾序列,它接收一個函數和一個序列,把函數做用在序列的每一個元素上,而後根據返回值是True仍是False決定保留仍是丟棄該元素。
mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list(filter(lambda x: x%2 == 1, mylist))
複製代碼
output
[1, 3, 5, 7, 9]
複製代碼
保留奇數列表
map 函數傳入一個函數和一個序列,並把函數做用到序列的每一個元素上,返回一個可迭代對象
mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list(map(lambda x: x*2, mylist))
複製代碼
output
[2, 4, 6, 8, 10, 12, 14, 16, 18]
複製代碼
reduce 函數用於遞歸計算,一樣須要傳入一個函數和一個序列,並把函數和序列元素的計算結果與下一個元素進行計算。
from functools import reduce
reduce(lambda x, y: x+y, range(101))
複製代碼
output
15050
複製代碼
能夠看出,上面的三個函數與匿名函數相結合使用,能夠寫出強大簡潔的代碼。
match()函數只檢測要匹配的字符是否是在 string 的開始位置匹配,search()會掃描整個 string 查找匹配
__new__是在實例建立以前被調用的,由於它的任務就是建立實例而後返回該實例對象,是個靜態方法。
__init__是當實例對象建立完成後被調用的,而後設置對象屬性的一些初始值,一般用在初始化一個類實例的時候。是一個實例方法。
一、__new__至少要有一個參數 cls,表明當前類,此參數在實例化時由 Python 解釋器自動識別。
二、__new__必需要有返回值,返回實例化出來的實例,這點在本身實現__new__時要特別注意,能夠 return 父類(經過 super(當前類名, cls))__new__出來的實例,或者直接是 object 的__new__出來的實例。
三、__init__有一個參數 self,就是這個__new__返回的實例,__init__在__new__的基礎上能夠完成一些其它初始化的動做,__init__不須要返回值。
四、若是__new__建立的是當前類的實例,會自動調用__init__函數,經過 return 語句裏面調用的__new__函數的第一個參數是 cls 來保證是當前類實例,若是是其餘類的類名,;那麼實際建立返回的就是其餘類的實例,其實就不會調用當前類的__init__函數,也不會調用其餘類的__init__函數。
a, b = 1, 2
# 若果 a>b 成立 就輸出 a-b 不然 a+b
h = a-b if a>b else a+b
複製代碼
output
13
複製代碼
print(random.random())
print(random.randint(1, 100))
print(random.uniform(1,5))
複製代碼
output
10.03765019937131564
218
31.8458555362279228
複製代碼
zip() 函數將可迭代的對象做爲參數,將對象中對應的元素打包成一個個元組,而後返回由這些元組組成的列表
list1 = ['zhangfei', 'guanyu', 'liubei', 'zhaoyun']
list2 = [0, 3, 2, 4]
list(zip(list1, list2))
複製代碼
output
[('zhangfei', 0), ('guanyu', 3), ('liubei', 2), ('zhaoyun', 4)]
複製代碼
range([start,] stop[, step]),根據 start 與 stop 指定的範圍以及 step 設定的步長,生成一個序列。 而 xrange 生成一個生成器,能夠很大的節約內存。
開文件在進行讀寫的時候可能會出現一些異常情況,若是按照常規的 f.open 寫法,咱們須要 try,except,finally,作異常判斷,而且文件最終無論遇到什麼狀況,都要執行 finally f.close() 關閉文件,with 方法幫咱們實現了 finally 中 f.close。
Python 中默認是貪婪匹配模式。
貪婪模式:正則表達式通常趨向於最大長度匹配。
非貪婪模式:在整個表達式匹配成功的前提下,儘量少的匹配。
例如:
def test(L=[]):
L.append('test')
print(L)
複製代碼
output
test() # ['test']
test() # ['test', 'test']
複製代碼
默認參數是一個列表,是可變對象[],Python 在函數定義的時候,默認參數 L 的值就被計算出來了,是[],每次調用函數,若是 L 的值變了,那麼下次調用時,默認參數的值就已經再也不是[]了。
mystr = '1,2,3'
mystr.split(',')
複製代碼
output
['1', '2', '3']
複製代碼
mylist = ['1', '2', '3']
list(map(lambda x: int(x), mylist))
複製代碼
output
[1, 2, 3]
複製代碼
mylist = [1, 2, 3, 4, 5, 5]
list(set(mylist))
複製代碼
from collections import Counter
mystr = 'sdfsfsfsdfsd,were,hrhrgege.sdfwe!sfsdfs'
Counter(mystr)
複製代碼
output
Counter({'s': 9,
'd': 5,
'f': 7,
',': 2,
'w': 2,
'e': 5,
'r': 3,
'h': 2,
'g': 2,
'.': 1,
'!': 1})
複製代碼
[x for x in range(10) if x%2 == 1]
複製代碼
output
[1, 3, 5, 7, 9]
複製代碼
list1 = [[1,2],[3,4],[5,6]]
[j for i in list1 for j in i]
複製代碼
output
[1, 2, 3, 4, 5, 6]
複製代碼
二分查找算法也稱折半查找,基本思想就是折半,對比大小後再折半查找,必須是有序序列纔可使用二分查找。 遞歸算法
def binary_search(data, item):
# 遞歸
n = len(data)
if n > 0:
mid = n // 2
if data[mid] == item:
return True
elif data[mid] > item:
return binary_search(data[:mid], item)
else:
return binary_search(data[mid+1:], item)
return False
list1 = [1,4,5,66,78,99,100,101,233,250,444,890]
binary_search(list1, 999)
複製代碼
非遞歸算法
def binary_search(data, item):
# 非遞歸
n = len(data)
first = 0
last = n - 1
while first <= last:
mid = (first + last)//2
if data[mid] == item:
return True
elif data[mid] > item:
last = mid - 1
else:
first = mid + 1
return False
list1 = [1,4,5,66,78,99,100,101,233,250,444,890]
binary_search(list1, 99)
複製代碼
字典轉 json
import json
dict1 = {'zhangfei':1, "liubei":2, "guanyu": 4, "zhaoyun":3}
myjson = json.dumps(dict1)
myjson
複製代碼
output
'{"zhangfei": 1, "liubei": 2, "guanyu": 4, "zhaoyun": 3}'
複製代碼
json 轉字典
mydict = json.loads(myjson)
mydict
複製代碼
output
{'zhangfei': 1, 'liubei': 2, 'guanyu': 4, 'zhaoyun': 3}
複製代碼
import random
td_list=[i for i in range(10)]
print("列表推導式", td_list, type(td_list))
ge_list = (i for i in range(10))
print("生成器", ge_list)
dic = {k:random.randint(4, 9)for k in ["a", "b", "c", "d"]}
print("字典推導式",dic,type(dic))
複製代碼
output
列表推導式 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <class 'list'>
生成器 <generator object <genexpr> at 0x0139F070>
字典推導式 {'a': 6, 'b': 5, 'c': 8, 'd': 9} <class 'dict'>
複製代碼
read 讀取整個文件
readline 讀取下一行,使用生成器方法
readlines 讀取整個文件到一個迭代器以供咱們遍歷
list2 = [1, 2, 3, 4, 5, 6]
random.shuffle(list2)
print(list2)
複製代碼
output
[4, 6, 5, 1, 2, 3]
複製代碼
str1 = 'luobodazahui'
str1[::-1]
複製代碼
output
'iuhazadoboul'
複製代碼
__foo__
:一種約定,Python 內部的名字,用來區別其餘用戶自定義的命名,以防衝突,就是例如__init__()和__del__()及__call__()這些特殊方法。
_foo
:一種約定,用來指定變量私有。不能用 from module import * 導入,其餘方面和公有變量同樣訪問。
__foo
:這個有真正的意義:解析器用_classname__foo 來代替這個名字,以區別和其餘類相同的命名,它沒法直接像公有成員同樣隨便訪問,經過對象名._類名__xxx 這樣的方式能夠訪問。
a. 在 python 裏凡是繼承了 object 的類,都是新式類
b. Python3 裏只有新式類
c. Python2 裏面繼承 object 的是新式類,沒有寫父類的是經典類
d. 經典類目前在 Python 裏基本沒有應用
a. 同時支持單繼承與多繼承,當只有一個父類時爲單繼承,當存在多個父類時爲多繼承。
b. 子類會繼承父類全部的屬性和方法,子類也能夠覆蓋父類同名的變量和方法。
c. 在繼承中基類的構造(__init__()
)方法不會被自動調用,它須要在其派生類的構造中專門調用。
d. 在調用基類的方法時,須要加上基類的類名前綴,且須要帶上 self 參數變量。區別於在類中調用普通函數時並不須要帶上 self 參數。
super() 函數是用於調用父類(超類)的一個方法。
class A():
def funcA(self):
print("this is func A")
class B(A):
def funcA_in_B(self):
super(B, self).funcA()
def funcC(self):
print("this is func C")
ins = B()
ins.funcA_in_B()
ins.funcC()
複製代碼
output
this is func A
this is func C
複製代碼
主要分爲實例方法、類方法和靜態方法
實例方法:
定義:第一個參數必須是實例對象,該參數名通常約定爲「self」,經過它來傳遞實例的屬性和方法(也能夠傳類的屬性和方法);
調用:只能由實例對象調用。
類方法:
定義:使用裝飾器@classmethod。第一個參數必須是當前類對象,該參數名通常約定爲「cls」,經過它來傳遞類的屬性和方法(不能傳實例的屬性和方法);
調用:實例對象和類對象均可以調用。
靜態方法:
定義:使用裝飾器@staticmethod。參數隨意,沒有「self」和「cls」參數,可是方法體中不能使用類或實例的任何屬性和方法;
調用:實例對象和類對象均可以調用。
靜態方法是類中的函數,不須要實例。靜態方法主要是用來存放邏輯性的代碼,主要是一些邏輯屬於類,可是和類自己沒有交互。即在靜態方法中,不會涉及到類中的方法和屬性的操做。能夠理解爲將靜態方法存在此類的名稱空間中。 類方法是將類自己做爲對象進行操做的方法。他和靜態方法的區別在於:無論這個方式是從實例調用仍是從類調用,它都用第一個參數把類傳遞過來。
與類和實例無綁定關係的 function 都屬於函數(function) 與類和實例有綁定關係的 function 都屬於方法(method)
普通函數:
def func1():
pass
print(func1)
複製代碼
output
<function func1 at 0x01379348>
複製代碼
類中的函數:
class People(object):
def func2(self):
pass
@staticmethod
def func3():
pass
@classmethod
def func4(cls):
pass
people = People()
print(people.func2)
print(people.func3)
print(people.func4)
複製代碼
output
<bound method People.func2 of <__main__.People object at 0x013B8C90>>
<function People.func3 at 0x01379390>
<bound method People.func4 of <class '__main__.People'>>
複製代碼
isinstance() 函數來判斷一個對象是不是一個已知的類型,相似 type()。
區別:
type() 不會認爲子類是一種父類類型,不考慮繼承關係。
isinstance() 會認爲子類是一種父類類型,考慮繼承關係。
class A(object):
pass
class B(A):
pass
a = A()
b = B()
print(isinstance(a, A))
print(isinstance(b, A))
print(type(a) == A)
print(type(b) == A)
複製代碼
output
True
True
True
False
複製代碼
單例模式:主要目的是確保某一個類只有一個實例存在。
工廠模式:包涵一個超類,這個超類提供一個抽象化的接口來建立一個特定類型的對象,而不是決定哪一個對象能夠被建立。
import os
print(os.listdir('.'))
複製代碼
# 1到5組成的互不重複的三位數
k = 0
for i in range(1, 6):
for j in range(1, 6):
for z in range(1, 6):
if (i != j) and (i != z) and (j != z):
k += 1
if k%6:
print("%s%s%s" %(i, j, z), end="|")
else:
print("%s%s%s" %(i, j, z))
複製代碼
output
1123|124|125|132|134|135
2142|143|145|152|153|154
3213|214|215|231|234|235
4241|243|245|251|253|254
5312|314|315|321|324|325
6341|342|345|351|352|354
7412|413|415|421|423|425
8431|432|435|451|452|453
9512|513|514|521|523|524
10531|532|534|541|542|543
複製代碼
str1 = " hello nihao "
str1.strip()
複製代碼
output
'hello nihao'
複製代碼
str2 = "hello you are good"
print(str2.replace(" ", ""))
"".join(str2.split(" "))
複製代碼
output
helloyouaregood
'helloyouaregood'
複製代碼
面試題系列第一部分就到這裏了,咱們下次見!
歡迎關注個人微信公衆號--蘿蔔大雜燴,或者掃描下方的二維碼,你們一塊兒交流,學習和進步!