Python高階知識點學習(五)
dict的子類
首先,不建議自己編寫程式碼繼承dict和list這種原生使用c語言編寫的,因為有時候,用c語言寫的dict不會呼叫python寫的覆蓋的方法。
如果確實有繼承dict來寫程式碼的需求,可以使用UserDict,繼承這個UserDict。
UserDict這個內部使用了python語言實現了c語言寫的邏輯。
from collections import UserDict
class Mydict(UserDict):
def __setitem__(self, key, value):
super().__setitem__(key, value*2)
my_dict = Mydict(one=1)
print (my_dict)
列印結果:
{`one`: 2}
set和fronzenset
set集合:
- 無序
- 不重複
- set 接受一個可迭代物件
frozenset集合:
- 一旦設定好就無法修改。
- frozenset為不可變型別。
- 相對於可變型別來說的好處,可以作為dict的key。
set的初始化方法:
set([a, b, c])
a = {a, b, c}
兩種都可以初始化
dict、set實現原理
當我們瞭解了背後的實現原理,就可以判斷什麼情況下使用dict以及為什麼要使用dict。
dict查詢的效能遠遠大於list。
在list中隨著list資料的增大 查詢時間會增大。
在dict中查詢元素不會隨著dict的增大而增大。
dict原理實際上就是利用hash演算法。
陣列和連結串列相比來說最大的優勢,就是它可以做到任何一個位置直接存取而不需要從頭到尾遍歷,因為陣列是一段連續的空間,陣列取資料的時間複雜度是O(1)。
dict的key或者set的值,都必須是可以hash的。不可變物件都是可hash的, str, fronzenset, tuple。
自己實現的類過載__hash__
這個魔法函式,讓它可以變為可雜湊物件。
dict的記憶體花銷大,但是查詢速度快, 自定義的物件或者python內部的物件都是用dict包裝的。
dict的儲存順序和元素新增順序有關,新增資料有可能改變已有資料的順序。
Python中的變數是什麼
python和java中的變數本質不一樣,python的變數實質上是一個指標。我們可以理解變數就是一個便利貼,
例如:a = 1
先成物件,然後貼便利貼,把a貼在1上面。
a = [1, 2, 3]
b = a
print(id(a), id(b))
列印結果:
a和b的地址值一樣。
is 和 == 的區別
is是判斷物件的id是否相同,但是注意看下邊例子:
a = [1, 2, 3, 4]
b = [1, 2, 3, 4]
print (id(a), id(b))
print (a is b)
輸出結果:
4446597320 4446597640
False
上邊這種用法得到的結果很正常,再看下邊程式碼:
a = 1
b = 1
print (id(a), id(b))
print (a is b)
執行結果:
4325627840 4325627840
True
這種情況下,a和b指向的是同一個。這是由於Python內部機制決定的,將小正數建立一個全域性唯一的物件,小段字串也是一樣的。
a = [1, 2, 3]
b = [1, 2, 3]
print(a==b) 返回True
因為:
list裡邊實現了一個魔法函式 __eq__
,當我們呼叫a==b這種模式的時候,會呼叫__eq__
這個魔法函式,從而來判斷值是否相等。
它們的值是相等的,只是不是同一個物件而已,所有a==b是True。
垃圾回收和del語句
cpython中垃圾回收的演算法是採用 引用計數
a = 1
b = a
此時,1這個物件上就又有一個計數器,a = 1 時會在計數器上加1,b如果指向的還是1,1上邊的計數器會再加1,當不使用時,執行del a,他就會將引用計數器減1,當引用計數器減到0時,python直譯器會將物件回收。
物件只有在計數器減到0時,才會被回收,del只是減計數器的功能。
a = object()
b = a
del a
print(b)
print(a)
列印結果:
<object object at 0x104a86100>
NameError: name `a` is not defined
可以看到,執行del後,只是把a銷燬了,b還在。
__del__
魔法函式:
可以在__del__
魔法函式中實現自己的邏輯,當python直譯器回收物件的時候,會呼叫物件的__del__
魔法函式,它可以幫我們在回收物件時做一些事。
@property的用法
我們在讀原始碼時,往往會看到這這種方法:
@property
def hello(self):
pass
@property 這個裝飾器會把函式變為屬性描述符,怎麼說?
看程式碼:
class Allen(object):
def word(self):
return `word`
@property
def hello(self):
return `hello`
a = Allen()
print(a.hello)
print(a.word())
執行結果:
hello
word
可以發現,@property這個裝飾器把取方法的模式變為取屬性。
魔法函式__getattr__
、__getattribute__
介紹
魔法函式是python直譯器內部需要用的方法,它是整個python動態特性的最根本原因。
__getattr__
:就是在查詢不到屬性的時候呼叫。
例1:
class User:
def __init__(self, info):
self.info = info
def __getattr__(self, item):
return `2`
if __name__ == "__main__":
user = User(`allen`)
print(user.info)
print(user.age)
執行結果:
allen
2
例2:
class User:
def __init__(self, info={}):
self.info = info
def __getattr__(self, item):
return self.info[item]
if __name__ == "__main__":
user = User(info={"name": "allen", "age": "3"})
print(user.name)
列印結果:
allen
__getattribute__
: 比__getattr__
更高階,只要查詢屬性,就會首先進入__getattribute__
這個魔法函式,強制進入,無條件的。
__getattribute__
這個魔法函式儘量不要去重寫,因為如果一旦寫不好,整個類的屬性訪問就會崩潰掉,一般寫框架時會用到這個魔法函式。
class User:
def __init__(self,info={}):
self.info = info
def __getattr__(self, item):
return self.info[item]
def __getattribute__(self, item):
return "10"
if __name__ == "__main__":
user = User(info={"name":"allen"})
print(user.name)
print(user.test)
列印結果:
10
10
屬性描述符和屬性查詢過程
一個類只需要實現__get__
、__set__
、__delete__
這三個中的任意一個方法,它就算是屬性描述符。
通過屬性描述符,可以控制在賦值的時候它的行為,在屬性設定的時候引數檢查。
屬性描述符有兩種:
- 資料屬性描述符:實現
__get__
和__set__
就是資料屬性描述符。 - 非資料屬性描述符:只實現一個
__get__
方法就是非資料屬性描述符。
資料屬性描述符 和 非資料屬性描述符 它們的屬性查詢過程是不一樣的。
前邊提到的屬性查詢過程,先查詢例項中的屬性,然後查詢類中的屬性,實際上它有更加詳細的查詢過程。
魔法函式__new__
和 __init__
區別
__new__
魔法函式在python新式類才會有 python2.2之前沒有這個。
class User:
def __new__(cls, *args, **kwargs):
print(" in new ")
return super().__new__(cls)
def __init__(self):
print(" in init")
pass
if __name__ == "__main__":
user = User()
列印結果:
in new
in init
__new__
魔法函式允許在生成物件之前加邏輯,自定義物件生成過程,傳遞進來的是類。
__init__
方法傳遞進去的是物件。
__new__
在 __init__
之前呼叫。
__new__
中必須return super().__new__(cls)
才會呼叫__init__方法
。
def __new__(cls, *args, **kwargs):
這個中的*args
,和**kwargs
,代表的是傳入的引數。
相關文章
- java知識點-高階Java
- Android高階知識點Android
- 網頁高階知識點(二)網頁
- (小白學JAVA之)Java高階特性知識點梳理Java
- Python全棧學習_day003知識點Python全棧
- Python全棧學習_day001知識點Python全棧
- python面試中較常問及的知識點梳理---高階特性Python面試
- 高階 Java 面試通關知識點整理Java面試
- 學習記錄 -- 知識點
- 未雨綢繆:Java高階架構進階必學之⑥大知識要點附視訊學習資料Java架構
- 後端知識點總結——NODE.JS(高階)後端Node.js
- 高階 Java 必須突破的 10 個知識點!Java
- 高階Java必須突破的10個知識點!Java
- JAVA高階面試必過知識點彙總Java面試
- Bootstrap 個人學習知識點boot
- jQuery 個人學習知識點jQuery
- Vue學習知識點總結Vue
- MySQL高階知識——Show ProfileMySql
- 高階前端知識架構前端架構
- Python學習-字串的基本知識Python字串
- 小白階段如何學習Web前端知識Web前端
- 前端知識點總結——JS高階(持續更新中)前端JS
- (五)numpy知識學習2-python資料分析與機器學習實戰(學習筆記)Python機器學習筆記
- 【Python學習教程】Python的5種高階用法!Python
- 【java學習】java知識點總結Java
- JS 學習個人知識盲點JS
- React學習筆記知識點整理React筆記
- 機器學習知識點整理(三)機器學習
- PG知識點學習總結圖
- Python知識點(二)Python
- Python知識點(一)Python
- Mysql知識樹整理【3】 ---高階MySql
- 哪些人都在學習Python知識?Python
- netcore高階知識點,記憶體對齊,原理與示例NetCore記憶體
- C++ 字串完全指南:學習基礎知識到掌握高階應用技巧C++字串
- 高階NumPy知識圖譜-《利用Python進行資料分析》Python
- 學習 Laravel 必須理解的知識點Laravel
- 大資料學習,涉及的知識點大資料