1 解包
所謂解包,就是將字典通過 ** 操作符轉為 Key=Value 的形式,這種形式可以直接傳給函式作為關鍵字引數。 說說適用的幾種情況。
1.1 搜尋拼接條件
當應用中使用類似 SQLAlchemy 的 ORM 形式讀取資料的時候,不同搜尋條件,傳入給 ORM 的搜尋引數也隨之改變。 下面是圖書表的部分資料(只展示了部分欄位)
+----+---------------+-------------------------+-------+
| id | category_name | book_name | price |
+----+---------------+-------------------------+-------+
| 1 | 人文社科 | 人類簡史 | 42.90 |
| 2 | 人文社科 | 世界簡史 | 25.50 |
| 3 | 經濟管理 | 極致產品 | 37.00 |
| 4 | 經濟管理 | 史蒂夫·賈伯斯傳 | 44.20 |
| 5 | 經濟管理 | 影響力 | 41.20 |
+----+---------------+-------------------------+-------+
複製程式碼
搜尋時,我們會以這樣的形式執行查詢方法
books = Book.query.filter_by(id=1, book_name='影響力').all()
複製程式碼
但是由於傳入引數會根據搜尋條件的變化而變化,無法直接寫出有哪些引數,這個時候就可以使用字典解包
condition = {}
if book_id:
condition['id'] = id
if book_name:
condition['name'] = book_name
books = Book.query.filter_by(**condition).all()
複製程式碼
這樣就 OK 了
1.2 方法引數太多,為程式碼美觀使用
new_book = Book(category_name='文學小說', book_name='解憂雜貨店', price=28.8,
...)
db.session.add(new_book)
複製程式碼
改成這樣的話,美觀一些
book_param = {'category_name': '文學小說', 'book_name': '解憂雜貨店', 'price': 28.8,
...}
new_book = Book(**book_param)
db.session.add(new_book)
複製程式碼
並且,在上述新增圖書過程中,都會對提交的引數進行校驗,而校驗方法返回的結果(也就是 book_param
和其它資訊)一般也都是字典,所以使用字典解包的方式更符合實際場景。
總之,適當使用字典解包對方法進行傳參,可以讓我們的程式碼更靈活。
2 setdefault() 的使用
先看下這個方法怎麼使用
dict.setdefault(key, default=None)
如果字典中包含有給定鍵,則返回該鍵對應的值,否則返回為該鍵設定的值。
很多時候我們需要對列表根據元素的某個 key 轉化成一個包含列表的字典。比如,上面的資料中,我希望得到一個字典,字典的 key 是圖書分類,value 是屬於該分類的圖書列表。我們通常會這樣寫
books_dict = {}
for book in book_list:
if book['category_name'] not in books_dict.keys():
books_dict[book['category_name']] = []
books_dict[book['category_name']].append(book)
複製程式碼
當然,這樣寫是正確的,能得到預期結果
{
"人文社科": [{
"id": 1,
"category_name": "人文社科",
"book_name": "人類簡史",
"price": 42.9
}, {
"id": 2,
"category_name": "人文社科",
"book_name": "世界簡史",
"price": 25.5
}],
"經濟管理": [{
"id": 3,
"category_name": "經濟管理",
"book_name": "極致產品",
"price": 37.0
}, {
"id": 4,
"category_name": "經濟管理",
"book_name": "史蒂夫·賈伯斯傳",
"price": 44.2
}, {
"id": 5,
"category_name": "經濟管理",
"book_name": "影響力",
"price": 41.2
}]
}
複製程式碼
但是如果使用字典的 setdefault() 方法話,可以少寫幾行程式碼,看起來也優雅一些
books_dict = {}
for book in book_list:
books_dict.setdefault(book['category_name'], []).append(book)
複製程式碼
3 字典合併
常用的合併方式
# new_dict = {**dict1, **dict2, ...}
# 合併多個字典,如果字典中存在相同的 key 的話,後面的會覆蓋掉前面的
# 比如 dict2 會覆蓋 dict1 中的 key 相同的值
>>> a = {'name': 'x', 'age': 13}
>>> b = {'name': 'y'}
>>> c = {**a, **b}
>>> c
{'name': 'y', 'age': 13}
# dict1.update(dict2)
# 合併兩個字典,如果字典中存在相同的 key 的話,dict2 會覆蓋 dict1 的對應值
# 理解為更新某個字典應該更合適
>>> a.update(b)
>>> a
{'name': 'y', 'age': 13}
複製程式碼
有時我們碰到合併字典的情況也不少。比如,我們準備根據一本書的基本資訊建立一本新書
# to_dict 將 ORM 物件轉為字典,是自定義的,理解意思就好
base_book = Book.query.filter_by(id=1).first().to_dict()
# 提交的引數需要校驗,校驗成功後返回值包含 book_param ,內容和下面類似
book_param = {'book_name': '國家寶藏', 'price': 55.60}
# 同時需要更新新書的建立時間和更新時間
time_param = {'created_at': current_time, 'updated_at': current_time}
# 新增書籍
new_book = Book(**{**base_book, **book_param, **time_param})
db.session.add(new_book)
複製程式碼
當然,如果只是合併兩個字典的話,也可以使用 update() 方法。
假設我們只需要合併 base_book
和 book_param
base_book.update(book_param)
複製程式碼
這也可以工作,不過要注意,這樣會修改 base_book
中的值。
如果只是單純的更新某個字典的資訊的話,update() 方法顯然最合適。對於當前需求的話,還是第一種方式更合適。
本文首發於公眾號「小小後端」,關注並回復關鍵字「1024」,各種 IT 學習資料大禮包免費贈送。