這邊有幾個面試題,好棒
第1題:你如何管理不同版本的程式碼?
git,svn兩個都要說到,github,碼雲也要提及,面試官想要的就是版本管理工具,你只要選擇一個你熟悉的,瘋狂的說一通就可以了,最好說一下自己以前做過哪些開源的專案,放在上面,沒有,就另當別論了。
第2題:python中生成隨機整數、隨機小數、0~1之間小數方法?
python中生成隨機整數
import random
random.randint(1,10)
隨機小數
看自己習慣,可以用random庫,也可以用numpy庫
import random
random.random()
# 利用np.random.randn(5)生成5個隨機小數
import numpy as np
np.random.randn(5)
0~1之間小數
random.random()
第3題:迭代器、可迭代物件、生成器?
第一步,你要知道什麼是迭代
對list、tuple、str等型別的資料使用for...in...的迴圈語法從其中依次拿到資料進行使用,我們把這樣的過程稱為遍歷,也叫迭代
。
從結果去分析原因,能被for迴圈的就是“可迭代的”,但是如果正著想,for怎麼知道誰是可迭代的呢?
假如我們自己寫了一個資料型別,希望這個資料型別裡的東西也可以使用for被一個一個的取出來,那我們就必須滿足for的要求--- 這個要求就叫做 協議
。
可以被迭代
要滿足的要求就叫做:可迭代協議
。
可迭代協議的定義非常簡單,就是內部實現了__iter()__
方法
如果某個物件中有_ iter _()
方法,這個物件就是可迭代物件
(Iterable)
if '__iter__' in dir(str)
通俗易懂 :可以被for迴圈迭代的物件就是可迭代物件。
從程式碼上面可以使用isinstance()判斷一個物件是否是Iterable物件
from collections import Iterable
a = isinstance([], Iterable)
b = isinstance({}, Iterable)
c = isinstance('abc', Iterable)
d = isinstance((x for x in range(10)), Iterable)
e = isinstance(100, Iterable)
print(a,b,c,d,e)
結論
True True True True False
只有最後的數字不是可迭代物件
可迭代物件的本質
我們分析對可迭代物件進行迭代使用的過程,發現每迭代一次(即在for...in...中每迴圈一次)都會返回物件中的下一條資料,一直向後讀取資料直到迭代了所有資料後結束。
那麼,在這個過程中就應該有一個“人”去記錄每次訪問到了第幾條資料,以便每次迭代都可以返回下一條資料。
我們把這個能幫助我們進行資料迭代的“人”稱為迭代器(Iterator)
可迭代物件的本質就是可以 向我們提供一個這樣的中間“人”即迭代器 幫助我們對其進行迭代遍歷使用。
可迭代物件通過__iter__
方法向我們提供一個迭代器,在迭代一個可迭代物件的時候,實際上就是先獲取該物件提供的一個迭代器,然後通過這個迭代器來依次獲取物件中的每一個資料。
綜上所述,一個具備了__iter__
方法的物件,就是一個可迭代物件。
class MyList(object):
def __init__(self):
self.container = []
def add(self, item):
self.container.append(item)
def __iter__(self):
"""返回一個迭代器"""
# 我們暫時忽略如何構造一個迭代器物件
pass
mylist = MyList()
from collections import Iterable
isinstance(mylist, Iterable)
iter()函式與next()函式
list
、tuple
等都是可迭代物件,我們可以通過iter()
函式獲取這些可迭代物件的迭代器。
然後我們可以對獲取到的迭代器不斷使用next()函式來獲取下一條資料。iter()函式實際上就是呼叫了可迭代物件的__iter__
方法。
>>> i = iter('spam')
>>> next(i)
's'
>>> next(i)
'p'
>>> next(i)
'a'
>>> next(i)
'm'
>>> next(i)
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
next(i)
StopIteration
>>>
當序列遍歷完時,將丟擲一個
StopIteration異常
。這將使迭代器與迴圈相容,因為它們將捕獲這個異常以停止迴圈。
要建立定製的迭代器,可以編寫一個具有next方法
的類。
迭代器Iterator
通過上面的分析,現在你應該已經知道了,迭代器是用來幫助我們記錄每次迭代訪問到的位置,當我們對迭代器使用next()
函式的時候,迭代器會向我們返回它所記錄位置的下一個位置的資料。
實際上,在使用next()
函式的時候,呼叫的就是迭代器物件的__next__
方法(Python3中是物件的__next__
方法,Python2中是物件的next()
方法)。
所以,我們要想構造一個迭代器,就要實現它的__next__
方法。但這還不夠,python要求迭代器本身也是可迭代的,所以我們還要為迭代器實現__iter__
方法,而__iter__
方法要返回一個迭代器,迭代器自身正是一個迭代器,所以迭代器的__iter__
方法返回自身即可。
一個實現了__iter__
方法和__next__
方法的物件,就是迭代器。
class MyList(object):
"""自定義的一個可迭代物件"""
def __init__(self):
self.items = []
def add(self, val):
self.items.append(val)
def __iter__(self):
myiterator = MyIterator(self)
return myiterator
class MyIterator(object):
"""自定義的供上面可迭代物件使用的一個迭代器"""
def __init__(self, mylist):
self.mylist = mylist
# current用來記錄當前訪問到的位置
self.current = 0
def __next__(self):
if self.current < len(self.mylist.items):
item = self.mylist.items[self.current]
self.current += 1
return item
else:
raise StopIteration
def __iter__(self):
return self
if __name__ == '__main__':
mylist = MyList()
mylist.add(1)
mylist.add(2)
mylist.add(3)
mylist.add(4)
mylist.add(5)
for num in mylist:
print(num)
本部分程式碼來源: https://blog.csdn.net/weixin_42225318/article/details/81274348 博主這篇部落格寫的真好
可迭代物件與迭代器
- 可迭代物件包含迭代器。
- 如果一個物件擁有
__iter__
方法,那麼它是可迭代物件;如果一個物件擁有next
方法,其是迭代器。 - 定義可迭代物件,必須實現
__iter__
方法;定義迭代器,必須實現__iter__
和next
方法。
_iter_()
該方法返回的是當前物件的迭代器類的例項。因為可迭代物件與迭代器都要實現這個方法next()
返回迭代的每一步,實現該方法時注意要最後超出邊界要丟擲StopIteration異常。
迭代器一定是可迭代物件,反過來則不一定成立。用iter()函式可以把list、dict、str等Iterable變成Iterator
生成器
- 生成器是一種特殊的迭代器,生成器
自動
實現了“迭代器協議”(即__iter__
和next
方法),不需要再手動實現兩方法。 - 生成器在迭代的過程中可以改變當前迭代值,而修改普通迭代器的當前迭代值往往會發生異常,影響程式的執行。
- 具有
yield關鍵字
的函式都是生成器,yield
可以理解為return
,返回後面的值給呼叫者。不同的是return
返回後,函式會釋放,而生成器則不會。在直接呼叫next
方法或用for語句進行下一次迭代時,生成器會從yield下一句開始執行,直至遇到下一個yield。
第4題:單引號,雙引號,三引號的區別?
單引號和雙引號主要用來表示字串
比如: 單引號:'python' 雙引號:"python"
三引號
三單引號:'''python ''',也可以表示字串一般用來輸入多行文字,或者用於大段的註釋;
三雙引號:"""python""",一般用在類裡面,用來註釋類,這樣省的寫文件,直接用類的物件__doc__
訪問獲得文件。
區別
若你的字串裡面本身包含單引號,必須用雙引號
例子:"can't find the log\n"
第5題:Python是如何進行記憶體管理的?
物件的引用計數機制
Python內部使用引用計數,來保持追蹤記憶體中的物件,所有物件都有引用計數。
引用計數增加的情況:
總結一下物件會在一下情況下引用計數加1:
- 物件被建立:x='spam'
- 另外的別人被建立:y=x
- 被作為引數傳遞給函式:foo(x)
- 作為容器物件的一個元素:a=[1,x,'33']
引用計數減少情況
- 一個本地引用離開了它的作用域。比如上面的foo(x)函式結束時,x指向的物件引用減1。
- 物件的別名被顯式的銷燬:del x ;或者del y
- 物件的一個別名被賦值給其他物件:x=789
- 物件從一個視窗物件中移除:myList.remove(x)
- 視窗物件本身被銷燬:del myList,或者視窗物件本身離開了作用域。
垃圾回收
- 當記憶體中有不再使用的部分時,垃圾收集器就會把他們清理掉。它會去檢查那些引用計數為0的物件,然後清除其在記憶體的空間。當然除了引用計數為0的會被清除,還有一種情況也會被垃圾收集器清掉:當兩個物件相互引用時,他們本身其他的引用已經為0了。
- 垃圾回收機制還有一個迴圈垃圾回收器, 確保釋放迴圈引用物件(a引用b, b引用a, 導致其引用計數永遠不為0)。
在Python中,許多時候申請的記憶體都是小塊的記憶體,這些小塊記憶體在申請後,很快又會被釋放,由於這些記憶體的申請並不是為了建立物件,所以並沒有物件一級的記憶體池機制。這就意味著Python在執行期間會大量地執行malloc和free的操作,頻繁地在使用者態和核心態之間進行切換,這將嚴重影響Python的執行效率。為了加速Python的執行效率,Python引入了一個記憶體池機制,用於管理對小塊記憶體的申請和釋放。
記憶體池機制
- Python提供了對記憶體的垃圾收集機制,但是它將不用的記憶體放到記憶體池而不是返回給作業系統;
- Pymalloc機制:為了加速Python的執行效率,Python引入了一個記憶體池機制,用於管理對小塊記憶體的申請和釋放;
- 對於Python物件,如整數,浮點數和List,都有其獨立的私有記憶體池,物件間不共享他們的記憶體池。也就是說如果你分配又釋放了大量的整數,用於快取這些整數的記憶體就不能再分配給浮點數。
第6題:寫一個函式, 輸入一個字串, 返回倒序排列的結果?
使用字串本身的翻轉
def order_by(str):
return str[::-1]
print(order_by('123456'))
輸出:654321
把字串變為列表,用列表的reverse函式
def reverse2(text='abcdef'):
new_text=list(text)
new_text.reverse()
return ''.join(new_text)
reverse2('abcdef')
新建一個列表,從後往前取
def reverse3(text='abcdef'):
new_text=[]
for i in range(1,len(text)+1):
new_text.append(text[-i])
return ''.join(new_text)
reverse3('abcdef')
利用雙向列表deque中的extendleft函式
from collections import deque
def reverse4(text='abcdef'):
d = deque()
d.extendleft(text)
return ''.join(d)
reverse4('abcdef')
微信搜尋:非本科程式設計師
關注微信公眾號「非本科程式設計師」,獲取2T學習資源