แนวทางและเทคนิค¶
รวบรวมเทคนิคและรูปแบบที่ใช้บ่อยในการเขียนโปรแกรมด้วยภาษาปิยะธอน
การจัดการข้อมูล¶
การอ่านไฟล์แบบประหยัดหน่วยความจำ¶
นิยาม อ่านไฟล์ใหญ่(ชื่อไฟล์):
"""อ่านไฟล์ทีละบรรทัดเพื่อประหยัดหน่วยความจำ"""
ด้วย เปิด(ชื่อไฟล์, 'r', encoding='utf-8') เป็น ไฟล์:
สำหรับ บรรทัด ใน ไฟล์:
ให้ บรรทัด.strip()
การจัดกลุ่มข้อมูล¶
จาก itertools นำเข้า groupby
จาก operator นำเข้า itemgetter
นิยาม จัดกลุ่มตามคีย์(ข้อมูล, คีย์):
"""จัดกลุ่มข้อมูลตามคีย์ที่กำหนด"""
ข้อมูล = เรียงลำดับ(ข้อมูล, key=itemgetter(คีย์))
คืนค่า {k: รายการ(v) สำหรับ k, v ใน groupby(ข้อมูล, key=itemgetter(คีย์))}
# ตัวอย่างการใช้งาน
ข้อมูล = [
{'กลุ่ม': 'A', 'คะแนน': 80},
{'กลุ่ม': 'B', 'คะแนน': 75},
{'กลุ่ม': 'A', 'คะแนน': 90}
]
ผลลัพธ์ = จัดกลุ่มตามคีย์(ข้อมูล, 'กลุ่ม')
การแคชข้อมูล¶
จาก functools นำเข้า lru_cache
@lru_cache(maxsize=128)
นิยาม ดึงข้อมูล(id):
"""ดึงข้อมูลพร้อมแคช"""
# จำลองการดึงข้อมูลจากฐานข้อมูล
คืนค่า f"ข้อมูล: {id}"
# เรียกใช้ฟังก์ชัน - ครั้งแรกจะดึงข้อมูลจริง
ข้อมูล1 = ดึงข้อมูล(1)
# ครั้งต่อไปจะดึงจากแคช
ข้อมูล1_แคช = ดึงข้อมูล(1)
การจัดการข้อผิดพลาด¶
การสร้าง Context Manager¶
จาก contextlib นำเข้า contextmanager
@contextmanager
นิยาม จัดการทรัพยากร(ชื่อ):
"""จัดการการเปิด-ปิดทรัพยากรอัตโนมัติ"""
พิมพ์(f"กำลังเปิด {ชื่อ}")
ลอง:
ให้ ชื่อ
สุดท้าย:
พิมพ์(f"กำลังปิด {ชื่อ}")
# ตัวอย่างการใช้งาน
ด้วย จัดการทรัพยากร("ไฟล์ทดสอบ") เป็น res:
พิมพ์("กำลังใช้งานทรัพยากร")
การจัดการข้อผิดพลาดหลายประเภท¶
นิยาม ทำงานที่อาจผิดพลาด():
"""จัดการข้อผิดพลาดหลายประเภท"""
ลอง:
# โค้ดที่อาจเกิดข้อผิดพลาด
ผลลัพธ์ = ทำงาน()
ยกเว้น ValueError เป็น e:
พิมพ์(f"ข้อมูลไม่ถูกต้อง: {e}")
ยกเว้น TypeError เป็น e:
พิมพ์(f"ชนิดข้อมูลไม่ถูกต้อง: {e}")
ยกเว้น Exception เป็น e:
พิมพ์(f"เกิดข้อผิดพลาด: {e}")
อื่น:
พิมพ์("ทำงานสำเร็จ")
สุดท้าย:
พิมพ์("เสร็จสิ้นการทำงาน")
การทำงานกับไฟล์¶
การหาไฟล์ทั้งหมดในโฟลเดอร์¶
จาก pathlib นำเข้า Path
นิยาม หาไฟล์(โฟลเดอร์, นามสกุล="*"):
"""หาไฟล์ทั้งหมดในโฟลเดอร์และโฟลเดอร์ย่อย"""
พาธ = Path(โฟลเดอร์)
คืนค่า รายการ(พาธ.rglob(f"*.{นามสกุล}"))
# ตัวอย่างการใช้งาน
ไฟล์_py = หาไฟล์("src", "py")
สำหรับ ไฟล์ ใน ไฟล์_py:
พิมพ์(ไฟล์)
การประมวลผลไฟล์ CSV แบบ Streaming¶
นำเข้า csv
จาก itertools นำเข้า islice
นิยาม ประมวลผล_csv(ชื่อไฟล์, ขนาด_batch=1000):
"""ประมวลผลไฟล์ CSV ทีละส่วน"""
ด้วย เปิด(ชื่อไฟล์, newline='', encoding='utf-8') เป็น csvfile:
reader = csv.DictReader(csvfile)
ขณะที่ จริง:
batch = รายการ(islice(reader, ขนาด_batch))
ถ้า ไม่ batch:
หยุด
ให้ batch
การทำงานกับเวลา¶
การวัดเวลาทำงาน¶
จาก time นำเข้า perf_counter
จาก functools นำเข้า wraps
นิยาม จับเวลา(func):
"""เดคอเรเตอร์สำหรับวัดเวลาทำงานของฟังก์ชัน"""
@wraps(func)
นิยาม wrapper(*args, **kwargs):
เริ่ม = perf_counter()
ผลลัพธ์ = func(*args, **kwargs)
สิ้นสุด = perf_counter()
พิมพ์(f"{func.__name__} ใช้เวลา {สิ้นสุด - เริ่ม:.4f} วินาที")
คืนค่า ผลลัพธ์
คืนค่า wrapper
# ตัวอย่างการใช้งาน
@จับเวลา
นิยาม ทำงานนาน():
จาก time นำเข้า sleep
sleep(1)
การจัดการเขตเวลา¶
จาก datetime นำเข้า datetime
จาก zoneinfo นำเข้า ZoneInfo
นิยาม แปลงเขตเวลา(เวลา, จาก_โซน, ไป_โซน):
"""แปลงเวลาระหว่างเขตเวลา"""
เวลา_ต้นทาง = เวลา.replace(tzinfo=ZoneInfo(จาก_โซน))
คืนค่า เวลา_ต้นทาง.astimezone(ZoneInfo(ไป_โซน))
# ตัวอย่างการใช้งาน
เวลา = datetime.now()
เวลา_ไทย = แปลงเขตเวลา(เวลา, "UTC", "Asia/Bangkok")
เทคนิคการเขียนโค้ด¶
การใช้ Generator¶
นิยาม อ่านทีละบรรทัด(ไฟล์):
"""Generator สำหรับอ่านไฟล์ทีละบรรทัด"""
ด้วย เปิด(ไฟล์, 'r', encoding='utf-8') เป็น f:
สำหรับ บรรทัด ใน f:
ให้ บรรทัด.strip()
# ตัวอย่างการใช้งาน
สำหรับ บรรทัด ใน อ่านทีละบรรทัด('ไฟล์.txt'):
พิมพ์(บรรทัด)
การทำงานแบบขนาน¶
จาก concurrent.futures นำเข้า ThreadPoolExecutor, ProcessPoolExecutor
นิยาม ประมวลผลขนาน(ข้อมูล, func, ประเภท='thread', max_workers=4):
"""ประมวลผลข้อมูลแบบขนาน"""
Executor = ThreadPoolExecutor ถ้า ประเภท == 'thread' อื่น ProcessPoolExecutor
ด้วย Executor(max_workers=max_workers) เป็น executor:
ผลลัพธ์ = รายการ(executor.map(func, ข้อมูล))
คืนค่า ผลลัพธ์
# ตัวอย่างการใช้งาน
นิยาม ทำงาน(x):
คืนค่า x * x
ข้อมูล = ช่วง(10)
ผลลัพธ์ = ประมวลผลขนาน(ข้อมูล, ทำงาน)
การทดสอบ¶
การเขียนเทสต์¶
จาก unittest นำเข้า TestCase, main
จาก unittest.mock นำเข้า Mock, patch
ชั้น ทดสอบการทำงาน(TestCase):
นิยาม setUp(ตัว):
ตัว.ข้อมูล = {'id': 1, 'ชื่อ': 'ทดสอบ'}
นิยาม test_การคำนวณ(ตัว):
ผลลัพธ์ = คำนวณ(ตัว.ข้อมูล)
ตัว.assertEqual(ผลลัพธ์, 1)
@patch('module.external_api')
นิยาม test_เรียก_api(ตัว, mock_api):
mock_api.return_value = {'status': 'ok'}
ผลลัพธ์ = เรียก_api()
ตัว.assertEqual(ผลลัพธ์['status'], 'ok')
ถ้า __ชื่อ__ == '__main__':
main()
Note
เทคนิคและรูปแบบเหล่านี้สามารถนำไปประยุกต์ใช้กับโค้ดของคุณ โดยปรับแต่งให้เหมาะสมกับความต้องการเฉพาะได้