推導式(comprehensions),又稱解析式,是 Python 中常見的語法糖。推導式可以從一個數據序列構建另一個新的數據序列,常用於數據處理場景。
推導式的核心為 for 循環。根據返回對象的不同,推導式可區分為列表推導式,字典推導式,結合推導式等。不同推導式在語法上基本一致。
列表推導式(list comprehension)是一種簡化的 for 循環創建列表,為最常見的推導式。
用 [] 生成list
基本格式 : [ 表達式 for 迭代變量 in 可迭代對象 if 條件表達式 ]
# # 打印20以內不是3的倍數的數,並且平方
result1 = []
for i in range(20):
if i % 3:
result1.append(i * i)
print(result1)
# 等價於
result2 = [i * i for i in range(20) if i % 3]
print(result2)
# 上面[i * i for i in range(20) if i % 3]就是一個列表推導式
列表推導式簡化了代碼,返回新的列表。這樣看來推導式是不是非常便捷
再舉兩個例子
# # 使用列表推導式輸出200以內,,開平方是整數的數
import math
result1 = [i for i in range(200) if (math.sqrt(i).is_integer())]
print(result1)
# # 對列表中的數,取兩位小數
li = [2.45345, 4.3454325, 9, 82.234324, 9.841234]
result2 = [round(i, 2) for i in li]
print(result2)
與列表推導式相比,集合推導式因為集合自身的特性,帶有去重功能。
基本格式 : { 表達式 for 迭代變量 in 可迭代對象 if 條件表達式 }
str1 = "asasodefewihftyzrfea"
print({
i for i in str1})
#------結果-----
D:\softs\python\python.exe E:/project/sanchuang/python基礎/迭代器與生成器/code_推導式.py
{
'i', 'f', 'w', 's', 'e', 'h', 'z', 't', 'y', 'o', 'a', 'r', 'd'}
結果會將重復字母自動去除
字典推導和列表推導的使用方法是類似的,只是中括號該改成大括號。
基本格式 : { 表達式 for 迭代變量 in 可迭代對象 if 條件表達式 }
# # 統計str1中每一個字符出現的次數
str1 = "asodefehfrfea"
# 常規寫法
tmp = {
}
for i in str1:
if i in tmp:
tmp[i] += 1
else:
tmp[i] = 1
print(tmp)
# 字典推導式
print({
i: str1.count(i) for i in str1})
#------結果-----
D:\softs\python\python.exe E:/project/sanchuang/python基礎/迭代器與生成器/code_推導式.py
{
'a': 2, 's': 1, 'o': 1, 'd': 1, 'e': 3, 'f': 3, 'h': 1, 'r': 1}
{
'a': 2, 's': 1, 'o': 1, 'd': 1, 'e': 3, 'f': 3, 'h': 1, 'r': 1}
再舉幾個例子
# 過濾長度小於3的字符串列表,並將剩下的轉換成大寫字母
q1 = ['a', 'ab', 'abc', 'abcd', 'abcde']
print([i.upper() for i in q1 if len(i) >= 3])
# 求(x,y)其中x是0-5之間的偶數,y是0-5之間的奇數組成的元組列表
print([(x, y) for x in range(6) if x % 2 == 0 for y in range(6) if y % 2 == 1])
# 更換key和value
q3 = {
'a': 10, 'b': 34}
print({
y: x for x, y in q3.items()})
# 合並大小寫對應的value值,將k統一成小寫
q4 = {
'B': 3, 'a': 1, 'b': 6, 'c': 3, 'A': 4}
print({
x.lower(): q4.get(x.lower(), 0)+q4.get(x.upper(), 0) for x in q4})
# ------結果-----
D:\softs\python\python.exe E:/project/sanchuang/python基礎/迭代器與生成器/code_推導式.py
['ABC', 'ABCD', 'ABCDE']
[(0, 1), (0, 3), (0, 5), (2, 1), (2, 3), (2, 5), (4, 1), (4, 3), (4, 5)]
{
10: 'a', 34: 'b'}
{
'b': 9, 'a': 5, 'c': 3}
Process finished with exit code 0
常見的可迭代對象: 容器類型數據(list、set、dict)都是可迭代對象,打開的文件,range等
定義:對象實現了__iter__方法,並且該方法返回一個迭代器,則該對象為可迭代對象
str1 = "abc"
# 一般來說容器類型都是可迭代對象,包含__init__方法
print(dir(str1))
# 結果########################
D:\softs\python\python.exe E:/project/sanchuang/python基礎/迭代器與生成器/code_推導式.py
['__add__', '__class__', '__contains__', '__iter__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
判斷一個對象是不是可迭代對象
from collections import Iterable
print(isinstance('abc', Iterable)) # 判斷是否為可迭代對象,是則返回True
什麼是迭代器?實現了__iter__()方法和__next__()方法的都是迭代器,迭代器一定是可迭代對象
迭代器優點:一個一個的加載,不會一次性消耗大量的內存(懶加載、惰性取值、用的時候才生成)。
# # 自定義迭代器
class A:
def __iter__(self):
return self
def __next__(self):
pass
# 編寫迭代器實現range
class MyRange(object):
tmp = -1
def __init__(self, num):
self.num = num
def __iter__(self):
return self
def __next__(self):
self.tmp += 1
if self.tmp < self.num:
return self.tmp
raise StopIteration
li = MyRange(3)
print(next(li))
print(next(li))
print(next(li))
# print(next(li)) # 超出范圍3會報錯
# 編寫迭代器實現斐波那契數 1,1,2,3,5,8,13......
class Fibonacci(object):
def __init__(self, num):
self.num = num
self.tmp = 0
self.pre1 = 0
self.pre2 = 1
def __iter__(self):
return self
def __next__(self):
if self.tmp < self.num:
self.pre1, self.pre2 = self.pre2, self.pre1 + self.pre2
self.tmp = self.pre1
return self.pre1
raise StopIteration
li = Fibonacci(21)
for i in li:
print(i)
特殊的迭代器、不需要手動實現__iter__和__next__方法
==》 就是為了寫迭代器更加的簡單優雅
生成器函數-----yield關鍵字
yield 用於保留中間算法,下次繼續執行。當調用next時,遇到yield就暫停運行,並且返回yield後面表達式的值,當再次調用時,會從剛才暫停的地方繼續執行,直到遇到下一個yield或者整個生成器結束為止。
常用於對大文件/復雜的數據庫查詢,進行處理,即處理大數據集合。
# yield舉例
def get_content():
print("start yield.....")
yield 3
print("second yield....")
yield 4
print("end....")
g1 = get_content()
print(next(g1))
print(next(g1))
# print(next(g1)) # 超出范圍
------結果--------
D:\softs\python\python.exe E:/project/sanchuang/python基礎/迭代器與生成器/code_迭代器與生成器.py
start yield.....
3
second yield....
4
Process finished with exit code 0
# 生成器實現range
def MyRange(num):
i = 0
while i < num:
yield i
i += 1
raise StopIteration # 當超出range范圍時報錯
for i in MyRange(10):
print(i)
與迭代器實現range功能相比,很顯然這裡代碼簡潔許多
# 使用生成器實現斐波那契數列 1,1,2,3,5,8,13......
def Fibonacci(num):
pre1 = 0
pre2 = 1
tmp = 0
while tmp < num:
pre1, pre2 = pre2, pre1 + pre2
tmp += 1
yield pre1
raise StopIteration
fib = Fibonacci(10)
for i in fib:
print(i)
Catalog One 、 Single factor a
What is recursion recursive ,