ตัวอย่างที่เป็นรูปธรรมของ Python“ วิธีเดียวที่จะทำได้” maxim [ปิด]


34

ฉันกำลังเรียนรู้ Python และรู้สึกทึ่งกับประเด็นต่อไปนี้ใน PEP 20 The Zen of Python :

ควรมีอย่างน้อยหนึ่งวิธีที่ชัดเจนกว่าที่จะทำ แม้ว่าวิธีนี้อาจไม่ชัดเจนในตอนแรกเว้นแต่ว่าคุณเป็นชาวดัตช์

ใครสามารถเสนอตัวอย่างที่เป็นรูปธรรมของคติพจน์นี้ได้บ้าง ฉันสนใจเป็นพิเศษในการเปรียบเทียบกับภาษาอื่นเช่นทับทิม ส่วนหนึ่งของปรัชญาการออกแบบทับทิม (ที่มาจากภาษา Perl ฉันคิดว่า?) ก็คือการทำสิ่งต่าง ๆ เป็นสิ่งที่ดี ทุกคนสามารถเสนอตัวอย่างที่แสดงข้อดีข้อเสียของแต่ละวิธีได้หรือไม่ หมายเหตุฉันไม่ได้หลังจากคำตอบที่ดีกว่า (ซึ่งอาจเป็นอัตนัยเกินกว่าที่จะตอบ) แต่เป็นการเปรียบเทียบที่ไม่ลำเอียงของทั้งสองสไตล์

คำตอบ:


47

เปรียบเทียบกับภาษาอย่าง Perl, Python มีโครงสร้างควบคุมจำนวน จำกัด :

  • เท่านั้นifและไม่มีการunless,
  • เท่านั้นforที่ iterates กว่าลำดับและไม่มีforeachหรือ C สไตล์for,
  • เพียงwhileว่าการตรวจสอบสภาพทุกห่วงและไม่มีdo-while,
  • เท่านั้นif-elifและไม่มีการswitch,
  • มีเพียงความคิดเห็นเดียวที่สร้างขึ้น#และสำหรับทุกบรรทัดที่คุณสามารถบอกได้ว่ามีการใส่ความคิดเห็นหรือไม่โดยไม่ดูที่บรรทัดก่อนหน้า

นอกจากนี้ยังมีวิธีหนึ่งในการเยื้องแหล่งที่มาของคุณ กรณีส่วนใหญ่ของการเยื้องโฆษณาจะได้รับการยกเว้น

สิ่งนี้ทำให้การวิเคราะห์แหล่ง Python ง่ายขึ้นสำหรับมนุษย์

มีความพยายามที่จะสร้างน้อยที่สุด แต่สมบูรณ์ในประเภทที่มีอยู่แล้วและไลบรารีมาตรฐาน

  • สำหรับรายการที่ไม่แน่นอนคุณใช้listชนิดในตัวเท่านั้น เป็น O (1) สำหรับการปฏิบัติงานส่วนใหญ่และคุณไม่จำเป็นต้องเลือกใช้งานที่เหมาะสม
  • สำหรับรายการที่ไม่เปลี่ยนแปลงอย่างเท่าเทียมกันคุณเพียงแค่ใช้tupleประเภท
  • สำหรับแผนที่คุณสามารถใช้ในตัวเท่านั้นdictซึ่งมีประสิทธิภาพแช่งในกรณีส่วนใหญ่จำเป็นต้องไตร่ตรองซึ่งการดำเนินการที่จะใช้ไม่ได้

Python 3 ขยายไปถึงจำนวนเต็ม: ไม่ว่าจำนวนเต็มของคุณจะใหญ่แค่ไหนคุณก็ใช้ประเภทเดียวกันและไม่สนใจเรื่องการบีบบังคับ

Python พยายามหลีกเลี่ยงการสร้างประโยคน้ำตาล แต่บางครั้งมันจะเพิ่มน้ำตาลประโยคเพียงเพื่อให้วิธีที่ชัดเจนที่เห็นได้ชัด คุณสามารถเขียนif foo is not Noneแทนif not (foo is None)เพราะ 'ไม่ได้เป็น' ใส่ซองพิเศษ ยังfoo is not Noneอ่านได้ง่ายไม่สามารถตีความผิดและคุณไม่ต้องคิดคุณแค่เขียนสิ่งที่ชัดเจน

แน่นอนว่าสิ่งที่ซับซ้อนยิ่งกว่าใน Python สามารถทำได้หลายวิธี คุณสามารถเพิ่มวิธีการเรียนโดยการประกาศหรือโดยการกำหนดช่องง่ายคุณสามารถส่งข้อโต้แย้งไปยังฟังก์ชั่นในหลายวิธีสร้างสรรค์ ฯลฯ นั่นเป็นเพียงเพราะ internals ของภาษาส่วนใหญ่จะเปิดเผย

กุญแจสำคัญคือมักจะมีวิธีหนึ่งที่ตั้งใจจะให้ดีที่สุดคือเคสทั้งหมด หากมีวิธีอื่นอยู่พวกเขาจะไม่ถูกเพิ่มเป็นทางเลือกที่เท่าเทียมกัน (เช่นifและunless) แต่เพียงแสดงผลงานภายใน ช้า แต่อย่างต่อเนื่องทางเลือกดังกล่าวล้าสมัย (ไม่กำจัด!) โดยการเพิ่มกลไกที่ดีที่สุดที่รู้จักกัน

มัณฑนากรตัดการเรียกใช้ฟังก์ชัน AOP ก่อนที่ 2.6 คุณต้องใช้__metaclass__สมาชิกมายากลที่จะประกาศ metaclass ระดับของ; ตอนนี้คุณสามารถใช้ไวยากรณ์มัณฑนากรเดียวกันสำหรับสิ่งนี้ได้เช่นกัน ก่อนหน้า 3.0 คุณมีสตริงสองประเภทคือไบต์ที่มุ่งเน้นและ Unicode ซึ่งคุณสามารถผสมโดยไม่ได้ตั้งใจ ตอนนี้คุณมี Unicode เดียวstrและไบนารีโปร่งใสbytesซึ่งคุณไม่สามารถผสมได้โดยไม่ได้ตั้งใจ


3
เช่นเดียวกับบันทึกอย่าลืม"""ความคิดเห็น (เอกสาร) เหล่านี้ครอบคลุมหลายบรรทัด
asthasr

8
ตัวอักษรที่ยกมาสามตัวเป็นเพียงสตริงเช่นเดียวกับที่ยกมาเดี่ยว แต่สามารถขยายหลายบรรทัดโดยไม่ต้องหลบหนีปลายสาย สตริงตัวอักษรที่ถูกต้องหลังจากการประกาศนั้นถือว่าเป็นสตริง doc และไม่ใช่ความคิดเห็นซึ่งโดยทั่วไปจะสามารถเข้าถึงได้เป็น__doc__แอตทริบิวต์ แต่สตริงเป็นพื้นที่ที่ Python ให้ 'วิธีที่ถูกต้อง' หลายอย่าง: ใช้คำพูดเดี่ยวสองหรือสามคำโดยนัยเข้าร่วมตัวอักษรที่อยู่ติดกันใช้rสำหรับตัวอักษรดิบ ฯลฯ
9000

1
ผมคิดว่า @ คิดเห็น syrion ถูกเรื่อง "คุณมักจะสามารถตัดสินใจได้ว่าโฆษณาที่ได้แสดงความคิดเห็นหรือไม่โดยเพียงแค่มองมัน" ซึ่งไม่เป็นความจริงเพราะ """ สตริง.
blubb

2
"สิ่งนี้ทำให้การวิเคราะห์แหล่ง Python ง่ายขึ้นสำหรับมนุษย์" <- เป็นอัตนัย
jiggy

การประกาศ metaclass เปลี่ยนไปใน 2.7 อย่างไร ไม่พบรูปแบบการตกแต่งภายในใน 2.7 เอกสารสำหรับ metaclasses
Nick T

10

อีกสองตัวอย่างคือ:
len()เป็นฟังก์ชั่นแทนวิธีการที่มีอยู่ในทุกลำดับ; ถ้าคุณเปรียบเทียบกับ Java คุณมี.length, .size(), .getSize()และวิธีการอื่น ๆ เพื่อหาจำนวนขององค์ประกอบในลำดับที่

อีกตัวอย่างหนึ่งคือความจริงที่ว่า.join()เป็นstringวิธีการไม่ใช่วิธีการที่มีอยู่ในทุกลำดับ คุณไม่จำเป็นต้องทราบว่าพารามิเตอร์เข้าร่วมเป็นรายการชุดความเข้าใจหรืออะไรก็ตามมันจะทำงานได้หรือไม่


8

ใน C มีหลายวิธีที่เป็นไปได้ในการเพิ่มค่าของตัวแปรโดยหนึ่ง:

i++     // Post-increment, returns the number before the increment
++i     // Pre-increment, returns the number after the increment
i += 1 

แต่ละจบลงด้วยการเพิ่มมูลค่าของiโดย1แต่แต่ละคนก็แตกต่างกันเล็กน้อย

ใน Python มีเพียงทางเดียวเท่านั้น เพียงเพิ่ม

i += 1

และในขณะที่มีวิธีการที่ถูกต้องมากกว่าหนึ่งวิธีในการทำสิ่งนี้ (เช่นi = i + 1) คุณกำลังทำสิ่งเดียวกันโดยมีผลข้างเคียงที่เหมือนกัน


1
ฉันไม่ใช่ผู้เชี่ยวชาญ แต่ตัวอย่างนั้นดูเหมือนจะละเมิดแนวคิด "ทางเดียวเท่านั้นที่จะทำได้" เรามีสองวิธีที่จะทำ แต่สิ่งใดที่ชัดเจนกว่ากัน ในสายตาของฉันตัวอย่างแรกนั้นชัดเจนมากขึ้นในขณะที่สองนั้นสั้นกว่าเล็กน้อย แต่ไม่สามารถอ่านหรือเห็นได้ชัดเจนสำหรับโปรแกรมเมอร์ผู้ใดที่ก้าวหน้าเกินกว่าพื้นฐาน ขอบคุณสำหรับคำตอบ - มันเป็นอาหารที่ดีสำหรับความคิด
Charles Roper

@Peter (และ @Charles): จริงๆแล้วi = i + 1เป็นการมอบหมายไม่ใช่การเพิ่ม i += 1ในหลามเพิ่มขึ้นเป็น ในภาษา C-สไตล์ที่คุณสามารถเขียนi++, และ++i i += 1
Josh K

2
ไม่แน่ใจเกี่ยวกับความคิดเห็น "ความสับสนมาก" ของคุณตัวอย่าง C ทั้งสามของคุณ (คุณพลาดi += 1BTW) ให้ผลลัพธ์เหมือนกันทุกประการ ครั้งเดียวที่ฉันเห็นผู้คนสับสนคือเมื่อพวกเขาเพิ่มตัวแปรก่อนหรือหลังการเพิ่มขึ้นซึ่งเป็นส่วนหนึ่งของการแสดงออกที่ใหญ่กว่าและนั่นมักจะแก้ไขได้อย่างรวดเร็วโดยการอ่านส่วนที่เหมาะสมของการอ้างอิงภาษา โดยส่วนตัวฉันได้เลือกความจริงที่ว่าคุณสามารถอ้างถึงตัวละครที่ห้าของสตริงโดยทั้งสองstr[4]หรือ*(str+4)แต่อาจจะง่ายเกินไป ...
TMN

2
@TMN: บางกรณีเช่นmax(i++, ++i)ไม่สามารถแก้ไขได้อย่างรวดเร็ว C มีกรณีพฤติกรรม "ไม่ได้กำหนด" และ "ขึ้นอยู่กับการใช้งาน" เป็นจำนวนมากทุกกรณีมีเหตุผลที่ดี - แต่แต่ละกรณีสามารถสร้างข้อผิดพลาดได้
9000

@TMN: ไม่ต้องพูดถึง 4 [str] (ใช้ได้ใน C อาจไม่ถูกต้องใน C ++)
Vatine

6

ความเป็นไปได้อื่นอาจเป็นรายการความเข้าใจ ใน Python คุณสามารถทำสิ่งนี้:

new_list = []
    for item in list_of_items:
       if item < 10:
           new_list.append(item)

แต่วิธี "ชัดเจน" (ถ้าคุณเป็นชาวดัตช์หรือคุ้นเคยกับ Python มากกว่า) ในการทำเช่นนี้จะต้องมีรายการความเข้าใจ:

new_list = [item for item in list_of_items if item < 10]

สั้นกว่ารายการใหม่ถูกสร้างขึ้นในขั้นตอนเดียวทำงานได้เร็วกว่าที่ฉันเชื่อและเป็นสิ่งที่สวยงาม ข้อเสียอย่างหนึ่งอาจเถียงว่ามันรู้สึกชัดเจนน้อยลง แต่ฉันคิดว่าเมื่อคุณชินกับมันแล้วมันก็ชัดเจน


สำหรับการเยื้องและรหัส: เติมมันด้วย 4 ช่องว่างจากนั้นจะเคารพการเยื้อง
Inca
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.