首頁  >  文章  >  後端開發  >  我們一起聊聊 Python 八股文

我們一起聊聊 Python 八股文

WBOY
WBOY轉載
2023-04-13 15:10:034324瀏覽

同志們好,今天帶著大家一起來複習python中的基礎問題,我們都知道python屬於解釋性語言,效率也就相對其它語言來說較低一些,這個較低只是運行稍微低些,但是呢,在很多場景買這些都是微不足道的

憑藉著語法的易於理解和學習,可以在短時間內完成更多工作,開發效率也會變得更高

同時,python自帶了各種現成的函式庫,供我們在開發程式中使用,python也比較容易維護

Python為我們提供了非常完善的基礎程式碼庫,涵蓋了網路、檔案、GUI、資料庫、文字等大量內容,被形象化地稱作「內建電池(batteries included)」。用Python開發,許多功能不必從零編寫,直接使用現成的即可。

除了內建的函式庫外,Python還有大量的第三方函式庫,也就是別人開發的,供你直接使用的東西。當然,如果你開發的程式碼通過很好的封裝,也可以作為第三方函式庫給別人使用。

什麼是 Python 產生器?

generator,有兩種產生生成器物件的方式:一種是列表產生式加括號:

g1 = (x for x in range(10) )

一種是在函數定義中包含yield關鍵字:

def fib(max):
n, a, b = 0, 0, 1
while n < max:yield b
a, b = b, a + b
n = n + 1
return 'done'g2 = fib(8)

# 對於generator物件g1和g2,可以透過next(g1)不斷得到下一個元素的值,如果沒有更多的元素,就會報錯StopIteration

也可以透過for迴圈得到元素的值。

生成器的好處是不用佔用很多內存,只需要在用的時候計算元素的值就行了。

什麼是 Python 迭代器?

Python中可以用於for循環的,叫做可迭代Iterable,包括list/set/tuple/str/dict等資料結構以及生成器;可以用以下語句判斷一個對象是否是可迭代的:

from collections import Iterableisinstance(x, Iterable)

 迭代器Iterator,是指可以被next()函數呼叫並不斷返回下一個值,直到StopIteration;生成器都是Iterator,而列表等資料結構不是;

可以透過以下語句將list變成Iterator:

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

#產生器都是Iterator,但迭代器不一定是生成器。

list 和 tuple 有什麼差別?

  • list 長度可變,tuple不可變;
  • #list 中元素的值可以改變,tuple 不能改變;
  • list 支持append; insert; remove; pop等方法,tuple 都不支援

#Python 中的list 和dict 是怎麼實現的?

List:    本質是順序表,只不過每次表的擴容都是指數級,所以動態增刪資料時,表並不會頻繁改變物理結構,同時受益於順序表遍歷的高效性(透過角標配合表頭物理位址,計算目標元素的位置),使得python的list綜合性能比較優秀

dict:  本質上是順序表,不過每個元素儲存位置的角標,不是又插入順序決定的,而是由key經過hash演算法和其他機制,動態生成的,即key透過hash散列,生成value應該儲存的位置,然後再去存儲這個value;所以dict的查詢時間複雜度是o(1);

因此,dict的key只能為可hash的對象,即不可變型別;

Python 中使用多執行緒可以達到多核心CPU一起使用嗎?

Python中有一個被稱為Global Interpreter Lock(GIL)的東西,它會確保任何時候你的多個執行緒中,只有一個被執行。

執行緒的執行速度非常之快,會讓你誤以為執行緒是並行執行的,但是實際上都是輪流執行。經過GIL這一道關卡處理,會增加執行的開銷。

可以透過多進程實現多核心任務。

py3和py2的差別

#print在py3裡是一個函數,在py2裡只是一個關鍵字

py3檔案的預設編碼是utf8,py2檔案的預設編碼是ascii

#py3的str是unicode字串,而py2的str是bytes

py3的range()傳回一個可迭代對象,py2的range()傳回一個列表,xrange()傳回一個可迭代對象,py3的除法回傳float,py2的除法回傳int

可變物件與不可變物件

可變物件: list,dict,set

不可變物件: bool,int,float,tuple,str…

#迭代器與可迭代物件的區別

可迭代對象類,必須自訂__iter__()魔法方法,range,list類的實例化物件都是可迭代物件

迭代器類,必須自訂__iter__()和_ _next__()魔法方法,用iter()函數可以建立可迭代物件的迭代器

#閉包

##。閉包就是一個嵌套函數,它的內部函數使用了外部函數的變數或參數,它的外部函數傳回了內部函數

可以保存外部函数内的变量,不会随着外部函数调用完而销毁

什么是装饰器?

装饰器是一个接收函数作为参数的闭包函数

它可以在不修改函数内部源代码的情况下,给函数添加额外的功能

import time
def calc_time(func):
def inner():
t1 = time.time()
func()
t2 = time.time()
print('cost time: {}s'.format(t2-t1))
return inner

什么是元类? 使用场景

元类是创建类的类,type还有继承自type的类都是元类

作用: 在类定义时(new, init)和 类实例化时(call) 可以添加自定义的功能

使用场景: ORM框架中创建一个类就代表数据库中的一个表,但是定义这个类时为了统一需要把里面的类属性全部改为小写,这个时候就要用元类重写new方法,把attrs字典里的key转为小写

GIL(Global Interpreter Lock)

全局解释器锁

全局解释器锁(Global Interpreter Lock)是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。

即便在多核处理器上,使用 GIL 的解释器也只允许同一时间执行一个线程,常见的使用 GIL 的解释器有CPython与Ruby MRI。可以看到GIL并不是Python独有的特性,是解释型语言处理多线程问题的一种机制而非语言特性。

GIL的设计初衷?

单核时代高效利用CPU, 针对解释器级别的数据安全(不是thread-safe 线程安全)。首先需要明确的是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。

当Python虚拟机的线程想要调用C的原生线程需要知道线程的上下文,因为没有办法控制C的原生线程的执行,所以只能把上下文关系传给原生线程,同理获取结果也是线 程在python虚拟机这边等待。那么要执行一次计算操作,就必须让执行程序的线程组串行执行。

为什么要加在解释器,而不是在其他层?

展开 GIL锁加在解释器一层,也就是说Python调用的Cython解释器上加了GIL锁,因为你python调用的所有线程都是原生线程。原生线程是通过C语言提供原生接口,相当于C语言的一个函数。

你一调它,你就控制不了了它了,就必须等它给你返回结果。只要已通过python虚拟机 ,再往下就不受python控制了,就是C语言自己控制了。

加在Python虚拟机以下加不上去,只能加在Python解释器这一层。

GIL的实现是线程不安全?为什么?

python2.x和3.x都是在执行IO操作的时候,强制释放GIL,使其他线程有机会执行程序。

Python2.x Python使用计数器ticks计算字节码,当执行100个字节码的时候强制释放GIL,其他线程获取GIL继续执行。ticks可以看作是Python自己的计数器,专门作用于GIL,释放后归零,技术可以调整。

Python3.x Python使用计时器,执行时间达到阈值后,当前线程释放GIL。总体来说比Python3.x对CPU密集型任务更好,但是依然没有解决问题。

什么是 lambda 表达式?

简单来说,lambda表达式通常是当你需要使用一个函数,但是又不想费脑袋去命名一个函数的时候使用,也就是通常所说的匿名函数。

lambda表达式一般的形式是:关键词lambda后面紧接一个或多个参数,紧接一个冒号“:”,紧接一个表达式

什么是深拷贝和浅拷贝?

赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。

浅拷贝 copy.copy:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变)

深拷贝:创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变){copy模块的deep.deepcopy()函数}​

以上是我們一起聊聊 Python 八股文的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:51cto.com。如有侵權,請聯絡admin@php.cn刪除