Python面試題解答——第三部分Python高級

元類

42.Python中類方法、類實例方法、靜態方法有何區別?
類方法: 是類對象的方法,在定義時需要在上方使用 @classmethod 進行裝飾,形參爲cls,表示類對象,類對象和實例對象都可調用 類實例方法: 是類實例化對象的方法,只有實例對象可以調用,形參爲self,指代對象本身;

靜態方法: 是一個任意函數,在其上方使用 @staticmethod 進行裝飾,可以用對象直接調用,靜態方法實際上跟該類沒有太大關係

43.遍歷一個object的所有屬性,並print每一個屬性名?

class Car:
    def __init__(self,name,loss): # loss [價格,油耗,公里數]
        self.name = name
        self.loss = loss
    
    def getName(self):
        return self.name
    
    def getPrice(self):
        # 獲取汽車價格
        return self.loss[0]
    
    def getLoss(self):
        # 獲取汽車損耗值
        return self.loss[1] * self.loss[2]

Bmw = Car("寶馬",[60,9,500]) # 實例化一個寶馬車對象
print(getattr(Bmw,"name")) # 使用getattr()傳入對象名字,屬性值。
print(dir(Bmw)) # 獲Bmw所有的屬性和方法

46.請描述抽象類和接口類的區別和聯繫

1.抽象類: 規定了一系列的方法,並規定了必須由繼承類實現的方法。由於有抽象方法的存在,所以抽象類不能實例化。可以將抽象類理解爲毛坯房,門窗,牆面的樣式由你自己來定,所以抽象類與作爲基類的普通類的區別在於約束性更強

2.接口類:與抽象類很相似,表現在接口中定義的方法,必須由引用類實現,但他與抽象類的根本區別在於用途:與不同個體間溝通的規則,你要進宿舍需要有鑰匙,這個鑰匙就是你與宿舍的接口,你的舍友也有這個接口,所以他也能進入宿舍,你用手機通話,那麼手機就是你與他人交流的接口

3.區別和關聯: 1.接口是抽象類的變體,接口中所有的方法都是抽象的,而抽象類中可以有非抽象方法,抽象類是聲明方法的存在而不去實現它的類 2.接口可以繼承,抽象類不行 3.接口定義方法,沒有實現的代碼,而抽象類可以實現部分方法

4.接口中基本數據類型爲static而抽象類不是

47.Python中如何動態獲取和設置對象的屬性?

if hasattr(Parent, 'x'):
    print(getattr(Parent, 'x'))
    setattr(Parent, 'x',3)
print(getattr(Parent,'x'))

內存管理與垃圾回收機制

48.哪些操作會導致Python內存溢出,怎麼處理?

49.關於Python內存管理,下列說法錯誤的是 B

A,變量不必事先聲明 B,變量無須先創建和賦值而直接使用

C,變量無須指定類型 D,可以使用del釋放資源

50.Python的內存管理機制及調優手段?

內存管理機制: 引用計數、垃圾回收、內存池

引用計數:引用計數是一種非常高效的內存管理手段,當一個Python對象被引用時其引用計數增加1,

當其不再被一個變量引用時則計數減1,當引用計數等於0時對象被刪除。弱引用不會增加引用計數

垃圾回收:

1.引用計數

引用計數也是一種垃圾收集機制,而且也是一種最直觀、最簡單的垃圾收集技術。當Python的某個對象的引用計數降爲0時,說明沒有任何引用指向該對象,該對象就成爲要被回收的垃圾了。比如某個新建對象,它被分配給某個引用,對象的引用計數變爲1,如果引用被刪除,對象的引用計數爲0,那麼該對象就可以被垃圾回收。不過如果出現循環引用的話,引用計數機制就不再起有效的作用了。

2.標記清除

https://foofish.net/python-gc.html

調優手段

1.手動垃圾回收

2.調高垃圾回收閾值

3.避免循環引用

51.內存泄露是什麼?如何避免?

內存泄漏指由於疏忽或錯誤造成程序未能釋放已經不再使用的內存。內存泄漏並非指內存在物理上的消失,而是應用程序分配某段內存後,由於設計錯誤,導致在釋放該段內存之前就失去了對該段內存的控制,從而造成了內存的浪費。

__del__()函數的對象間的循環引用是導致內存泄露的主兇。不使用一個對象時使用: del object 來刪除一個對象的引用計數就可以有效防止內存泄露問題。

通過Python擴展模塊gc 來查看不能回收的對象的詳細信息。

可以通過 sys.getrefcount(obj) 來獲取對象的引用計數,並根據返回值是否爲0來判斷是否內存泄露

59.編寫函數的4個原則

1.函數設計要儘量短小

2.函數聲明要做到合理、簡單、易於使用

3.函數參數設計應該考慮向下兼容

4.一個函數只做一件事情,儘量保證函數語句粒度的一致性

60.函數調用參數的傳遞方式是值傳遞還是引用傳遞?

Python的參數傳遞有:位置參數、默認參數、可變參數、關鍵字參數。

函數的傳值到底是值傳遞還是引用傳遞、要分情況:

不可變參數用值傳遞:像整數和字符串這樣的不可變對象,是通過拷貝進行傳遞的,因爲你無論如何都不可能在原處改變不可變對象。

可變參數是引用傳遞:比如像列表,字典這樣的對象是通過引用傳遞、和C語言裏面的用指針傳遞數組很相似,可變對象能在函數內部改變。

75.什麼是lambda函數? 有什麼好處?

lambda 函數是一個可以接收任意多個參數(包括可選參數)並且返回單個表達式值的函數

1.lambda函數比較輕便,即用即仍,很適合需要完成一項功能,但是此功能只在此一處使用,連名字都很隨意的情況下

2.匿名函數,一般用來給filter,map這樣的函數式編程服務

3.作爲回調函數,傳遞給某些應用,比如消息處理

76.遞歸函數停止的條件?

遞歸的終止條件一般定義在遞歸函數內部,在遞歸調用前要做一個條件判斷,根據判斷的結果選擇是繼續調用自身,還是return,,返回終止遞歸。

終止的條件:判斷遞歸的次數是否達到某一限定值

2.判斷運算的結果是否達到某個範圍等,根據設計的目的來選擇

設計模式

79.對設計模式的理解,簡述你瞭解的設計模式?

設計模式是經過總結,優化的,對我們經常會碰到的一些編程問題的可重用解決方案。一個設計模式並不像一個類或一個庫那樣能夠直接作用於我們的代碼,反之,設計模式更爲高級,它是一種必須在特定情形下實現的一種方法模板。 常見的是工廠模式和單例模式

面向對象

90.Python中的可變對象和不可變對象?

不可變對象,該對象所指向的內存中的值不能被改變。當改變某個變量時候,由於其所指的值不能被改變,相當於把原來的值複製一份後再改變,這會開闢一個新的地址,變量再指向這個新的地址。

可變對象,該對象所指向的內存中的值可以被改變。變量(準確的說是引用)改變後,實際上其所指的值直接發生改變,並沒有發生複製行爲,也沒有開闢出新的地址,通俗點說就是原地改變。

Pyhton中,數值類型(int 和float),字符串str、元祖tuple都是不可變類型。而列表list、字典dict、集合set是可變類型

91.Python的魔法方法

魔法方法就是可以給你的類增加魔力的特殊方法,如果你的對象實現(重載)了這些方法中的某一個,那麼這個方法就會在特殊的情況下被Python所調用,你可以定義自己想要的行爲,而這一切都是自動發生的,它們經常是兩個下劃線包圍來命名的(比如__init___,__len__),Python的魔法方法是非常強大的所以瞭解其使用方法也變得尤爲重要!

__init__構造器,當一個實例被創建的時候初始化的方法,但是它並不是實例化調用的第一個方法。

__new__纔是實例化對象調用的第一個方法,它只取下cls參數,並把其他參數傳給__init___.

___new__很少使用,但是也有它適合的場景,尤其是當類繼承自一個像元祖或者字符串這樣不經常改變的類型的時候。

__call__讓一個類的實例像函數一樣被調用

__getitem__定義獲取容器中指定元素的行爲,相當於self[key]

__getattr__定義當用戶試圖訪問一個不存在屬性的時候的行爲。

__setattr__定義當一個屬性被設置的時候的行爲

__getattribute___定義當一個屬性被訪問的時候的行爲

92.面向對象中怎麼實現只讀屬性?

將對象私有化,通過共有方法提供一個讀取數據的接口

class person:
    def __init__(self, x):
        self.__age = 10
    def age(self):
        return self.__age
t = person(22)
# t.__age =100
print(t.age())

最好的方法

class MyCls(object):
    __weight = 50
    
    @property
    def weight(self):
        return self.__weight

 

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