python 魔法函数 __add___PythonI/O进阶学习笔记_2.魔法函数
前言:
本文一切觀點和測試代碼是在python3的基礎上。
Content:
1.什么是魔法函數,魔法函數__getitem__在python中應用。
2.python的數據模型和數據模型這種設計對python的影響
3.python常用的魔法函數
4.從len()方法看魔法函數的特點
5.魔法函數知識小結
一? ?python的魔法函數
1.什么是魔法函數?
魔法函數是Python中定義的,以__開頭,__結尾,形如__fun__()的函數,一般使用已經定義好了的即可。
使用這樣一些函數,可以讓我們自定義的類有更加強大的特性。
魔法函數一般是隱式調用的,不需要我們顯示調用。(即python解釋器幫我們調用實現)
2.如何使用魔法函數?
例:我們建立一個公司類,里面有員工列表屬性。需要循環打印所有員工。
普通方法為:
1 classCompany:2 def __init__(self,employee_list):3 self.employee=employee_list4 user_list=['ttr1','ttrr2','ttrr3']5 company=Company(user_list)6 for i incompany.employee:7 print(i)
如果說我們用python一個內置的魔法函數的話:
user_list=['ttr1','ttrr2','ttrr3']
company=Company(user_list)classCompany_Magic:def __init__(self,employee_list):
self.employee_list=employee_listdef __getitem__(self, item):returnself.employee_list[item]
company2=Company_Magic(user_list)for i incompany2:print(i)
區別:第二種直接對對象進行了for循環,第一種對對象里面的一個屬性(list)進行循環。
就是第二種Company_Magic類生成的對象,是有可以迭代這個特性的。
因為__getitem__幫我們實現了一個邏輯,每次我們實現for循環的時候,for會去找company2這個對象中的__getitem__方法(實際上是先找另外一個迭代方法),并且傳入0、1、2...直到拋了異常然后結束。這是解釋器幫我們實現的功能。
ps.想想看如果__getitem__這個函數不管傳入什么item都不報異常會怎么樣?
二? python的數據模型和數據模型這種設計模式賦予python的特性
1.什么是數據模型?
數據模型其實是對 Python 框架的描述,它規范了這門語言自身構建模塊的接口,這些模塊包括但不限于序列、迭代器、函數、類等。
而魔法函數就是數據模型的一個概念。java中常被叫魔術方法,python常叫數據模型。
2.數據模型對python的影響
魔法函數不屬于定義它的那個類,只是增強了類的一些功能。
實現了特定的魔法函數之后,某些操作會變得特別簡單。
我們可以采用實現魔法函數來靈活地設計我們需要的類。
這點是很重要的需要明白python的類有些特性是可以被靈活設計的,只要在編碼中讓它遵循了某種特定的協議(魔法函數)。
三 python常用的魔法函數
__init__:最常用。
__str__:被print函數調用;這個魔法函數必須返回為string,否則拋異常。
(我記得最開始初學python調用mongodb對象的什么方法來著,返回的數據用print出來的字符串一直沒問題,但是做處理的時候一直說數據格式有誤,就是因為傳回來的數據對象做了__str__處理。)
__len__:可以對對象使用 len()函數。在dict、list等類型中也實現了這個方法。
在pycharm中,輸入dict() ,用ctrl+B 跳到dict的定義,可以看到dict具有哪些魔法方法。或者用dir({})也可以看到。
還有很多比較重要的魔法方法例如 __setattr__() 、__getattr__()、__setitem__()、__getitem__()、__iter__() 超多簡化我們編程的魔法函數。
四? 用__len__看魔法函數大致做了哪些事情?
在三中我們看到,dict()的定義中的魔法函數__len__()定義的內容為空,list()也是。
實際上,我們在這里看到的相當于只是一個接口的定義而已,真正的實現是在cpython中。
為了加快len()的速度,比如list、dict、set類型,實際上會走一個捷徑。在cpython中,list、dict、set等內置類型是用c實現的,會在c數據結構內部有個參數用來存儲數據的長度,len()是直接去讀數據結構的長度。所以復雜度是O(1)。
以下為拓展,可不看:
有關 list 定義源碼位置在 Python 目錄下的 include/listobject.h 內, 代碼如下:
typedef struct{
PyObject_VAR_HEAD/*Vector of pointers to list elements. list[0] is ob_item[0], etc.*/PyObject**ob_item;/*ob_item contains space for 'allocated' elements. The number
* currently in use is ob_size.
* Invariants:
* 0 <= ob_size <= allocated
* len(list) == ob_size
* ob_item == NULL implies ob_size == allocated == 0
* list.sort() temporarily sets allocated to -1 to detect mutations.
*
* Items must normally not be NULL, except during construction when
* the list is not yet visible outside the function that builds it.*/Py_ssize_t allocated;
} PyListObject;
其中 ob_item 是指向列表元素的指針數組, list[0] 即 ob_item[0], allocated 是列表的空間大小。在 PyObject_VAR_HEAD 中, 擁有一個 ob_size 變量。
下面是 Python 目錄下的 include/object.h 中的相關代碼:
#define PyObject_VAR_HEAD PyVarObject ob_base;...
...
typedefstruct{
PyObject ob_base;
Py_ssize_t ob_size;/*Number of items in variable part*/} PyVarObject;
ob_size 變量存儲的就是對象的長度, 所以每次調用 _len_() 方法的時候, 返回的是一個已經存儲好了的變量,
小結:魔法函數大部分都做了很多優化的事情,設計理念還是比較重要的。
五? 總結
魔法函數是貫穿所有python知識點的。
可以用魔法函數來組織自己腦子里python知識點的知識樹。
魔法函數是內置的前面為__的方法
魔法函數是不需要顯示調用的,python語法本身會隱含調用魔法函數
魔法函數和對象不存在繼承關系,任何對象都可以定義魔法函數
魔法函數讓python的各種類型組織起來了,讓對象有數據類型,比如增加一個迭代類型等
__str__\__repr__\__add__等等多種常用魔法函數熟知會讓代碼更pythonic
python解釋器其實會經可能提高很多效率,讓開發者靈活性變高
總結
以上是生活随笔為你收集整理的python 魔法函数 __add___PythonI/O进阶学习笔记_2.魔法函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 朝鲜战争中的那些军用直升机
- 下一篇: 战车已死,战车万岁