[Python]第九章 魔法方法、特性和迭代器
文章目錄
類似__future__以兩個下劃線開頭和結尾的名稱擁有特殊意義,因此在程式建立中不能使用這樣的名稱,這樣的名稱中,很大一部分是特殊名稱
魔法名稱: init
特性property:以前通過魔法方法處理,現在通過函式property處理
迭代器iterator:使用魔法方法__iter__,可讓其用於for迴圈之中
9.1如果你使用的不是Python3
Python2有些功能(如特性和函式super)不適合舊式類,如果要讓類是最新的,要麼在模組開頭包含賦值語句__metaclass__=type,要麼直接或者間接的繼承內建類object或其他新式類。
如下:
class NewStyle(object):
more_code_here
class OldStyle:
more_code_here
在這兩個類中,NewStyle是一個新式類,而OldStyle是一箇舊式類。如果檔案開頭包含賦值語句__metaclass__ = type,這兩個類都將是新式類。
在Python 3中沒有舊式類,因此無需顯式地繼承object或將__metaclass__設定為type。所有的類都將隱式地繼承object。如果沒有指定超類,將直接繼承它,否則將間接地繼承它。
9.2建構函式
即初始化方法,只是命名__init__,建構函式特殊之處在於,將在物件建立後自動呼叫他們,因此無需顯式呼叫
class Person:
def __init__(self,name):
self.name=name
p=Person('jack')#這裡直接在構造物件的時候呼叫了__init__方法
p.name
'jack'
PS:解構函式__del__
9.2.1重寫普通方法和特殊的建構函式
重寫普通方法,方法名相同
class A:
def hello(self):
print('hello,I am A')
class B(A):
pass
class Son(A):
def hello(self,name):
self.name=name
print('hello,I am the son of A,I am ',self.name)
>>> a=A()
>>> hello()
hello,I am A
>>>b=B()
>>>hello()
hello,I am A
>>>son=Son()
>>> son.hello('jack')
hello,I am the son of A,I am jack
重寫建構函式時,必須呼叫超類(繼承的類)的建構函式,否則可能無法正確的初始化物件
class Bird:
def __init__(self):
self.hungry=True
def eat(self):
if self.hungry:
print('dying...')
self.hungry=False
else:
print('full')
>>>bird=Bird()
>>> bird.eat()
dying...
寫一個子類,建構函式沒有重寫父類
class SongBird(A):
def __init__(self):
self.sound='jiujiu'
def sing(self):
print(self.sound)
>>>songbird=SongBird()
>>>songbird.sing()
jiujiu
>>>songbird.eat()#eat是父類的方法,這個方法呼叫了父類的建構函式
報錯
解決方法有見如下兩節
9.2.2呼叫未關聯的超類建構函式
在子類的建構函式中新增一行程式碼:父類.__init__(self)
class SongBird(Bird):
def __init__(self):
Bird.__init__(self)
self.sound='jiujiu'
def sing(self):
print(self.sound)
songbird=SongBird()
songbird.eat()
dying..
通過類呼叫方法(如Bird.__init__),就沒有例項與其相關聯。在這種情況下,可隨便設定引數self。這樣的方法稱為未關聯的。
通過將這個未關聯方法的self引數設定為當前例項,將使用超類的建構函式來初始化SongBird物件。這意味著將設定其屬性hungry。
9.2.3使用函式super(更好)
super函式適用於新式類,在子類的構造方法中新增super().__init__()
class SongBir(Bird):
def __init__(self):
super().__init__()
self.sound='jiujiu'
def sing(self):
print(self.sound)
>>>songbir=SongBir()
>>>songbir.eat()
dying...
9.3元素訪問
用魔法方法建立行為類似於序列或對映的物件
9.3.1基本的序列和對映協議
序列和對映基本上是元素的集合,要實現他們的基本行為(協議),不可變物件需要實現2個方法,可變物件需要實現4個:
__len__(self):返回集合的項數,序列的元素個數,對映的鍵值對數,返回0,視為假
__getitem__(self,key):返回指定鍵對應的值,對序列來說鍵是0~n-1的整數(n是序列長度),對映的鍵可以是任何型別的
__setitem__(self,key,value):以與鍵相關的方式儲存值,以便以後使用__getitem__來獲取,適用可變物件
__delitem__(self,key):在物件組成部件使用__del__語句時被呼叫,刪除與鍵相關的值,適用於可變物件且允許被刪除
額外要求:
1.對於序列,如果鍵為負整數,應從末尾往前數。x[-n]等同於x[len(x)-n]
2.如果鍵的型別不合適(如對序列使用字串鍵),可能引發TypeError異常
3.對於序列,如果索引的型別是正確的,但不在允許的範圍內,應引發IndexError異常
CASE:建立一個無窮序列
建立一個序列,可以自己設定開始值和步長,沒有設定的話,預設以0開始步長是1
這個序列的長度是無窮的,因此不能從後往前,key不能是負數,而且得是整數
先寫一個引數檢查函式,在之後類的方法裡被呼叫即可
def check_index(key):
if not isinstance(key,int):raise TypeError#isinstance(例項,類)判斷該例項是否屬於該類
if key<0:raise IndexError
這個類除了構造方法,還要有__getitem__(self,key)和__setitem__(self,key,value)方法用於獲取和傳入引數
class ArithmeticSequence:
def __init__(self,start=0,step=1):
self.start=start#序列中的第1個值,儲存起始值
self.step=step#兩個相鄰值的差,儲存步長值
self.changed={}#一個字典,包含使用者修改後的值
def __getitem__(self,key):#這個方法用來根據KEY返回值
check_index(key)#首先要檢查傳入的key是否符合要求,不符合就會在檢查函數了報錯
try:
return self.changed[key]#如果該字典中含有該key的鍵值對,就返回值
except KeyError:#KeyError在字典中不含該key時引發
return self.start+key*self.step#如果不存在就返回計算後的值
finally:#可用該子句檢查字典changed的狀態
print(self.changed)#
def __setitem__(self,key,value):#該方法用來傳入鍵值
check_index(key)#先檢查傳入的key是否符合要求
self.changed[key]=value#將鍵值傳入字典
>>>a=ArithmeticSequence()
>>>a[4]#按照預設起始值和步長,self.start+key*self.step=0+4*1=4
4
>>>s=ArithmeticSequence(1,2)
>>>s[4]#按照設定起始值和步長,self.start+key*self.step=1+4*2=9
9
這兩個輸出都是呼叫了__getitem__的結果,這兩個操作都沒有改變字典
>>>s[5]=2
>>>s[5]
2
這個賦值實際上調動的是__setitem__方法,字典裡傳入新的鍵值對
>>>del s[5]
報錯AttributeError,該類沒有__del__方法,因此不能被del語句呼叫
>>>s[-1]
報錯IndexError,檢查函式中報對應的錯
>>>s['num']
報錯TypeError,檢查函式中報對應的錯
9.3.2從list、dict和str派生
通過繼承去實現序列/對映的其他有用的魔法方法,標準庫中,模組collections補充了抽象和具體的基類,但也可以繼承內建型別
CASE:帶訪問計數器的列表
class Counterlist(list):
def __init__(self,*args):
super().__init__(*args)
self.counter=0
def __getitem__(self,index):
self.counter+=1
return super(Counterlist,self).__getitem__(index)#呼叫父類的 __getitem__方法
# super(Counterlist,self):找到Counterlist的父類(即list),再把Counterlist類的物件轉換為list的物件
>>>a=[11,12,1,2,3,4,5]
>>>c=Counterlist(a)
>>>c
[11, 12, 1, 2, 3, 4, 5]
>>>c[0]#呼叫了__getitem__方法
11
>>>c.counter
1
>>>c[0]+c[2]#呼叫了__getitem__方法2次
12
>>>c.counter
3
Counterlist也繼承了list的一下方法
>>>c.reverse()
>>>c
[5, 4, 3, 2, 1, 12, 11]
>>>del c[2:3]
>>>c
[5, 4, 2, 1, 12, 11]
9.4其他魔法方法
可參閱“Python Reference Manual”的Special method names一節
9.5特性
class Rectangle:
def __init__(self):
self.width=0
self.height=0
def set_size(self,size):
self.width,self.height=size#size引數以元組的形式分別給屬性width\height賦值
def get_size(self):
return self.width,self.height
>>>r=Rectangle()
>>>r.width=5#外部直接訪問
>>>r.height=10
>>>r.get_size()
(5, 10)
>>>r.set_size((55,111))
>>>r.get_size()
(55, 111)
這裡size不是真正的屬性,get_size和set_size是假想屬性size的存取方法。如果有一天你想修改,讓size成為真正的屬性,而width和height是動態計算出來的,就需要提供用於訪問width和height的存取方法,使用這個類的程式也必須重寫。
所幸Python能夠替你隱藏存取方法,讓所有的屬性看起來都一樣。通過存取方法定義的屬性通常稱為特性(property)。
9.5.1函式property
class Rectangle:
def __init__(self):
self.width=0
self.height=0
def set_size(self,size):
self.width,self.height=size#size引數以元組的形式分別給屬性width\height賦值
def get_size(self):
return self.width,self.height
size=property(get_size,set_size)#將size定義成了特性,獲取方法在前,設定方法在後
>>>r=Rectangle()
>>>r.width=10
>>>r.height=50
>>>r.size#不需要呼叫get_size方法了,因為size已經變成了屬性(特性)
(10, 50)
>>>r.size=55,111#不需要呼叫set_size方法了,因為size已經變成了屬性(特性)
>>>r.size
(55, 111)
這裡property(fget,fset,fdel,doc)函式中,獲取(get)方法在前。當沒有引數時,預設沒有方法,不可獲取也不可設定,當只有1個引數時,只可獲取,兩個引數可獲取可設定,三個引數的最後一個引數指定用於刪除屬性的方法,四個引數的最後一個引數,指定一個文件字串。
9.5.2靜態方法和類方法
靜態方法和類方法是這樣建立的:將它們分別包裝在staticmethod和classmethod類的物件中。
靜態方法的定義中沒有引數self,可直接通過類來呼叫。
類方法的定義中包含類似於self的引數,通常被命名為cls。對於類方法,也可通過物件直接呼叫,但引數cls將自動關聯到類。
手工包裝和替換(方法繁瑣):
class MyClass:
def smeth():
print('This is a static method')
smeth = staticmethod(smeth)
def cmeth(cls):
print('This is a class method of', cls)
cmeth = classmethod(cmeth)
修飾器語法:
class MyClass:
@staticmethod
def smeth():
print('This is a static method')
@classmethod
def cmeth(cls):
print('This is a class method of', cls)
>>> MyClass.smeth()
This is a static method
>>> MyClass.cmeth()
This is a class method of <class '__main__.MyClass'>
9.5.3__getattr__、__setattr__等方法
可以攔截對物件屬性的所有訪問企圖,在舊式類中實現特性,要在屬性被訪問時執行一段程式碼,必須使用一些魔法方法:
__getattribute__(self,name):在屬性被訪問時自動呼叫(只適用新式類)
__getattr__(self,name):在屬性被訪問而物件沒有這樣的屬性時自動呼叫
__setattr__(self,name,value):試圖給屬性複製時自動呼叫
__delattr__(self,name):試圖刪除屬性時動呼叫
相比property,這些方法更棘手效率更低,但可在這些方法中編寫處理多個特性的程式碼。
__dict__參考:http://www.cnblogs.com/alvin2010/p/9102344.html
class Rectangle:
def __init__ (self):
self.width = 0
self.height = 0
def __setattr__(self, name, value):
if name == 'size':
self.width, self.height = value #這是的value一定是一個元組
else:
self. __dict__[name] = value #儲存屬性
def __getattr__(self, name):
if name == 'size':
return self.width, self.height
else:
raise AttributeError()
>>>rect2=Rectangle()
>>>rect2.__setattr__('size',(51,11))
>>>rect2.size
(51, 11)
>>>rect2.__setattr__('length',555)
>>>rect2.length
555
>>>rect2.color
報錯:AttributeError
9.6迭代器
iter__迭代器的基礎
9.6.1迭代器協議
迭代以為著重複多次,就像迴圈那樣。
方法__iter__返回一個迭代器,他是包含__next__方法的物件,而呼叫這個方法可不傳遞引數,迭代器盈返回下一個值,如果迭代器沒有可供返回的值,引發StopIteration異常。
內建的便利函式next(it)等同於it.__next
斐波那契數列
class Fibs:
def __init__(self):
self.a=0
self.b=1
def __next__(self):
self.a,self.b=self.b,self.a+self.b
return self.a
def __iter__(self):
return self
注意到這個迭代器實現了方法__iter__,而這個方法返回迭代器本身。在很多情況下,都在另一個物件中實現返回迭代器的方法__iter__,並在for迴圈中使用這個物件。但推薦在迭代器中也實現方__iter__(並像剛才那樣讓它返回self),這樣迭代器就可直接用於for迴圈中。
實現了方法__iter__的物件是可迭代的,而實現了方法__next__的物件
是迭代器。
fibs是一個無窮大的‘數列’
fibs=Fibs()
for f in fibs:
if f>100:
print(f)
break
也可以通過迭代物件呼叫內建函式iter,返回一個迭代器
it=iter([1,2,3])
next(it)
1
next(it)
2
9.6.2從迭代器生成序列
將迭代出來的物件轉換成序列
class TestIterator:
value = 0
def __next__(self):
self.value += 1
if self.value > 10: raise StopIteration
return self.value
def __iter__(self):
return self
>>> ti = TestIterator()
>>> list(ti)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
9.7生成器
生成器是一種使用普通函式語法定義的迭代器
9.7.1建立生成器
CASE:將巢狀列表展開的函式
nested = [[1, 2], [3, 4], [5]]
def faltten(nested):
for aa in nested:
for a in aa:
yield a
包含yield語句的函式都被稱為生成器
生成器不是使用return返回一個值,而是可以生成多個值,每次一個。
每次使用yield生成一個值後,函式都將凍結,即在此停止執行,等待被重新喚醒。被重新喚醒後,函式將從停止的地方開始繼續執行。
每執行到一個 yield 語句就會中斷,並返回一個迭代值,下次執行時從 yield 的下一個語句繼續執行。看起來就好像一個函式在正常執行的過程中被 yield 中斷了數次,每次中斷都會通過 yield 返回當前的迭代值。
list(faltten(nested))
[1, 2, 3, 4, 5]
或者
for i in faltten(nested):
print(i)
1
2
3
4
5
生成器推導:
類似於列表推導
[i ** 2 for i in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
生成器推導
(i ** 2 for i in range(10))
<generator object <genexpr> at 0x0000000004AD8678>
返回的就是一個生成器,可以逐步計算
g=(i ** 2 for i in range(10))
next(g)
0
next(g)
1
如果要包裝可迭代物件(大量的值),迭代器優於列表推導
另外圓括號可使該生成器直接被函式呼叫
sum(i ** 2 for i in range(10))
285
9.7.2遞迴生成器
遞迴:呼叫自身
基線條件(針對最小的問題):滿足這種條件是函式將直接返回一個值
遞迴條件:包含一個或多個呼叫,這些呼叫旨在解決問題的一部分
def faltten(nested):
try:
for aa in nested:
for a in faltten(aa):#呼叫自身
yield a#返回,中斷
except TypeError:#當需要展開的是一個單個元素,就會觸發該異常,執行後面的語句
yield nested
nested=[[[1
相關推薦
[Python]第九章 魔法方法、特性和迭代器
文章目錄
9.1如果你使用的不是Python3
9.2建構函式
9.2.1重寫普通方法和特殊的建構函式
9.2.2呼叫未關聯的超類建構函式
9.2.3使用函式super(更好)
python基礎——第9章 魔法方法、特性和迭代器
目錄
9.2.1 建構函式: __init__(self)
9.2.2 呼叫未關聯的超類建構函式
9.3 元素訪問
9.3.1 基本的序列和對映協議
9.3.2 從
九.魔法方法、特性和叠代器
一個 self delet item 調用 大數 包含 默認 fir 0.Python中雙下劃線__有特殊意義。
1.構造函數和析構函數:
class Test:
def __init__(self): #構造函數,創造實例默認執行
pa
魔法方法、特性和叠代器
類定義 刪除 魔法方法 oob ron 對數 元素 indexer ont
構造函數
在python中,創建構造函數和容易,只需將方法init的名稱從普通的init改為魔法版__init__即可.1 class FooBar:
2 def __init__(
python3自學筆記4-切片、迭代、列表生成式、生成器和迭代器
目錄切片迭代列表生成式生成器迭代器
切片
1、Python提供了切片(Slice)操作符:;
2、list可以進行切片操作:
# 生成列表
>>> L = list(range(100))
>>> L
[0, 1, 2, 3,
java 中 for 、foreach 和 迭代器 的學習筆記
開發十年,就只剩下這套架構體系了!
>>>
21天學python——第三章3.3、3.4
3.3.1標誌符
沒什麼新的,和c語言一樣,只能是數字、英文和下劃線,並且大小寫敏感。用來設定變數和函式名。
3.3.2 =
賦值也是很普通的內容
平時只要x = 2 或者 x = ‘a' 就能將字元或者數字賦值給變量了
3.4
21天學python——第四章4.1、4.2
4.1.1 if基礎
看了之前的基礎起始已經懂得if的基本用法了
if 《條件》: 《語句》
栗子:
然後if是可以有分支的,其實就是else 和else if,但是else if 只能寫成 elif ,在來個栗子:
python第九章,計算生態概念
1,從資料處理到人工智慧。
資料表示 ->資料清洗->資料統計->資料視覺化->資料探勘->人工智慧
資料表示:採用合適方式用程式表達資料。
資料清理:資料歸一化,資料轉換,異常值處理。
資料統計:資料的概要理解,數量。分佈。中位數等。
Python第九章 類
9.1建立和使用類
動手試一試
9-1
class Restaurant():
def __init__(self,name,type):
self.name=name
self.type=type
def describ
python第九章元件檔案
批量操作具有相同型別的檔案(python實現自動化) shutil 或者稱為shell工具,該模組中包含一些函式,用於實現python程式中複製,移動、改名和刪除檔案 shutil.copy(source, destination) 將路徑source處的檔案複製到路徑destination處
小甲魚Python視頻第041課(魔法方法:構造和析構 )課後題及參考解答
oat 構造 all 魔法 繼承 return shc 公式 none
# -*- coding: utf-8 -*-
"""
Created on Sun Mar 17 21:13:58 2019
@author: fengs
"""
"""
測試
Javascript權威指南閱讀筆記--第3章類型、值和變量(1)
分享圖片 自動 局部變量 清理 ace defined define 原型 未在 之前一直有個想法,好好讀完JS權威指南,便於自己對於JS有個較為全面的了解。畢竟本人非計算機專業出生,雖然做著相關行業的工作,但總覺得對於基礎的掌握並沒有相關專業學者紮實,正好因為辭職待業
第5章:介面、實現和多型
介面
介面是軟體資源使用者可用的一組操作
介面中的內容是函式頭和方法頭,以及它們的文件
設計良好的軟體系統會將介面與其實現分隔開來
多型
多型是在兩個或
資料庫系統概論(第九章: 關係查詢處理和查詢優化)
第9章 關係查詢處理和查詢優化 查詢優化分類 : 代數優化:指關係代數表示式的優化 物理優化:指存取路徑和底層操作演算法的選擇9.1 關係資料庫系統的查詢處理 9.1.1 查詢處理步驟 ※關係資料庫管
【資料庫視訊】第五章 操作架構、索引和檢視
一.建立檢視
1.語法格式
CREATE VIEW view_name(view_column_name)
AS query_expression
[WITH CHECK OPTION]
方法:①通過圖形化介面建立檢視
新建檢視,新增表,定義需要檢視
第15章 友元、異常和其他
本章內容包括:
友元類
友元類方法
巢狀類
引發異常,try塊和catch塊
異常類
執行階段型別識別(RTTI)
dynamic_cast和typeid
static_cast,const_cast和reiterpret_cast
RTT
第5章 操作架構、索引和檢視
一、建立檢視:
1、語法格式:
create view 檢視名
as 查詢表示式
with check option
2、新建檢視
在資源管理器中選擇檢視——>右擊新建
二、刪除和修改檢視
1、圖形化介面:
alter view 檢視名
as
select
Vulkan Cookbook 第四章 11 對映、更新和取消對映主機可見記憶體
對映、更新和取消對映主機可見記憶體
譯者注:示例程式碼點選此處
對於渲染期間使用的影象和緩衝區,建議繫結位於影象硬體(裝置本地記憶體)上的記憶體。這會產生最好的表現。但我們不能直接訪問這樣的記憶體,需要使用中間(暫存)資源來調節GPU(裝置)和CPU(主機)之間的資料傳輸。
另一方面,暫
C Primer Plus (第五版)中文版——第 12 章 儲存類、連結和記憶體管理
12.1 儲存類
12.1.1 作用域
定義:作用域描述了程式中可以訪問一個識別符號的一個或多個區域。
分類:
程式碼塊作用域:在程式碼塊中定義的變數具有程式碼塊作用域,從定義處到包含該定義的程式碼塊的末尾,該變數可見。
函式原型作用域:在函式原型