Python命名元組collections.namedtuple定製數據類

問題描述

需求多變,導致數據類型容易變,一昧使用字典和元組類型讓開發越來越複雜難懂。

開發成績表並計算每個人的平均分

  1. 成績表保存學生姓名和成績
grades = {
    'a': [70, 80],
    'b': [80, 90]
}
for key, value in grades.items():
    print('{}:{}'.format(key, sum(value) / len(value)))
# a:75.0
# b:85.0
  1. 成績表保存學生姓名和成績,成績按科目保存
grades = {
    'a': {
        'Chinese': [60, 70],
        'Math': [70, 80]
    },
    'b': {
        'Chinese': [70, 80],
        'Math': [80, 90]
    }
}
for key, value in grades.items():
    for k, v in value.items():
        print('{} {}:{}'.format(key, k, sum(v) / len(v)))
# a Chinese:65.0
# a Math:75.0
# b Chinese:75.0
# b Math:85.0
  1. 成績表保存學生姓名和成績,成績按科目保存且帶權重
grades = {
    'a': {
        'Chinese': [
            (60, 0.3),  # 期中考佔30%
            (70, 0.7)  # 期末考佔70%
        ],
        'Math': [
            (70, 0.3),
            (80, 0.7)
        ]
    },
    'b': {
        'Chinese': [
            (70, 0.3),
            (80, 0.7)
        ],
        'Math': [
            (80, 0.3),
            (90, 0.7)
        ]
    }
}
for key, value in grades.items():
    for k, v in value.items():
        count = 0
        for i in v:
            count += i[0] * i[1]
        print('{} {}:{}'.format(key, k, count))
# a Chinese:67.0
# a Math:77.0
# b Chinese:77.0
# b Math:87.0




解決方案

應避免數據類型嵌套大於一層,如不要使用字典的字典

使用命名元組collections.namedtuple

命名元組賦予每個位置一個含義,有良好的可讀性。它們可以用於任何普通元組,並能通過名字獲取值,也可以通過索引獲取




代碼

from collections import namedtuple

Grade = namedtuple("Grade", ("score", "weight"))
grades = {
    'a': {
        'Chinese': [
            Grade(60, 0.3),  # 期中考佔30%
            Grade(70, 0.7)  # 期末考佔70%
        ],
        'Math': [
            Grade(80, 0.3),
            Grade(90, 0.7)
        ]
    },
    'b': {
        'Chinese': [
            Grade(70, 0.3),
            Grade(80, 0.7)
        ],
        'Math': [
            Grade(80, 0.3),
            Grade(90, 0.7)
        ]
    }
}
for key, value in grades.items():
    for k, v in value.items():
        count = 0
        for i in v:
            count += i.score * i.weight
        print('{} {}:{}'.format(key, k, count))
# a Chinese:67.0
# a Math:87.0
# b Chinese:77.0
# b Math:87.0




更多示例

  1. CSV

employees.csv

name,age,title,department,paygrade
a,22,elementary,development,1
b,25,intermediate,sales,2
c,30,high,personnel,3
import csv
from collections import namedtuple

EmployeeRecord = namedtuple("EmployeeRecord", "name, age, title, department, paygrade")

for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "r"))):
    print(emp.name, emp.title)
# name title
# a elementary
# b intermediate
# c high
  1. sqlite3
import os
import sqlite3
from collections import namedtuple

database = "companydata.db"

# 創建SQLite數據庫
if os.path.exists(database):
    os.remove(database)
connection = sqlite3.connect(database)
cursor = connection.cursor()
cursor.execute("CREATE TABLE 'employees' ('name' text, 'age' text, 'title' text, 'department' text, 'paygrade' text)")
cursor.execute("INSERT INTO 'employees' VALUES ('a','22','elementary','development', '1')")
cursor.execute("INSERT INTO 'employees' VALUES ('b','25','intermediate','sales', '2')")
cursor.execute("INSERT INTO 'employees' VALUES ('c','30','high','personnel', '3')")
connection.commit()
connection.close()

# 從數據庫導入
connection = sqlite3.connect(database)
cursor = connection.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
for emp in map(EmployeeRecord._make, cursor.fetchall()):
    print(emp.name, emp.title)
# name title
# a elementary
# b intermediate
# c high




侷限

  1. 無法指定參數默認值:若屬性較多用起來不方便
  2. 可通過下標或迭代訪問:容易造成他人誤解,難以遷移到類

若數據類型含有非基本數據類型,或涉及多人開發,那麼最好定義自己的類




參考文獻

  1. namedtuple() 命名元組的工廠函數
  2. 如何在Python 3中使用collections模塊
  3. How To Use the collections Module in Python 3
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章