เข้าสู่เนื้อหา
PEP 8 คืออะไร และถ้าทำตามแล้วช่วยอะไร
PEP 8 (Python Enhancement Proposal 8) คือแนวทางปฏิบัติที่ช่วยให้โค้ด Python อ่านง่าย เป็นมาตรฐานเดียวกัน และเข้าใจได้ง่ายขึ้นในทีมพัฒนา โดยเฉพาะโค้ดที่ใช้ในโครงการขนาดใหญ่หรือโอเพ่นซอร์ส
ช่วยให้โค้ดอ่านง่ายและลดความซับซ้อน
-
ลดปัญหาเกี่ยวกับโค้ดที่อ่านยากหรือโค้ดที่แต่ละคนเขียนไม่เหมือนกัน
-
มีผลต่อการ review โค้ด และช่วยลด bug ได้
ตัวอย่าง PEP ที่เคยผ่านตามาก็
strict mode, ตัวแปรและฟังก์ชัน: ใช้ snake_case (ตัวอักษรเล็กทั้งหมด คั่นด้วย
_)-
คลาส: ใช้ CamelCase (ตัวอักษรตัวแรกของแต่ละคำเป็นตัวใหญ่)
-
ค่าคงที่ (Constants): ใช้ UPPER_CASE
-
ตัวแปรที่ไม่ใช้ (throwaway variables): ใช้
_
(ที่ปกติใช้ i กันนั่นแหละ และผมก็ยังใช้ i อยูบ้าง)
- เว้นวรรคหลัง comma เพื่อให้อ่านง่าย แต่ด้านหน้าไม่ต้องเว้นนะ
spam(ham[1], {eggs: 2})
- เว้นวรรคทั้งหน้าและหลังของ ตัวดำเนินการแบบ binary (เช่น =, +=, ==, and, or)
ซึ่งรวมถึง:
-
การกำหนดค่า (
=) -
การกำหนดค่าร่วม (
+=,-=, ฯลฯ) -
การเปรียบเทียบ (
==,<,>,!=,<=,>=,in,not in,is,is not) -
การดำเนินการแบบตรรกะ (
and,or,not)
x = 1 y = 2 long_variable = 3 if foo == 'blah':
-
- หากมีหลาย operator ที่มีลำดับความสำคัญต่างกัน ควรเว้นวรรคกับตัวที่มีความสำคัญต่ำสุด เพื่อให้โค้ดอ่านง่าย
i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (a-b)
- แต่ไม่เว้นวรรคทั้งหน้าและหลังของ = ใน default arguments และ keyword arguments
ตรงนี้หมายถึงตอนประกาศ function จะมีการส่งค่าเข้ามา และกำหนดค่า default ได้def complex(real, imag=0.0): return magic(r=real, i=imag)
- ไม่เว้นวรรคเป็นตัวสุดท้ายตอนจบบันทัด
- ไม่เว้นวรรคทั้งหน้าและหลังวงเล็บ ไม่ว่าจะเป็น ( ) { } [ ] ให้เขียนติดกันไปเลย
spam(ham[1], {eggs: 2})
- สำหรับ colon : อันนี้จะเรื่องมากหน่อย โดยปกติไม่ควรเว้นวรรคทั้งหน้าและหลัง แต่ถ้ามีการคำนวนอยู่ด้วย ก็สามารถเว้นได้โดยใช้หลักการ เว้นวรรคกับตัวที่มีความสำคัญต่ำสุด และ โคลอนถือเป็นตัวดำเนินการที่มีลำดับความสำคัญต่ำที่สุด
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:] ham[lower:upper], ham[lower:upper:], ham[lower::step] ham[lower+offset : upper+offset] ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)] ham[lower + offset : upper + offset]
- โดยปกติไม่ควรมีความยาวเกิน 79 ตัวอักษร ในแต่ละบันทัด
- ใช้
\หรือ()เพื่อขึ้นบรรทัดใหม่หากต้องการให้โค้ดยาว ๆ อ่านง่ายขึ้น - หากมีการคำนวนยาวๆแล้วอยากขึ้นบันทัดใหม่ ให้เอาเครื่องหมายลงมาด้วย
income = (gross_wages + taxable_interest + (dividends - qualified_dividends) - ira_deduction - student_loan_interest) - ควรเว้น 2 บรรทัด ระหว่าง คลาส หรือ ฟังก์ชัน ที่ไม่ได้อยู่ใน Class
- ภายในคลาส ควรเว้น 1 บรรทัด ระหว่าง Methods (Function ภายใน Class) เพื่อแยกการทำงานของแต่ละ Methods
- หากภายในคลาสมีตัวแปรระดับคลาส (
class attributes) ให้เว้น 1 บรรทัด ระหว่างตัวแปรกับ Methods แรก สามารถเว้น 1 บรรทัด เพื่อแยก กลุ่มของการทำงาน (Logical Sections) ภายในฟังก์ชันได้
- หากต้องการ แยกกลุ่มคำสั่งที่มีความเกี่ยวข้องกัน สามารถเว้นบรรทัดเพื่อให้โค้ดอ่านง่ายขึ้น
import ให้เป็นระเบียบ - Standard library (ไลบรารีที่ติดมากับ Python)
- Third-party libraries (ไลบรารีที่ติดตั้งเพิ่มเติม)
- Local application imports (ไลบรารีที่เราเขียนเอง)
- หลีกเลี่ยง
from module import *เพราะอาจทำให้เกิดปัญหาชื่อซ้ำกัน
ตัวอย่างก็ประมาณนี้
import osimport sysimport numpy as npimport requestsfrom my_project.utils import helper_function
6. ไม่ควรใช้หลายคำสั่งในบันทัดเดียว
ตัวอย่างที่ผิด (เขียนมาตั้งนานถึ่งรู้ว่า python ใช้ ; ในการแบ่งคำสั่งได้)if foo == 'blah': do_blah_thing() do_one(); do_two(); do_three()
ตัวอย่างที่ถูกif foo == 'blah':
do_blah_thing()
do_one()
do_two()
do_three()
7. Comments & Docstrings (การเขียนคอมเมนต์และคำอธิบายฟังก์ชัน)- ควรใช้ภาษาอังกฤษในการเขียน comment
- ใช้ # และเว้นวรรคก่อนเขียนข้อความ สำหรับ comment
- ใช้
""" """สำหรับ docstring
นอกจากที่กล่าวมาแล้ว PEP 8 ยังมีแนวทางสำคัญอื่น ๆ ที่ช่วยให้โค้ด Python เป็นระเบียบ อ่านง่าย และปฏิบัติตามมาตรฐานที่ดี โดยหัวข้อเพิ่มเติมที่ควรเรียนรู้ ได้แก่:
1️⃣ การใช้ Boolean Values อย่างเหมาะสม
-
ใช้
if variable:แทนif variable == True: -
ใช้
if not variable:แทนif variable == False:
✅ ตัวอย่างที่แนะนำ
❌ ตัวอย่างที่ควรหลักเลี่ยง
2️⃣ การเปรียบเทียบค่ากับ None
-
ควรใช้
isและis notเมื่อเปรียบเทียบกับNone -
ห้ามใช้
==หรือ!=เพราะอาจเกิดปัญหาในบางกรณี
✅ ตัวอย่างที่แนะนำ
❌ ตัวอย่างที่ควรหลักเลี่ยง
3️⃣ การใช้ with แทน try-finally ในการจัดการไฟล์
-
ใช้
withstatement เพื่อเปิดไฟล์หรือจัดการ resource ต่าง ๆ แทนtry-finally -
withจะช่วยปิดไฟล์อัตโนมัติ แม้ว่าจะเกิดข้อผิดพลาดระหว่างการอ่านไฟล์
✅ ตัวอย่างที่แนะนำ
❌ ตัวอย่างที่ผิด
4️⃣ การใช้ตัวดำเนินการแบบ in เมื่อเช็คค่าสมาชิก
-
ควรใช้
if item in listแทนif item == element1 or item == element2 -
อ่านง่ายขึ้น และมีประสิทธิภาพมากกว่า
✅ ตัวอย่างที่แนะนำ
❌ ตัวอย่างที่ควรหลักเลี่ยง
5️⃣ หลีกเลี่ยงการใช้ Mutable Default Arguments
-
หลีกเลี่ยงการใช้
list,dict, หรือsetเป็น default argument เพราะค่าจะถูกแชร์ข้ามการเรียกใช้ฟังก์ชัน
✅ ตัวอย่างที่แนะนำ
❌ ตัวอย่างที่ควรหลักเลี่ยง
6️⃣ การจัดการ Exception อย่างเหมาะสม
-
ควรใช้
try-exceptและจับข้อผิดพลาดให้เฉพาะเจาะจง ไม่ควรจับExceptionโดยไม่มีเหตุผล -
หลีกเลี่ยง
except:ที่จับข้อผิดพลาดทั้งหมดโดยไม่ระบุประเภทของข้อผิดพลาด
✅ ตัวอย่างที่แนะนำ
❌ ตัวอย่างที่ควรหลักเลี่ยง
7️⃣ การจัดการ Import Statement ให้มีประสิทธิภาพ
-
หลีกเลี่ยง
import *เพราะทำให้โค้ดอ่านยากและอาจเกิดปัญหาการซ้อนทับของชื่อฟังก์ชัน -
ใช้
from module import function_nameเฉพาะเมื่อใช้บางฟังก์ชันของโมดูลนั้น
✅ ตัวอย่างที่แนะนำ
❌ ตัวอย่างที่ควรหลักเลี่ยง
8️⃣ หลีกเลี่ยงการใช้ Lambda ที่ซับซ้อนเกินไป
-
Lambda ควรใช้สำหรับฟังก์ชันสั้น ๆ เท่านั้น ถ้ามีเงื่อนไขซับซ้อนควรใช้
defแทน คำอธิบายเรื่อง lambda อยู่อีกบทความนะครับ กดที่ lambda ที่หัวข้อได้เลย
✅ ตัวอย่างที่แนะนำ
❌ ตัวอย่างที่ควรหลักเลี่ยง
✅ เขียนใหม่ให้แนะนำ
🔥 สรุปหัวข้อเพิ่มเติมที่ควรรู้ใน PEP 8
| หัวข้อ | คำแนะนำที่สำคัญ |
|---|---|
| ✅ ใช้ Boolean อย่างเหมาะสม | ใช้ if variable: แทน if variable == True: |
✅ เปรียบเทียบ None ด้วย is | ใช้ if x is None: แทน if x == None: |
✅ ใช้ with เปิดไฟล์ | ช่วยปิดไฟล์อัตโนมัติ |
✅ ใช้ in แทน or หลายตัว | if x in [a, b, c]: |
| ✅ หลีกเลี่ยง Mutable Default Arguments | ใช้ None แล้วสร้าง list หรือ dict ภายในฟังก์ชัน |
| ✅ จับข้อผิดพลาดแบบเฉพาะเจาะจง | ใช้ except ValueError: แทน except: |
✅ หลีกเลี่ยง import * | ควร import เฉพาะสิ่งที่ใช้ |
| ✅ หลีกเลี่ยง Lambda ที่ซับซ้อน | ใช้ def แทน Lambda ที่มีเงื่อนไขซับซ้อน |
ไม่มีความคิดเห็น:
แสดงความคิดเห็น