1 生成器python
1.1 初識生成器app
什麼是生成器?這個概念比較模糊,各類文獻都有不一樣的理解,可是核心基本相同。生成器的本質就是迭代器,在python社區中,大多數時候都把迭代器和生成器是作同一個概念。不是相同麼?爲何還要建立生成器?生成器和迭代器也有不一樣,惟一的不一樣就是:迭代器都是Python給你提供的已經寫好的工具或者經過數據轉化得來的,(好比文件句柄,iter([1,2,3])。生成器是須要咱們本身用python代碼構建的工具。最大的區別也就如此了。函數
1.2 生成器的構建方式工具
在python中有三種方式來建立生成器:編碼
1. 經過生成器函數code
2. 經過生成器推導式orm
3. python內置函數或者模塊提供(其實1,3兩種本質上差很少,都是經過函數的形式生成,只不過1是本身寫的生成器函數,3是python提供的生成器函數而已)對象
1.3 生成器函數ip
咱們先來研究經過生成器函數構建生成器。內存
首先,咱們先看一個很簡單的函數:
複製代碼
def func():
print(11)
return 22
ret = func()
print(ret)
11
22
複製代碼
將函數中的return換成yield,這樣func就不是函數了,而是一個生成器函數
def func():
print(11)
yield 22
咱們這樣寫沒有任何的變化,這是爲何呢? 咱們來看看函數名加括號獲取到的是什麼?
複製代碼
def func():
print(11)
yield 22
ret = func()
print(ret)
<generator object func at 0x000001A575163888>
複製代碼
運行的結果和最上面的不同,爲何呢?? 因爲函數中存在yield,那麼這個函數就是一個生成器函數.
咱們在執行這個函數的時候.就再也不是函數的執行了.而是獲取這個生成器對象,那麼生成器對象如何取值呢?
以前咱們說了,生成器的本質就是迭代器.迭代器如何取值,生成器就如何取值。因此咱們能夠直接執行next()來執行如下生成器
複製代碼
def func():
print("111")
yield 222
gener = func() # 這個時候函數不會執⾏. ⽽是獲取到⽣成器
ret = gener.next() # 這個時候函數纔會執⾏
print(ret) # 而且yield會將func生產出來的數據 222 給了 ret。
結果:
111
222
複製代碼
而且個人生成器函數中能夠寫多個yield。
複製代碼
def func():
print("111")
yield 222
print("333")
yield 444
gener = func()
ret = gener.next()
print(ret)
ret2 = gener.next()
print(ret2)
ret3 = gener.next()
print(ret3)
結果:
111
222
333
444
複製代碼
當程序運行完最後一個yield,那麼後面繼續運行next()程序會報錯,一個yield對應一個next,next超過yield數量,就會報錯,與迭代器同樣。
yield與return的區別: return通常在函數中只設置一個,他的做用是終止函數,而且給函數的執行者返回值。 yield在生成器函數中可設置多個,他並不會終止函數,next會獲取對應yield生成的元素。
舉例:
咱們來看一下這個需求:老男孩向樓下賣包子的老闆訂購了10000個包子.包子鋪老闆很是實在,一下就所有都作出來了
複製代碼
def eat():
lst = []
for i in range(1,10000):
lst.append('包子'+str(i))
return lst
e = eat()
print(e)
複製代碼
這樣作沒有問題,可是咱們因爲學生沒有那麼多,只吃了2000個左右,剩下的8000個,就只能佔着必定的空間,放在一邊了。若是包子鋪老闆效率夠高,我吃一個包子,你作一個包子,那麼這就不會佔用太多空間存儲了,完美。
複製代碼
def eat():
for i in range(1,10000):
yield '包子'+str(i)
e = eat()
for i in range(200):
next(e)
複製代碼
這二者的區別:
第一種是直接把包子所有作出來,佔用內存。 第二種是吃一個生產一個,很是的節省內存,並且還能夠保留上次的位置。
複製代碼
def eat():
for i in range(1,10000):
yield '包子'+str(i)
e = eat()
for i in range(200):
next(e)
for i in range(300):
next(e)
複製代碼
1.4 send 方法(瞭解,不講)
·接下來咱們再來認識一個新的東西,send方法
View Code
send和next()區別:
相同點: send 和 next()均可以讓生成器對應的yield向下執行一次。 均可以獲取到yield生成的值。 不一樣點: 第一次獲取yield值只能用next不能用send(能夠用send(None))。 send能夠給上一個yield置傳遞值。
1.4 yield from
在python3中提供一種能夠直接把可迭代對象中的每個數據做爲生成器的結果進行返回
View Code
有個小坑,yield from 是將列表中的每個元素返回,因此 若是寫兩個yield from 並不會產生交替的效果
View Code
2. 推導式
本節咱們講列表推導式,生成器表達式以及其餘推導式,我認爲推導式就是構建比較有規律的列表,生成器,字典等一種簡便的方式。那麼他如何簡便呢?看下面的例題:
2.1列表推導式
這裏讓學生本身作一下,首先咱們先看一下這樣的代碼,給出一個列表,經過循環,想列表中添加1~10:
View Code
那麼按照上面的要求咱們用列表推導式寫一下:
View Code
怎麼樣?一行搞定,上面這個代碼就是列表推導式,接下來咱們將列表推導式進行一個分類:
列表推導式分爲兩種模式:
1.循環模式:[變量(加工的變量) for 變量 in iterable] 2.篩選模式: [變量(加工的變量) for 變量 in iterable if 條件]
固然還有多層循環的,這個咱們一會就會講到,那麼咱們先來看循環模式。
2.2 循環模式
剛纔咱們看到的就是循環模式,那麼有同窗會問到,什麼叫' 加工的變量'? 這個也比較簡單,接下來咱們作幾道題:
將10之內全部整數的平方寫入列表。
View Code
100之內全部的偶數寫入列表.
View Code
從python1期到python100期寫入列表lst
View Code
上面那個格式化輸出的變量f'python{i}',就是加工的變量。
上面作的那三個就是循環模式,比較簡單,接下來咱們研究篩選模式。
2.3 篩選模式
篩選模式就是在上面的基礎上加上一個判斷條件,將知足條件的變量留到列表中。
帶着同窗們作一個題:
將這個列表中大於3的元素留下來。
View Code
經過我給你們的演示,你們作幾道題:
三十之內能夠被三整除的數。
View Code
過濾掉長度小於3的字符串列表,並將剩下的轉換成大寫字母
View Code
找到嵌套列表中名字含有兩個‘e’的全部名字(有難度)
View Code
列表推導式基本上講完了,固然今天會作一些有關列表推導式的題,讓你們更加深刻的瞭解。
2.4 生成器表達式
生成器表達式和列表推導式的語法上如出一轍,只是把[]換成()就好了。好比將十之內全部數的平方放到一個生成器表達式中
View Code
生成器表達式也能夠進行篩選
View Code
生成器表達式和列表推導式的區別:
列表推導式比較耗內存,全部數據一次性加載到內存。而.生成器表達式遵循迭代器協議,逐個產生元素。
獲得的值不同,列表推導式獲得的是一個列表.生成器表達式獲取的是一個生成器
列表推導式一目瞭然,生成器表達式只是一個內存地址。
不管是生成器表達式,仍是列表推導式,他只是Python給你提供了一個相對簡單的構造方式,由於使用推導式很是簡單,因此大多數都會爲之着迷,這個必定要深重,推導式只能構建相對複雜的而且有規律的對象,對於沒有什麼規律,並且嵌套層數比較多(for循環超過三層)這樣就不建議你們用推導式構建。
生成器的惰性機制: 生成器只有在訪問的時候才取值,說白了.你找他要纔給你值.不找他要.他是不會執行的.
2.5 其餘相關的推導式(瞭解):
字典推導式
根據名字應該也能猜到,推到出來的是字典
View Code
集合推導式
集合推導式能夠幫咱們直接生成一個集合,集合的特色;無序,不重複 因此集合推導式自帶去重功能
View Code
3. 內置函數Ⅰ
本節咱們講內置函數。 首先來講,函數就是以功能爲導向,一個函數封裝一個功能,那麼Python將一些經常使用的功能(好比len)給咱們封裝成了一個一個的函數,供咱們使用,他們不只效率高(底層都是用C語言寫的),並且是拿來即用,避免重複早輪子,那麼這些函數就稱爲內置函數,到目前爲止python給咱們提供的內置函數一共是68個,因爲時間關係以及考慮這些函數的不一樣重要性咱們會挑經常使用的重要的內置函數去講,就是下面紅色黃色背景的內置函數,剩下的內置函數大家參照着個人博客本身課下練習一下便可。 因爲咱們這沒有表格的功能,我把這些內置函數進行分類:
黃色一帶而過:all() any() bytes() callable() chr() complex() divmod() eval() exec() format() frozenset() globals() hash() help() id() input() int() iter() locals() next() oct() ord() pow() repr() round()
紅色重點講解:abs() enumerate() filter() map() max() min() open() range() print() len() list() dict() str() float() reversed() set() sorted() sum() tuple() type() zip() dir()
藍色將來會講: classmethod() delattr() getattr() hasattr() issubclass() isinstance() object() property() setattr() staticmethod() super()
上面的黃色,紅色的內置函數是在這兩天講完的(講過的就不講了),藍色的講完面向對象會給你們補充,剩餘還有一些課上就不講了,課下練習一下就能夠。
eval:執行字符串類型的代碼,並返回最終結果。
eval('2 + 2') # 4
n=81
eval("n + 4") # 85
eval('print(666)') # 666
exec:執行字符串類型的代碼。
s = '''
for i in [1,2,3]:
print(i)
'''
exec(s)
hash:獲取一個對象(可哈希對象:int,str,Bool,tuple)的哈希值。
複製代碼
print(hash(12322))
print(hash('123'))
print(hash('arg'))
print(hash('alex'))
print(hash(True))
print(hash(False))
print(hash((1,2,3)))
'''
-2996001552409009098
-4637515981888139739
1
2528502973977326415
'''
複製代碼
help:函數用於查看函數或模塊用途的詳細說明。
print(help(list))
print(help(str.split))
callable:函數用於檢查一個對象是不是可調用的。若是返回True,object仍然可能調用失敗;但若是返回False,調用對象ojbect絕對不會成功。
name = 'alex'
def func():
pass
print(callable(name)) # False
print(callable(func)) # True
int:函數用於將一個字符串或數字轉換爲整型。
print(int()) # 0
print(int('12')) # 12
print(int(3.6)) # 3
print(int('0100',base=2)) # 將2進制的 0100 轉化成十進制。結果爲 4
float:函數用於將整數和字符串轉換成浮點數。
complex:函數用於建立一個值爲 real + imag * j 的複數或者轉化一個字符串或數爲複數。若是第一個參數爲字符串,則不須要指定第二個參數。。
print(float(3)) # 3.0
print(complex(1,2)) # (1+2j)
bin:將十進制轉換成二進制並返回。
oct:將十進制轉化成八進制字符串並返回。
hex:將十進制轉化成十六進制字符串並返回。
print(bin(10),type(bin(10))) # 0b1010 <class 'str'>
print(oct(10),type(oct(10))) # 0o12 <class 'str'>
print(hex(10),type(hex(10))) # 0xa <class 'str'>
divmod:計算除數與被除數的結果,返回一個包含商和餘數的元組(a // b, a % b)。
round:保留浮點數的小數位數,默認保留整數。
pow:求xy次冪。(三個參數爲xy的結果對z取餘)
複製代碼
print(divmod(7,2)) # (3, 1)
print(round(7/3,2)) # 2.33
print(round(7/3)) # 2
print(round(3.32567,3)) # 3.326
print(pow(2,3)) # 兩個參數爲23次冪
print(pow(2,3,3)) # 三個參數爲23次冪,對3取餘。
複製代碼
bytes:用於不一樣編碼之間的轉化。
複製代碼
複製代碼
ord:輸入字符找該字符編碼的位置
chr:輸入位置數字找出其對應的字符
複製代碼
複製代碼
repr:返回一個對象的string形式(原形畢露)。
複製代碼
print(repr('{"name":"alex"}'))
print('{"name":"alex"}')
複製代碼
all:可迭代對象中,全都是True纔是True
any:可迭代對象中,有一個True 就是True