day21(python高級編程,property屬性,生成器,迭代器,閉包,裝飾器)

屬性property

私有屬性添加getter和setter方法

對于類對象的私有屬性,我們不能直接調用,可以添加方法來調用。

class Person:

????def __init__(self):

????????pass

????def setAge(self,age):

????????if 0<=age<=100:

????????????self.__age = age

????????else:

????????????self.__age = 16

????????????print('輸入的年齡不符合')

????def getAge(self):

????????return self.__age

p1 = Person()

p1.setAge(10)

print(p1.getAge())

p1.setAge(200)

print(p1.getAge())

結果:

10

輸入的年齡不符合

16

使用property升級getter和setter方法

class Person:

????def __init__(self):

????????pass

????def setAge(self,age):

????????if 0<=age<=100:

????????????self.__age = age

????????else:

????????????self.__age = 16

????????????print('輸入的年齡不符合')

????def getAge(self):

????????return self.__age

????????age = property(getAge,setAge)

p1 = Person()

p1.age = 10

print(p1.age)

p1.age = 200

print(p1.age)

結果:

10

入的年齡不符合

16

使用property取代getter和setter方法

class Person:

????def __init__(self):

????????pass

????@property

????def age(self):

????????return self.__age

????@age.setter

????def age(self,age):

????????if 0<=age<=100:

????????????self.__age = age

????????else:

????????????self.__age = 16

????????????print('輸入的年齡不符合')

p1 = Person()

p1.age = 10

print(p1.age)

p1.age = 200

print(p1.age)

結果:

10

輸入的年齡不符合

16

生成器

通過列表生成式,我們可以直接創建一個列表。但是,受到內存限制,列表容量肯定是有限的。而且,創建一個包含100萬個元素的列表,不僅占用很大的存儲空間,如果我們僅僅需要訪問前面幾個元素,那后面絕大多數元素占用的空間都白白浪費了。所以,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算出后續的元素呢?這樣就不必創建完整的list,從而節省大量的空間。在Python中,這種一邊循環一邊計算的機制,稱為生成器:generator。

創建生成器

1.把列表生成式的[]改成()

如:

[ x*2 for x in range(5)]

改為:

( x*2 for x in range(5))

如果想要打印,可以通過next()獲取生成器的下一個返回值,而且,generator也是可迭代的,所以也可以用循環遍歷。

2.有的比較復雜,用類似列表生成式的for循環無法實現的時候,還可以用函數來實現。

可以用yield

例如:

def fib(num):

????a,b = 0,1

????while num>0:

????????yield b

????????a,b = b,a+b

????????num-=1


f = fib(5)

print(' ',next(f))

print(' ',next(f))

for i in f:

????print(i)

在上面fib 的例子,我們在循環過程中不斷調用 yield ,就會不斷中斷。當然要給循環設置一個條件來退出循環,不然就會產生一個無限數列出來。同樣的,把函數改成generator后,我們基本上從來不會用 next() 來獲取下一個返回值,而是直接使用 for 循環來迭代。

但是用for循環調用generator時,發現拿不到generator的return語句的返回值。如果想要拿到返回值,必須捕獲StopIteration錯誤,返回值包含在StopIteration的value中。

send:

執行到yield時,gen函數作用暫時保存,返回i的值;temp接收下次c.send("python"),send發送過來的值,c.next()等價c.send(None)。

def nums():

????for i in range(10):

????????ret = yield i

????????if ret == '平方':

????????????print(i**2)

????????elif ret == '立方':

????????????print(i**3)

num = nums()

print(num)

print(next(num))

print(next(num))

print(next(num))

print(next(num))

print(next(num))

print('----------')

num1 = nums()

next(num1)

num1.send('平方')

num1.send('平方')

num1.send('平方')

num1.send('立方')

num1.send('立方')

num1.send('立方')

__next__:作為一個魔法方法,__next__等價于next()

生成器是這樣一個函數,它記住上一次返回時在函數體中的位置。對生成器函數的第二次(或第 n 次)調用跳轉至該函數中間,而上次調用的所有局部變量都保持不變。

生成器不僅“記住”了它數據狀態;生成器還“記住”了它在流控制構造(在命令式編程中,這種構造不只是數據值)中的位置。

生成器的特點:

節約內存

迭代到下一次的調用時,所使用的參數都是第一次所保留下的,即是說,在整個所有函數調用的參數都是第一次所調用時保留的,而不是新創建的

迭代器

迭代是訪問集合元素的一種方式。迭代器是一個可以記住遍歷的位置的對象。迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會后退。

可迭代對象

以直接作用于 for 循環的數據類型有以下幾種:

一類是集合數據類型,如 list 、 tuple 、 dict 、 set 、 str 等;

一類是 generator ,包括生成器和帶 yield 的generator function。

這些可以直接作用于 for 循環的對象統稱為可迭代對象: Iterable 。

判斷是否可以迭代

可以使用 isinstance() 判斷一個對象是否是 Iterable 對象:

from collections import Iterable,Iterator

def f():

????yield 'hello'

print(isinstance(f(),Iterable))

print(isinstance(f(),Iterator))

print(isinstance('abc',Iterable))

print(isinstance('abc',Iterator))

迭代器

可以被next()函數調用并不斷返回下一個值的對象稱為迭代器:Iterator。

可以使用 isinstance() 判斷一個對象是否是 Iterator 對象。

iter()函數

生成器都是 Iterator 對象,但 list 、 dict 、 str 雖然是 Iterable ,卻不是 Iterator 。

把 list 、 dict 、 str 等 Iterable 變成 Iterator 可以使用 iter() 函數。

name = 'abc'

myIter = iter(name)

print(type(myIter))

print(isinstance(myIter,Iterator))

try:

????print(next(myIter))

????print(next(myIter))

????print(next(myIter))

????print(next(myIter))

except StopIteration as ex:

????print('迭代完了,%s'%ex)

閉包

函數引用

閉包概念:

在函數內部再定義一個函數,并且這個函數用到了外邊函數的變量,那么將這個函數以及用到的一些變量稱之為閉包。

def test(number):

????'''

????在函數內部再定義一個函數,并且這個函數用到了外邊函數的變量,

????那么將這個函數以及用到的一些變量稱之為閉包

????'''

????def test_in(number_in):

????????print("in test_in 函數, number_in is %d"%number_in)

????????return number+number_in

????#其實這里返回的就是閉包的結果

????return test_in

#給test函數賦值,這個20就是給參數number

ret = test(20)

#注意這里的100其實給參數number_in

print(ret(100))

#注意這里的200其實給參數number_in

print(ret(200))

閉包思考:

1.閉包似優化了變量,原來需要類對象完成的工作,閉包也可以完成

2.由于閉包引用了外部函數的局部變量,則外部函數的局部變量沒有及時釋放,消耗內存

裝飾器

裝飾器,功能就是在運行原來功能基礎上,加上一些其它功能,比如權限的驗證,比如日志的記錄等等。不修改原來的代碼,進行功能的擴展。

比如java中的動態代理,python的注解裝飾器

其實python的裝飾器,是修改了代碼。

def login(func):

????def inner(a,b):

????????user = input('請輸入用戶名:')

????????psd = input('請輸入密碼:')

????????if user == a and psd == b:

????????????print('Welcome in!')

????????????func(a,b)

????????else:

????????????print('Passward error!')

????return inner

@login

def f1(nowHaveUser,nowHavePsd):

print('f1')

def f2():

print('f2')

def f3():

print('f3')

def f4():

print('f4')

f1('haha','123456')


python解釋器就會從上到下解釋代碼,步驟如下:

1.def login(func):?==>將login函數加載到內存

2.@login

沒錯,?從表面上看解釋器僅僅會解釋這兩句代碼,因為函數在?沒有被調用之前其內部代碼不會被執行。

從表面上看解釋器著實會執行這兩句,但是@login這一句代碼里卻有大文章,@函數名?是python的一種語法糖。

上例@login內部會執行一下操作:

執行login函數

執login1函數?,并將@login下面的函數作為login函數的參數,即:@login等價于login(f1)所以,內部就會去執行。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,676評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,730評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,873評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,266評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,482評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,036評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,846評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,025評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,279評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,751評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,016評論 2 375

推薦閱讀更多精彩內容

  • 1.1==,is的使用 ·is是比較兩個引用是否指向了同一個對象(引用比較)。 ·==是比較兩個對象是否相等。 1...
    TENG書閱讀 740評論 0 0
  • 基礎1.r''表示''內部的字符串默認不轉義2.'''...'''表示多行內容3. 布爾值:True、False(...
    neo已經被使用閱讀 1,709評論 0 5
  • 住的這個小區也建好幾年了,怎么周圍一直在裝修,鉆啊鉆啊。于是開大音樂,擋住鉆的聲音,周期性重復的聲音實在是亂人心緒...
    KevinCool閱讀 836評論 1 1
  • 今晚吃秘魯菜,酸酸辣辣的味道,一不留神吃多了。席間,突然想起已經兩年多沒有跟納豆先生說:我從明天開始減肥這句話了...
    瘋小蝦閱讀 866評論 11 11
  • 有時候當被別人說到“你變了”之類的話,總是會不由自主的感到緊張焦慮 緊張別人說起自己的變是怎樣一種口吻和態度,更怕...
    藝妹哦耶耶閱讀 470評論 1 2