Python学习(六)
魔法方法
在python中,有一些內(nèi)置好的特定的方法,這些方法在進(jìn)行特定的操作時(shí)會(huì)自動(dòng)被調(diào)用,稱之為魔法方法。
構(gòu)造和析構(gòu)
魔法方法總是被雙下橫線包圍,例如__init__;
是面向?qū)ο蟮腜ython的一切;
他們總是能在適當(dāng)?shù)臅r(shí)候被調(diào)用。
-
__init__(self[, …])
相當(dāng)于其他編程語(yǔ)言的構(gòu)造方法,類在實(shí)例化對(duì)象的時(shí)候首先會(huì)調(diào)用的一個(gè)方法。
-
__new__(cls[, …])
init并不是實(shí)例化對(duì)象調(diào)用的第一個(gè)方法,new方法才是,它的第一個(gè)參數(shù)是cls,通常情況下是返回cls類的對(duì)象,也可以返回其他類的對(duì)象。
new方法是極少去重寫它的,Python會(huì)默認(rèn)執(zhí)行,但是當(dāng)需要繼承一個(gè)不可變類型又需要修改的時(shí)候,那么就需要重寫了。
-
__del__(self)
當(dāng)對(duì)象將要被銷毀的時(shí)候這個(gè)方法會(huì)自動(dòng)被調(diào)用,但是
del方法是當(dāng)垃圾回收機(jī)制,即當(dāng)沒有任何變量去引用這個(gè)對(duì)象的時(shí)候,垃圾回收機(jī)制會(huì)自動(dòng)銷毀,這時(shí)才會(huì)調(diào)用對(duì)象的self方法。
注意:內(nèi)置的__del__()方法并不是發(fā)生del操作的時(shí)候就會(huì)調(diào)用,當(dāng)對(duì)象生成后,所有對(duì)它的引用都被del后才會(huì)啟動(dòng)垃圾回收機(jī)制,才會(huì)調(diào)用__del__()方法。
算數(shù)運(yùn)算
在Python2.2之前類和類型是分開的,類是屬性和方法的封裝,類型是如整型、浮點(diǎn)型、字符串這些類型,但是在Python2.2后,試圖對(duì)兩者進(jìn)行統(tǒng)一,做法就是將int、float、string、list、tuple這些內(nèi)置函數(shù)通常轉(zhuǎn)化為工廠函數(shù)。
- 什么是工廠函數(shù)
參考
原因: 當(dāng)a+b,識(shí)別到加法會(huì)先調(diào)用前者a的add,返回self+other,即返回了a+b,就又運(yùn)行了加法add,進(jìn)入了無(wú)限遞歸。
所以在實(shí)現(xiàn)的時(shí)候,一定要注意避免出現(xiàn)無(wú)限遞歸的情況。
稍作修改
- 一些算數(shù)運(yùn)算
| __add__(self, other) | 定義加法的行為:+ |
| __sub__(self, other) | 定義減法的行為:- |
| __mul__(self, other) | 定義乘法的行為:* |
| __truediv__(self, other) | 定義真除法的行為:/ |
| __floordiv__(self, other) | 定義整數(shù)除法的行為:// |
| __mod__(self, other) | 定義取模算法的行為:% |
| __divmod__(self, other) | 定義當(dāng)被divmod()調(diào)用時(shí)的行為【divmod(a, b)返回值是一個(gè)元組(a//b, a%b)】 |
| __pow__(self, other[, modulo]) | 定義當(dāng)被pow()調(diào)用或**運(yùn)算時(shí)的行為 |
| __lshift__(self, other) | 定義按位左移位的行為:<< |
| __rshift__(self, other) | 定義按位右移位的行為:>> |
| __and__(self, other) | 定義按位與操作的行為:& |
| __xor__(self,other) | 定義按位異或操作的行為:^ |
| __or__(self, other) | 定義按位或操作的行為:| |
通過對(duì)指定魔法方法的重寫,可以讓Python根據(jù)自己的意圖來(lái)實(shí)現(xiàn)程序
魔法方法參考
- 反運(yùn)算
這里是3-1,并不是1-3,如果想讓1-3,那么就要互換int.sub()中self, other的位置,舉例說(shuō)明
定制一個(gè)簡(jiǎn)單的類
- 需要的資源
(1)使用time模塊的localtime方法獲取時(shí)間
time模塊詳解
(2)time.localtime返回struct_time的時(shí)間格式
(3)表現(xiàn)你的類:重寫__str__和__repr__
- 程序MyTimer
但是這里有一個(gè)問題就是,如果定以后直接調(diào)用,就會(huì)報(bào)錯(cuò)
因?yàn)檫@時(shí),prompt還沒有被定義,這時(shí)就需要所有屬于實(shí)例對(duì)象的變量先在init中定義
這時(shí)在執(zhí)行雖然不會(huì)直接調(diào)用t1出錯(cuò)了,但是運(yùn)行起來(lái)卻又出現(xiàn)“整型不能被調(diào)用”問題,這里是由于在init中將self.start定義為0導(dǎo)致,因?yàn)轭惖姆椒蛯傩悦粯訒r(shí),屬性會(huì)覆蓋方法,這里就認(rèn)為start是屬性。
這時(shí)只需要將start和stop改一下名字即可
并且在這里改變一下顯示的方式和累加計(jì)時(shí)
- 代碼存在的問題
(1)生成的時(shí)間會(huì)存在負(fù)數(shù)的情況
(2)精度不夠,只能到秒
屬性訪問
(1)直接訪問屬性
(2)通過getattr()訪問
(3)利用property(),以屬性的方式訪問屬性
- __getattr__(self, name)
定義當(dāng)用戶試圖獲取一個(gè)不存在的屬性時(shí)的行為 - __getattribute__(self, name)
定義當(dāng)該類的屬性被訪問時(shí)的行為 - __setattr__(self, name, value)
定義當(dāng)一個(gè)屬性被設(shè)置時(shí)的行為 - __delattr__(self, name)
定義當(dāng)一個(gè)屬性被刪除時(shí)的行為
- 練習(xí)
另一種改進(jìn)方法就是給一個(gè)特殊屬性dict,dict是以字典的形式顯示出當(dāng)前對(duì)象的所有屬性以及對(duì)應(yīng)的值
描述符
描述符就是將某種特殊類型的類的實(shí)例指派給另一個(gè)類的屬性。
__get__(self, instance, owner) # 用于訪問屬性,返回屬性的值 __set__(self, instane, value) # 將在屬性分配操作中調(diào)用,不返回任何內(nèi)容 __delete__(self, instance) # 控制刪除操作,不返回任何內(nèi)容- 實(shí)例
【ps:這里改用spyder編輯了,輸入處顯示方式改變,實(shí)際操作同python idle相同】
這里就是將某種特殊類型的類(MyDescriptor)的實(shí)例(MyDescriptor())指派給另一個(gè)類(Test)的屬性(x),就說(shuō)明MyDescriptor就是x的描述符。
實(shí)例化對(duì)象后,用text.x強(qiáng)制打印
可以看到打印出三個(gè)參數(shù),第一個(gè)是self的參數(shù)描述符類MyDescriptor本身的實(shí)例,第二個(gè)是instance的參數(shù)類的擁有者Test的實(shí)例test,第三個(gè)就是擁有者類Test本身
驗(yàn)證一下
對(duì)實(shí)例化對(duì)象進(jìn)行賦值,出現(xiàn)賦值調(diào)用set的特殊方法,打印self、instance和value
del同理,打印self和instance
- 定義一個(gè)MyProperty
之前提到的property其實(shí)就是一個(gè)描述符
同樣的這里將MyProperty的實(shí)例MyProperty()指派給類C的屬性x,對(duì)類C的實(shí)例對(duì)象c的x屬性賦值,調(diào)用setX返回c._x再進(jìn)行操作。
- 練習(xí)
定制容器
- 協(xié)議
協(xié)議Protocols相似于接口,規(guī)定了必須要定義的方法。而在Python中協(xié)議更像是一種指南。 - 容器類型的協(xié)議
(1)定制不可變?nèi)萜?br /> 只需定義__len__()和__getitem__()方法
(2)定制可變?nèi)萜?br /> 除__len__()和__getitem__()方法外,還需定義__setitem__()和__delitem__()兩個(gè)方法
Python魔法方法詳解
- 練習(xí)
編寫一個(gè)不可改變的自定義列表,要求記錄列表中每個(gè)元素被訪問的次數(shù)。
迭代器
提供迭代方法的容器稱之為迭代器。
通常的迭代器有序列、列表、元組、字符串、字典、文件。
- for語(yǔ)句迭代
- 字典迭代
- 關(guān)于迭代操作,Python提供了兩個(gè)BIF內(nèi)置函數(shù)inter()和next()
inter() 即iteration
對(duì)于容器對(duì)象調(diào)用iter就得到它的迭代器,調(diào)用next()就會(huì)返回下一個(gè)值,當(dāng)?shù)鳑]有值可以返回了,Python就會(huì)拋出一個(gè)“StopIteration”的異常,此時(shí)迭代結(jié)束。
這樣就可以知道for語(yǔ)句是如何執(zhí)行的
利用while語(yǔ)句來(lái)模擬for語(yǔ)句的執(zhí)行
- 迭代器的魔法方法
- 實(shí)現(xiàn)斐波那契數(shù)列的打印
生成器
生成器并不涉及魔法方法、類和對(duì)對(duì)象,只通過普通的函數(shù)實(shí)現(xiàn)。生成器實(shí)際上是迭代器的一種實(shí)現(xiàn)。
生成器延續(xù)了Python簡(jiǎn)潔的特點(diǎn),并且使協(xié)同程序的概念得以實(shí)現(xiàn),協(xié)同程序就是可以運(yùn)行的獨(dú)立函數(shù)調(diào)用,函數(shù)可以暫停或掛起,并在需要的時(shí)候從程序離開的地方繼續(xù)或者重新開始。
Generator 實(shí)例
def myGen():print("生成器被執(zhí)行!")yield 1yield 2# 一旦一個(gè)函數(shù)中出現(xiàn)yield語(yǔ)句# 那么就說(shuō)明這個(gè)函數(shù)被定義為生成器# yield就相當(dāng)于普通函數(shù)中的return# 和return的區(qū)別:# 出現(xiàn)yield,就將yield后的參數(shù)返回,并暫停在yield處- 實(shí)現(xiàn)斐波那契數(shù)列
- 推導(dǎo)式
(1)列表推導(dǎo)式
(2)字典推導(dǎo)式
有“:”的是字典,沒有的是集合
(3)集合推導(dǎo)式
(4)沒有字符串推導(dǎo)式
(5)元組(tuple)推導(dǎo)式
打印元組e發(fā)現(xiàn)e是一個(gè)生成器推導(dǎo)式
生成器推導(dǎo)式如果作為函數(shù)的參數(shù),是可以直接寫推導(dǎo)式,不需要加括號(hào)
【100以內(nèi)不能被2整除的整數(shù)和】
[擴(kuò)展閱讀] 提高你的 Python:解釋 yield 和 Generators(生成器)
總結(jié)
以上是生活随笔為你收集整理的Python学习(六)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【案例】正浩创新:多云多资产,实现敏捷云
- 下一篇: 064_《Delphi7程序设计与开发技