1. 程式人生 > 其它 >第六篇 生成器 ,生成器表示式,常見的內建函式

第六篇 生成器 ,生成器表示式,常見的內建函式

print(complex(1, 3))  # (1+3j) 數字

print(complex(111))  # (111+0j) 數字

print(complex('111'))  # (111+0j) 當做字串處理

生成器

生成器就是一種自定義的迭代器

生成器物件

# 定義階段就是一個普通函式
def func():
    print('first')
    yield 111
    print('second')
    yield 222
    print('third')  # 報錯,丟擲異常 StopIteration 取到這裡就取乾淨了
'''
當函式內出現yield關鍵字,再呼叫函式並不會觸發函式體程式碼的執行,
而是將函式變成了生成器(迭代器)
''' # 呼叫函式:不執行函式體程式碼 而是轉換為生成器(迭代器) g = func() # print(g) # <generator object func at 0x7fca46cd2890> 生成器就是一種自定義的迭代器 res = next(g) # 每執行一個__next__程式碼往下執行到yield停止 返回後面的資料 print(res) res
= next(g) # 再次執行__next__接著上次停止的地方繼續往後 遇到yield再停止 print(res) next(g) # 取不到了報錯 # 一出場就是一隻老母豬,可以存無窮個值的型別,但每次只能拿一個 def func(): res = 1 while True: yield res res += 1 g = func() # 得到一個迭代器 print(next(g)) # 列印next觸發程式碼執行,可以返回無數個值 print(next(g)) print(next(g))

自定義range功能

# for
i in range(1, 10): # print(i) # 模仿上面的range() def my_range(start, stop): while start < stop: yield start start += 1 res = my_range(1, 10) # 呼叫函式:不執行函式體程式碼,而是轉換為生成器(迭代器) for i in my_range(1, 10): print(i) # 結果和range效果一樣 # 自定義range()模仿的更像一點 def my_range(start, stop=None, step=1): if not stop: # 解決一個引數 stop = start start = 0 while start < stop: # 解決二個引數 yield start start += step # 解決三個引數 # 一個數的情況 res = my_range(10) # 不執行函式體程式碼,而是轉換為生成器(迭代器) for i in res: print(i) # 兩個數的情況 res = my_range(1,10) for i in res: print(i) # 三個數的情況 res = my_range(1,10,3) for i in res: print(i)

yield傳值(瞭解)

def eat(name):
    print('%s 準備乾飯!!!'%name)
    while True:
        food = yield
        print('%s 正在吃 %s' % (name, food))
        
res = eat('jason')  # 並不會執行程式碼,而是轉換成生成器
"""
send與next作用相同,都是進行下一次迭代的意思(都會解阻塞yield關鍵字)
send可以傳遞引數表示yield語句的返回值。而next不能傳遞引數
會先將引數當做yield語句的返回值,然後再解阻塞yield 遍歷。(因此不推薦第一次遍歷時使用send傳參)
"""
res.__next__()
res.send('肉包子')  # send的引數就是yield語句的返回值
res.send('蓋澆飯')
'''
jason 準備乾飯!!!
jason 正在吃 肉包子
jason 正在吃 蓋澆飯
'''

yield與return對比

  • yield

    • 1.可以返回值(支援多個並且組織成元組)

    • 2.函式體程式碼遇到yield不會結束而是"停住"

    • 3.yield可以將函式 變成生成器 並且還支援外界傳值

    • 4.yield可以返回值多次

  • return

    • 1.可以返回值(支援多個並且組織成元組)

    • 2.函式體程式碼遇到return直接結束

    • 3. return只能返回值一次

生成器表示式

# 把列表生成式的[]換成()就是生成器表示式
res = (i for i in range(3))
print(res)
print(next(res))
print(next(res))
print(next(res))
print(next(res))  # 報錯
"""
    迭代器物件,生成器物件,我們都可以看成是"工廠"
    只有當我們所要資料的時候工廠才會加工出"資料"
        上述方式就是為了節省空間
"""

# 統計一個檔案裡面的字元個數
with open('a.txt',mode='rt',encoding='utf-8') as f:
     res = f.read()
     print(len(res))
    
# 考慮到如果檔案過大一次讀嗎?可採用下面方式
# 方式一:
      res = 0
      for line in f:  # 每次統計一行,不費記憶體
          res += len(line)
      print(res)

# 方式二:利用內建函式sum,每取一次加一次
# res = sum((len(line) for line in f))
      res = sum(len(line) for line in f)

      print(res)
    
    
# 生成器表示式筆試題:求和
def add(n, i):
    return n + i
# 呼叫之前是函式 呼叫之後是生成器
def test():
    for i in range(4):
        yield i
g = test()  # 初始化生成器物件
for n in [1, 10]:
    g = (add(n, i) for i in g)
    """
    第一次for迴圈
        g = (add(n, i) for i in g)
    第二次for迴圈
        g = (add(10, i) for i in (add(10, i) for i in g))
    """
res = list(g)
print(res)

# A. res=[10,11,12,13]
# B. res=[11,12,13,14]
# C. res=[20,21,22,23]  √
# D. res=[21,22,23,24]

常見內建函式

1.abs() 函式返回數字的絕對值

print(abs(123))  # 123

print(abs(-123))  # 123

print(abs(10.2))  # 10.2

print(abs(-10.2))  # 10.2

2.all() 用於判斷給定的可迭代引數中的所有元素是否都為True,如果是返回True,否則返回False

l = [11, 22, 33, 44]
print(all(l))  # True

l = [11, 22, 33, 0]  # 元素除了是 0、空、None、False外都算True
print(all(l))  # False


l = []  # 注意:空元組、空列表返回值為True,這裡要特別注意。
print(all(l))  # True

3.any() 用於判斷給定的可迭代引數中的所有元素有一個為True,則返回True,否則返回False

l = [1, 2, 3]
print(any(l))  # True

l = [0, '', None, False]  
print(any(l))  # False

4.bin() 將int轉換成二進位制 oct() 將int轉換成8進位制 hex() 將int轉換成16進位制以字串形式表示

print(bin(123))  # 0b1111011  轉換成二進位制

print(oct(123))  # 0o173  將int轉換成8進位制

print(hex(123))  # 0x7b  將int轉換成16進位制

5.bytes() 將字串轉換成二進位制 str() 將二進位制轉換成字串(需指定編碼)

res = '哈哈哈'
res1 = bytes(res, 'utf8')
print(res1)  # b'\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88'

res2 = str(res1,'utf8')
print(res2)  # 哈哈哈

# 編碼
res1 = res.encode('utf8')  # b'\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88'
print(res1)

# 解碼
res2 = res1.decode('utf8')  # 哈哈哈
print(res2)

6.callable() 於檢查一個物件是否可呼叫的,可呼叫返回 True,否則返回 False

s = 'jason'
print(callable(s))  # False

def index():
    pass
print(callable(index))  # True

7.chr() 根據ASCII碼轉數字找字元 ord() 根據ASCII碼轉字元找數字

print(chr(65))  # A

print(ord('Z'))  # 90

8.complex() 將數字轉化為複數。如果第一個引數為字串,則不需要指定第二個引數

print(complex(1, 3))  # (1+3j) 數字

print(complex(111))  # (111+0j) 數字

print(complex('111'))  # (111+0j) 當做字串處理

9.dir() 檢視當前物件可以呼叫的名字

print(dir())  #  獲得當前模組的屬性列表

print(dir([])) # 檢視列表的方法

def index():
    pass
print(dir(index))  # 檢視函式的方法

10.divmod() 把除數和餘數運算結果結合起來,返回一個包含商和餘數的元組(a // b, a % b)

print(dir())  #  獲得當前模組的屬性列表

print(dir([])) # 檢視列表的方法

def index():
    pass
print(dir(index))  # 檢視函式的方法

11.eval()只能識別簡單的語法 exec()可以識別複雜語法。都是將字串中的資料內容載入並執行

res1 = """
print('hello world')
"""
eval(res1)  # hello world
exec(res1)  # hello world


res = """
for i in range(10):
    print(i)
"""
# eval(res) # 複雜的無法識別
exec(res)  # 可以看到結果

12.isinstance() 來判斷一個物件是否是一個已知的型別

print(isinstance(123, float))  # False

print(isinstance(123, int))  # True

print(isinstance(123, (str, int, list)))  # 是元組中的一個返回True

13.pow() 方法返回 xy(x 的 y 次方) 的值

print(pow(2, 2))  # 4

print(pow(4, 3))  # 27

14.round() 方法返回浮點數x的四捨五入值

a = 4.6
print(round(a))  # 5

b = 4.5
print(round(b))  # 4 可以看成是五舍六入

c = 8.6
print(round(c))  # 9

15.sum() 方法對序列進行求和計算

l = [11, 22, 33, 44]
print(sum(l))  # 110