การอภิปรายล่าสุดเกี่ยวกับแนวปฏิบัติที่ดีของ Python dataclass ได้จุดประกายการถกเถียงในชุมชนที่กว้างขึ้นเกี่ยวกับการจัดการ keyword arguments ของภาษานี้และความจำเป็นในการใช้ไวยากรณ์ที่กระชับกว่า การสนทนาเริ่มต้นด้วยคำแนะนำในการใช้ keyword-only arguments ใน dataclasses แต่ได้พัฒนาไปสู่การตรวจสอบเชิงลึกเกี่ยวกับความยาวเยิ่นของ Python เมื่อเปรียบเทียบกับภาษาโปรแกรมมิ่งอื่น ๆ
การเปรียบเทียบไวยากรณ์ Keyword-Only ของ Python Dataclass
dataclass แบบดั้งเดิม:
@dataclass
class MyDataClass:
x: int
y: str
z: bool = True
dataclass แบบ keyword-only (แนะนำ):
@dataclass(kw_only=True)
class MyDataClass:
x: int
y: str
z: bool = True
ความแตกต่างในการใช้งาน:
- แบบดั้งเดิม:
MyDataClass(1, 'foo', False)
- แบบ keyword-only:
MyDataClass(x=1, y='foo', z=False)
ปัญหาความยาวเยิ่น
นักพัฒนา Python รู้สึกหงุดหงิดมากขึ้นกับลักษณะที่ซ้ำซากของ keyword arguments โดยเฉพาะเมื่อชื่อตัวแปรตรงกับชื่อพารามิเตอร์ทุกประการ ข้อกำหนดปัจจุบันที่ต้องเขียน function(x=x, y=y, z=z)
ทำให้โปรแกรมเมอร์หลายคนที่เคยสัมผัสกับวิธีแก้ปัญหาที่สวยงามกว่าในภาษาอื่น ๆ รู้สึกว่ามันยาวเยิ่นโดยไม่จำเป็น
ไวยากรณ์แบบย่อสำหรับ property ของ JavaScript ได้กลายเป็นจุดที่นักพัฒนา Python อิจฉาเป็นพิเศษ ใน JavaScript นักพัฒนาสามารถเขียนแค่ {x, y, z}
แทนที่จะเป็น {x: x, y: y, z: z}
เมื่อชื่อ property ตรงกับชื่อตัวแปร ฟีเจอร์นี้ช่วยลดการทำซ้ำของโค้ดและปรับปรุงความสามารถในการอ่านได้อย่างมาก
ความพยายามแก้ปัญหาที่ล้มเหลว
ชุมชน Python ได้พยายามแก้ไขปัญหานี้ผ่านช่องทางอย่างเป็นทางการ PEP 736 เสนอไวยากรณ์แบบย่อโดยใช้สัญลักษณ์ fn(x=, y=, z=)
แต่ข้อเสนอนี้ถูกปฏิเสธในที่สุด นักพัฒนาหลายคนแสดงความโล่งใจกับการปฏิเสธนี้ โดยรู้สึกว่าไวยากรณ์ที่เสนอมานั้นแปลกและไม่ได้ให้วิธีแก้ปัญหาที่สวยงามตามที่พวกเขาหวังไว้
จากที่ดูแล้ว ความรู้สึกที่ฉันได้รับคือข้อเสนอไวยากรณ์ที่ดีและสะดวกได้ถูกปฏิเสธเพราะการถกเถียงเรื่องเล็กน้อย
สมาชิกชุมชนได้เสนอแนวทางทางเลือกหลายแบบ บางคนเสนอการใช้ไวยากรณ์แบบ OCaml ด้วยสัญลักษณ์ tilde ในขณะที่คนอื่น ๆ แนะนำแนวทาง semicolon prefix ของ Julia อย่างไรก็ตาม ทางเลือกเหล่านี้ไม่ได้รับการสนับสนุนหรือการพิจารณาอย่างเป็นทางการอย่างมีนัยสำคัญ
โซลูชันไวยากรณ์แบบย่อที่เสนอสำหรับ Python
ภาษา | ไวยากรณ์ปัจจุบัน | ไวยากรณ์แบบย่อ | สถานะ |
---|---|---|---|
JavaScript | {x: x, y: y, z: z} |
{x, y, z} |
ใช้งานได้ |
Python (PEP 736) | fn(x=x, y=y, z=z) |
fn(x=, y=, z=) |
ถูกปฏิเสธ |
OCaml-style | fn(x=x, y=y) |
fn(~x, ~y) |
เสนอแนะ |
Julia-style | fn(x=x, y=y) |
fn(;x, y) |
เสนอแนะ |
วิธีแก้ปัญหาชั่วคราวใน Python ปัจจุบัน:
f(**{x, y, z})
- ใช้การแกะ dictionary แต่อ่านยากกว่า
วิธีแก้ปัญหาชั่วคราวและวิธีแก้ปัจจุบัน
แม้จะไม่มีไวยากรณ์แบบย่อดั้งเดิม นักพัฒนา Python ก็ได้พบวิธีแก้ปัญหาชั่วคราวที่สร้างสรรค์ วิธีหนึ่งคือการใช้ dictionary unpacking ด้วย f(**{x, y, z})
แม้ว่าไวยากรณ์นี้จะไม่ค่อยสวยงามและอาจทำให้เกิดความสับสนในการอ่าน
ชุมชนยังได้ยอมรับ TypedDict เป็นวิธีแก้ปัญหาสำหรับเอกสารที่ดีกว่าและการสนับสนุนจาก IDE เมื่อต้องจัดการกับ keyword arguments แนวทางนี้ช่วยแก้ไขจุดเจ็บปวดบางส่วนเกี่ยวกับการใช้ ** kwargs โดยเฉพาะในไลบรารีเช่น boto3 ที่เอกสารพารามิเตอร์มีคุณภาพไม่ดีในอดีต
การถกเถียงปรัชญาที่กว้างขึ้น
การอภิปรายได้เปิดเผยความตึงเครียดพื้นฐานในปรัชญาการออกแบบของ Python นักพัฒนาบางคนโต้แย้งว่าการที่ Python ชอบไวยากรณ์ที่ชัดเจนและเฉพาะกิจมากกว่า composable primitives กำลังนำภาษาไปสู่ความซับซ้อนที่ไม่จำเป็น พวกเขากังวลว่า Python กำลังเข้าใกล้สถานการณ์ที่คล้ายกับ C++ ที่ไวยากรณ์กลายเป็นเรื่องกว้างขวางมากจนนักพัฒนาเพียงไม่กี่คนเท่านั้นที่เข้าใจอย่างครอบคลุม
คนอื่น ๆ ปกป้องแนวทางปัจจุบันของ Python โดยโต้แย้งว่าไวยากรณ์ที่ชัดเจนและการครอบคลุมไลบรารีมาตรฐานที่ครบถ้วนช่วยลดความจำเป็นในการพึ่งพาภายนอกและทำให้โค้ดอ่านง่ายขึ้นในระยะยาว
บทสรุป
แม้ว่าตัวกระตุ้นโดยตรงสำหรับการอภิปรายนี้จะเป็นแนวปฏิบัติที่ดีของ dataclass แต่มันได้เปิดเผยความกังวลที่ลึกซึ้งกว่าเกี่ยวกับวิวัฒนาการและการออกแบบไวยากรณ์ของ Python ชุมชนยังคงแบ่งแยกเกี่ยวกับว่า Python ต้องการไวยากรณ์ที่กระชับกว่าสำหรับรูปแบบทั่วไปหรือไม่ หรือว่าแนวทางที่ชัดเจนในปัจจุบันให้บริการเป้าหมายของภาษาในด้านความสามารถในการอ่านและการบำรุงรักษาได้ดีกว่า ขณะที่ Python ยังคงพัฒนาต่อไป การถกเถียงเหล่านี้น่าจะมีอิทธิพลต่อการตัดสินใจออกแบบภาษาในอนาคตและทิศทางของ PEPs ที่จะมาถึง
อ้างอิง: Tip: Use keyword-only arguments in Python dataclasses