Python中的常見面試題

解釋一下Python中的三元運算

[on true] if [expression] else [on false]

如果表達式爲True,就執行[on true]中的語句。否則,就執行[on false]中的語句

a,b=2,3
min=a if a<b else b
min

GIL: 全局解釋器鎖

GIL: 全局解釋器鎖(英語:Global Interpreter Lock,縮寫GIL),是計算機程序設計語言解釋器用於同步線程的一種機制,它使得任何時刻僅有一個線程在執行。即便在多核心處理器上,使用 GIL 的解釋器也只允許同一時間執行一個線程。

解釋一下Python中的繼承

當一個類繼承自另一個類,它就被稱爲一個子類/派生類,繼承自父類/基類/超類。它會繼承/獲取所有類成員(屬性和方法)。

繼承能讓我們重新使用代碼,也能更容易的創建和維護應用。Python支持如下種類的繼承:

單繼承:一個類繼承自單個基類
多繼承:一個類繼承自多個基類
多級繼承:一個類繼承自單個基類,後者則繼承自另一個基類
分層繼承:多個類繼承自單個基類
混合繼承:兩種或多種類型繼承的混合

解釋Python中的help()和dir()函數

Help()函數是一個內置函數,用於查看函數或模塊用途的詳細說明:

import copy
help(copy.copy)

Dir()函數也是Python內置函數,dir() 函數不帶參數時,返回當前範圍內的變量、方法和定義的類型列表;帶參數時,返回參數的屬性、方法列表。

dir(copy.copy)

什麼是猴子補丁?

在運行期間動態修改一個類或模塊。

class A:
    def func(self):
        print("Hi")
def monkey(self):
    print("Hi, monkey")
m.A.func = monkey
a = m.A()
a.func()

請解釋使用args和*kwargs的含義

當我們不知道向函數傳遞多少參數時,比如我們向傳遞一個列表或元組,我們就使用*args。

>>> def func(*args):
    for i in args:
        print(i)  
>>> func(3,2,1,4,7)

在我們不知道該傳遞多少關鍵字參數時,使用**kwargs來收集關鍵字參數。

>>> def func(**kwargs):
    for i in kwargs:
        print(i,kwargs[i])
>>> func(a=1,b=2,c=7)

什麼是負索引?

負索引和正索引不同,它是從右邊開始檢索。

它也能用於列表中的切片:

mylist=[0,1,2,3,4,5,6,7,8]
mylist[-3]
mylist[-6:-1]

解釋Python中的join()和split()函數

Join()能讓我們將指定字符添加至字符串中。

Split()能讓我們用指定字符分割字符串。

怎麼移除一個字符串中的前導空格?

字符串中的前導空格就是出現在字符串中第一個非空格字符前的空格。我們使用方法Istrip()可以將它從字符串中移除。

'   Ayushi '.lstrip()

可以看到,該字符串既有前導字符,也有後綴字符,調用Istrip()去除了前導空格。如果我們想去除後綴空格,就用rstrip()方法。

'   Ayushi '.rstrip()

Python中的pass語句是什麼?

在用Python寫代碼時,有時可能還沒想好函數怎麼寫,只寫了函數聲明,但爲了保證語法正確,必須輸入一些東西,在這種情況下,我們會使用pass語句。

def func(*args):
    pass

同樣,break語句能讓我們跳出循環。

for i in range(7):
    if i==3: break

最後,continue語句能讓我們跳到下個循環。

for i in range(7):
    if i==3: continue
    print(i)

Python中的閉包是什麼?

當一個嵌套函數在其外部區域引用了一個值時,該嵌套函數就是一個閉包。其意義就是會記錄這個值。

def A(x):
    def B():
        print(x)
    return B

談一談Python的裝飾器(decorator)

裝飾器本質上是一個Python函數,它可以讓其它函數在不作任何變動的情況下增加額外功能,裝飾器的返回值也是一個函數對象。它經常用於有切面需求的場景。比如:插入日誌、性能測試、事務處理、緩存、權限校驗等。有了裝飾器我們就可以抽離出大量的與函數功能無關的雷同代碼進行重用。

裝飾器其實就是一個閉包,把一個函數當做參數然後返回一個替代版函數

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

Python中有3個邏輯運算符:and,or,not

Python支持什麼數據類型?
Numbers(數字)——用於保存數值

Strings(字符串)——字符串是一個字符序列。我們用單引號或雙引號來聲明字符串。

Lists(列表)——列表就是一些值的有序集合,我們用方括號聲明列表。

Tuples(元組)——元組和列表一樣,也是一些值的有序集合,區別是元組是不可變的,意味着我們無法改變元組內的值。

Dictionary(字典)——字典是一種數據結構,含有鍵值對。我們用大括號聲明字典

什麼是切片?

切片是Python中的一種方法,能讓我們只檢索列表、元素或字符串的一部分。在切片時,我們使用切片操作符[]。

(1,2,3,4,5)[2:4]

Python中的不可變集合(frozenset)是什麼?

首先,我們討論一下什麼是集合。集合就是一系列數據項的合集,不存在任何副本。另外,集合是無序的。

這就意味着我們無法索引它。

不過,集合是可變的。而不可變集合卻不可變,這意味着我們無法改變它的值,從而也使其無法作爲字典的鍵值。

myset=frozenset([1,3,2,2])
myset

解釋lambda表達式,什麼時候會用到它?

如果我們需要一個只有單一表達式的函數,我們可以匿名定義它。拉姆達表達式通常是在需要一個函數,但是又不想費神去命名一個函數的場合下使用,也就是指匿名函數。

(lambda a,b:a if a>b else b)(3,3.5)

實現斐波那契數列

fib = lambda n : n if n <= 2 else fib(n-1)+fib(n-2)

什麼是遞歸?

在調用一個函數的過程中,直接或間接地調用了函數本身這個就叫遞歸。但爲了避免出現死循環,必須要有一個結束條件

def facto(n):
    if n==1: return 1
    return n*facto(n-1)
facto(4)

什麼是生成器?

生成器會生成一系列的值用於迭代,這樣看它又是一種可迭代對象。它是在for循環的過程中不斷計算出下一個元素,並在適當的條件結束for循環。

什麼是迭代器?

迭代器是訪問集合元素的一種方式。迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退。我們使用inter()函數創建迭代器。

請說說生成器和迭代器之間的區別?

在使用生成器時,我們創建一個函數;在使用迭代器時,我們使用內置函數iter()和next()。 在生成器中,我們使用關鍵字‘yield’來每次生成/返回一個對象。 生成器中有多少‘yield’語句,你可以自定義。 每次‘yield’暫停循環時,生成器會保存本地變量的狀態。而迭代器並不會使用局部變量,它只需要一個可迭代對象進行迭代。 使用類可以實現你自己的迭代器,但無法實現生成器。 生成器運行速度快,語法簡潔,更簡單。 迭代器更能節約內存。

Python中的yield用法

yield簡單說來就是一個生成器,這樣函數它記住上次返 回時在函數體中的位置。對生成器第 二次(或n 次)調用跳轉至該函 次)調用跳轉至該函數。

解釋Python的參數傳遞機制

Python使用按引用傳遞(pass-by-reference)將參數傳遞到函數中。如果你改變一個函數內的參數,會影響到函數的調用。這是Python的默認操作。不過,如果我們傳遞字面參數,比如字符串、數字或元組,它們是按值傳遞,這是因爲它們是不可變的。

python不允許程序員選擇採用傳值還是傳引用。Python參數傳遞採用的肯定是“傳對象引用”的方式。這種方式相當於傳值和傳引用的一種綜合。如果函數收到的是一個可變對象(比如字典或者列表)的引用,就能修改對象的原始值--相當於通過“傳引用”來傳遞對象。如果函數收到的是一個不可變對象(比如數字、字符或者元組)的引用,就不能直接修改原始對象--相當於通過“傳值’來傳遞對象。

如何在Python中創建自己的包?

Python中創建包是比較方便的,只需要在當前目錄建立一個文件夾,文件夾中包含一個init.py文件和若干個模塊文件,其中init.py可以是一個空文件,但還是建議將包中所有需要導出的變量放到all中,這樣可以確保包的接口清晰明瞭,易於使用。

元類

元類是類的類對象,換言之類是元類的實例,Python中默認的元類爲type,可以通過自定義元類的方式實現對類創建的控制。

class Base:
    a = 1
    b = 2

    print('class defined')

    def __new__(cls, *args, **kwargs):
        print(cls.__name__, 'class instance created')
        return super().__new__(cls)

    def __init__(self):
        print(type(self).__name__, 'class instance inited')

    def hello(self):
        pass


b = Base()

當調用print(type(b)),得到,可知b是Base類的實例。Python是純面嚮對象語言,因此類也是對象,當調用print(type(Base))時得到,可知類Base是type的實例,type就是Python中的原生元類,用來控制、生成類這個對象。 一般地,在定義類時,默認的此類的元類是type,因此,如果我們想控制類的創建,需要將類的元類指爲我們自定義的元類,這個自定義的元類需要繼承type元類。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章