2 คะแนน โดย GN⁺ 2025-07-20 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • fstrings.wtf เป็นควิซออนไลน์สำหรับตรวจสอบความเข้าใจเกี่ยวกับ ความสามารถของ f-string ใน Python
  • ประกอบด้วยคำถามที่ทดสอบ พฤติกรรมที่หลากหลายของ f-string และข้อยกเว้นต่าง ๆ ที่ใช้กับ Python 3.13 เวอร์ชันล่าสุด
  • ผู้ใช้สามารถ เริ่มทำควิซได้ทันที โดยไม่ต้องผ่านขั้นตอนเพิ่มเติม
  • ช่วยให้ได้ลองเจอกับทริกหรือพฤติกรรมผิดปกติที่เกี่ยวกับ f-string ซึ่งมักพบในงานจริงล่วงหน้า

1 ความคิดเห็น

 
GN⁺ 2025-07-20
ความคิดเห็นบน Hacker News
  • ฟีเจอร์ string interpolation ก็เหมือน type inference คือพอชินแล้ว พอไม่มีจะรู้สึกอึดอัดมาก ดูเหมือนว่ายิ่งค่อย ๆ เพิ่มความสามารถเข้าไปก็ยิ่งดีขึ้นเรื่อย ๆ แต่พอถึงจุดหนึ่งก็จะตระหนักว่าโค้ดมันกลายเป็นอะไรที่อ่านยากมาก โดยทั่วไปในสาย CS มักอยากเพิ่มความสามารถเข้าไปเรื่อย ๆ แต่ในเชิงคณิตศาสตร์บางทีก็ทำได้ยาก ตรงนี้ต้องเลี่ยงทั้งการไม่มีเลยและการมีมากเกินไป Python กับ C# เลือกแนวทางให้ผู้ใช้ตัดสินตามรสนิยม จะเขียน interpolation string ซับซ้อนยาว 16 หน้าเลยก็ได้ แต่เพื่อนร่วมงานอาจไม่ชอบและอาจไม่ผ่าน code review ก็ได้ ส่วน C++ 23 เป็นแนวที่ห้าม interpolation ตั้งแต่แรกเลย ขณะที่ Rust เลือกทางเลือกที่จำกัดมากคืออนุญาตให้ interpolate ได้แค่ identifier ซึ่งสำหรับบางคนอาจน้อยเกินไป และสำหรับบางคนก็อาจมากเกินไป

    • คิดว่าทีม Java String Template ก็คงผ่านกระบวนการคล้ายกัน ตอนมองจากภายนอกมันดูเป็นระบบที่เท่มาก แต่พอลองใช้จริงกลับรู้สึกว่าทิศทางนั้นเป็นไปไม่ได้ สุดท้ายเลยถอดออกทั้งหมด เมื่อนึกถึงทั้งความต้องการที่มีต่อฟีเจอร์ interpolation และความพยายามที่ลงไปก่อนหน้านี้ นี่ถือเป็นการตัดสินใจที่น่าสนใจทีเดียว สุดท้ายพวกเขาคงมองว่าไม่สามารถย้อนกลับได้ง่าย เลยตัดสินใจกลับไปเริ่มต้นใหม่

    • ความบริสุทธิ์กับความใช้งานได้จริงเป็นสิ่งที่ขัดแย้งกัน และแต่ละภาษาก็หาจุดสมดุลต่างกันไป ไม่มีคำตอบตายตัว นักพัฒนาเลยมักยืนยันซ้ำ ๆ ว่าเกณฑ์ที่ถูกต้องนั้นเป็นของตัวเอง

    • ทุกครั้งที่ต้อง format ตัวเลขหรือวันที่ใน C# ผมต้องไปเปิดเอกสารก่อนเสมอ mini-language นั้นแย่มากจนไม่คิดจะพยายามจำมันเลย

    • การควบคุม interpolation ให้พอดีโดยไม่ต้องไปไล่ให้ตรงกับตัวอย่างซับซ้อน ๆ ไม่ใช่เรื่องยาก ผมไม่เคยรู้สึกจำเป็นต้องซ้อน f-string ไว้ใน f-string และ format specifier ที่ใช้บ่อยจริง ๆ ก็มีแค่ :02x

    • ผมไม่คิดว่าวิธี interpolation แบบจำกัดของ Rust จะเป็นคำตอบเลย มันใช้ได้แค่บางสถานการณ์ ทำให้เวลาทำ refactor ต้องคอยระวังและต้องเกลางานเพิ่มโดยไม่จำเป็น อย่างน้อยก็น่าจะอนุญาตการเข้าถึง field ได้บ้าง ตรงกันข้ามกับ Python ที่ถึงจะมีกรณีแปลก ๆ แบบในตัวอย่าง แต่ผู้ใช้จริงก็ไม่ค่อยสนใจและใช้ fstring กันอย่างสบายใจ

  • เพิ่งได้รู้ทิปบางอย่างที่อธิบายใน fstring.help เช่น การจัดกึ่งกลาง, prefix แบบ 0x/0b/0o, การแสดงผลแบบ ASCII เป็นต้น ช่วงหลังยังสนใจประเด็น nested f-string ด้วย และจำได้ว่าจนถึง 3.11 มันยังทำได้ถ้าใช้เครื่องหมายคำพูดคนละแบบ ส่วนใน 3.12 เข้าใจว่าข้อจำกัดหลายอย่างถูกจัดระเบียบใหม่แล้ว f-string ทำให้สะดวกขึ้นก็จริง แต่การที่ต้องสลับใช้ทั้งการ format แบบเก่า %, แบบ .format() และแบบใหม่ที่มีความต่างเล็ก ๆ น้อย ๆ อยู่ตลอด กลับยุ่งยากกว่าที่คิด และมีหลายสถานการณ์ที่เลี่ยงไม่ได้ แม้ usability จะดีขึ้น แต่ก็ยังน่าเสียดายเวลาที่ต้องกลับไปใช้วิธีเก่า

    • ตรวจสอบเรื่องนี้ได้จากเอกสารทางการ ที่อธิบายสิ่งที่จัดระเบียบใหม่ใน 3.12

    • บางครั้งเห็นเพื่อนร่วมงานหรือ AI ใช้ f-string ในการเรียก logger ทั้งที่ logger ออกแบบมาให้ทำ lazy interpolation โดยตั้งใจ เลยสงสัยว่าทำไมถึงยอมทิ้งความสามารถดี ๆ นั้นไป

    • ผมมองว่า nested f-string เป็นปัญหาแนวลูกเล่น รู้ว่ามีการเพิ่มให้ซ้อนด้วยเครื่องหมายคำพูดสไตล์เดียวกันได้ แต่ไม่รู้ว่าอยู่ในเวอร์ชันไหน ทุกวันนี้ยังใช้ทริก f'{f"{}"}' อยู่ เหตุผลคืออยากให้โค้ดของผมรองรับ Python เวอร์ชันเก่ากว่านี้ได้อีกหน่อย

  • เพิ่งรู้ว่าใน f-string มีฟีเจอร์ใช้เครื่องหมายเท่ากับ(=) เพื่อแสดงทั้ง expression และค่าของมันพร้อมกันได้

    • คิดว่า release note ของ Python เป็นสิ่งที่คุ้มค่าแก่การอ่านจริง ๆ มักมีเรื่องน่าประหลาดใจในทางที่ดีเสมอ ฟีเจอร์เครื่องหมายเท่ากับถูกเพิ่มใน Python 3.8 ลิงก์ที่เกี่ยวข้อง

    • เสียดายที่ไม่มี PEP ลักษณะใกล้เคียงกันสำหรับ keyword argument ของฟังก์ชัน ถ้าเขียนเป็น foo(bar=) แทน foo(bar=bar) ได้ มันก็คงช่วยให้เห็นความต่างจากกรณีส่งอาร์กิวเมนต์ตรง ๆ ได้ง่ายขึ้น และมีประโยชน์ต่อการดีบักด้วย

    • ผมคิดว่ามันเป็นฟีเจอร์ที่สร้างความแปลกใจได้มากกว่าคุณค่าที่ให้จริง มีโอกาสจะเกิดพฤติกรรมไม่คาดคิดสูง เลยกังวลว่าจะกลายเป็นแหล่งของบั๊ก ฟังก์ชันมาตรฐานที่พิมพ์เฉพาะบางส่วนของ locals() ออกมาได้น่าจะดีกว่า

    • นี่เป็นแพตเทิร์นที่ถูกใช้บ่อยมากในการพิมพ์ดีบัก ใน C++ ผมถึงกับติดนิสัยเขียน expression หนึ่งไว้ในเครื่องหมายคำพูด อีกอันเขียนตรง ๆ ไปเลย เพราะมันทำให้อ่านง่ายและไม่ต้องคิดมาก

    • มีประโยชน์มากเวลาทำดีบักด้วย print(f)

  • เมื่อเทียบกับ URL แล้ว ผมคิดว่าแทบไม่มีคำถามไหนถึงระดับ WTF จริง ๆ มีแค่บางข้ออย่างข้อ 20, 21 ที่น่าตกใจจริง

    • สำหรับผม walrus operator มีประโยชน์มากจนยอมปล่อยไปไม่ได้เลย เวลาทำ pattern matching และจัดการหลายกรณี โค้ดมันสะอาดขึ้นมาก แม้ไม่ได้ใช้บ่อย แต่พออยู่ในสถานการณ์ที่เหมาะก็มีผลมาก

    • อันนี้ไม่ใช่เพราะ walrus operator แต่เป็นพฤติกรรมของ python string.format ดูเอกสารที่เกี่ยวข้อง

  • ผมไม่ได้ใช้ Python จริงจังมากนักทั้งก่อนและหลังมี f-string แต่ก็เดากฎไวยากรณ์ได้เกือบหมด และกลับพลาดแค่เรื่องการคืนค่าอยู่ไม่กี่ครั้ง เลยรู้สึกว่า f-string อาจเป็นส่วนที่ WTF น้อยที่สุดของ Python ก็ได้

  • ตอนทำไลบรารีคล้าย f-string สำหรับ Lua ผมได้เรียนรู้ไวยากรณ์เยอะพอสมควร แต่ f"{...}" กับ walrus operator นี่เหนือความคาดหมาย ถึงอย่างนั้นก็ยังห่างไกลจากความประหลาดระดับ Wat ถ้าสนใจไลบรารีที่เกี่ยวข้องดูได้ที่นี่

    • ไลบรารีนั้นดูเจ๋งมากจริง ๆ
  • ผมไม่คิดว่ามีอะไร WTF เป็นพิเศษ เนื้อหาส่วนมากเกี่ยวกับไวยากรณ์ mini-language ของ str.format() มากกว่าตัว f-string เอง

    • ก็มีบางอย่างที่ชวน WTF อยู่บ้าง แต่ส่วนใหญ่เป็นเรื่องว่าคุณรู้ไวยากรณ์การ format string หรือเปล่า
  • ฟีเจอร์มันเยอะเกินไปจนเหมือนข้ามจุดวิกฤตไปแล้ว นักพัฒนาคนเดียวไม่จำเป็นต้องรู้ทุกอย่าง และในทางปฏิบัติพอถึงเวลาต้องใช้ก็มักต้องกลับไปเปิดเอกสารอยู่ดี ทำให้ไม่มีประสิทธิภาพ พอใช้ไม่บ่อยก็ลืมไวยากรณ์ และการเขียนฟังก์ชันเองสำหรับความต้องการนั้น ๆ มักเร็วกว่ามาก แถมเพื่อนร่วมงานก็ปรับแต่งต่อได้ง่ายกว่า padding ด้านซ้ายเหรอ? ใช้ฟังก์ชัน 2 บรรทัดก็พอ แทนที่จะมานั่งงงว่าไวยากรณ์ format ต้องใส่ n ก่อนหรือ < ก่อน แบบทำ ad-hoc เองกลับเร็วกว่า

    • ของอย่าง left padding ใช้ได้ในเมธอด string.format เช่นกัน และมีมาตั้งแต่ Python 2.6 (ออกปี 2008) ดูเอกสารที่เกี่ยวข้อง ส่วนตัวผมกลับจำไวยากรณ์ format ได้ค่อนข้างติดหัวและใช้ประโยชน์จากมันได้ดี นอกจากนี้ระบบ formatting ยังเปิดช่องให้ hook เพื่อทำ customization ได้ด้วย

    • ผมอยากเลือกจุดกึ่งกลางมากกว่า ถ้ามีฟังก์ชัน pad_left/pad_right ที่ให้ระบุอักขระ padding เป็น keyword argument ได้โดยตรงก็น่าจะใช้งานสบายที่สุด ของแบบนี้จำเป็นในชีวิตประจำวันพอสมควร เลยอยากให้มีใน standard library ถ้าภาษาไม่มีของพวกนี้ สุดท้ายแต่ละโปรเจกต์ก็มักจะเต็มไปด้วย implementation คุณภาพต่ำของตัวเอง เหมือน JavaScript ในโปรเจกต์ของผมคงไม่ถึงกับต้องใช้ formatting แบบ Python อย่าง ^ หรือ <> แต่ในซอฟต์แวร์ที่ให้ความสำคัญกับการแสดงผลแบบ monospaced มันอาจเป็นฟีเจอร์ที่สำคัญมากจริง ๆ

    • บางทีใน codebase เดียวกันก็มีการใช้ฟีเจอร์ประหลาดหรือวิธีลัดซ้ำ ๆ เยอะมาก มักเป็นกรณีที่ทำขึ้นครั้งหนึ่งแล้วก็ copy-paste ใช้ต่อไปเรื่อย ๆ

  • ถ้า syntax แบบนี้เป็นของ JavaScript คนส่วนใหญ่น่าจะบ่นกันว่าไม่ intuitive และมีฟีเจอร์ประหลาดเต็มไปหมด

    • ผมว่าประเด็นจริงของควิซนี้คือ Python เองก็มี footgun เยอะไม่แพ้ JavaScript อาจเพราะในฝั่ง JS มีโพสต์แนว 'WTF' แบบนี้บ่อยก็ได้

    • ถึงจะตัดลูกเล่นเล็ก ๆ น้อย ๆ ออกไป ผมก็ยังคิดว่า JavaScript ครองแชมป์เรื่องไวยากรณ์ที่ไม่ intuitive แบบขาดลอย องค์ประกอบของ f-string ใน Python เองก็แปลกอยู่เหมือนกัน แต่จะโผล่มาเฉพาะบางสถานการณ์ ขณะที่ใน JS คุณยังไม่ทันจะเปรียบเทียบ array สองอัน ก็ต้องนั่งรอติดตั้ง dependency ก่อนแล้ว

    • ผมอยากถามเรื่อง JavaScript template literal หน่อย ดูเหมือนว่าใน JS จะทำแบบ Python อย่าง let template = 'hello ${name}'; แล้วค่อย template.format({ name: 'joe' }) เพื่อเติมค่าหลายครั้งแบบไดนามิกไม่ได้ สุดท้ายเลยต้องทำเอง เคยลองดู tagged template อะไรพวกนั้นแล้ว แต่ก็ยังรู้สึกว่ายากที่จะ reuse ตัว template เอง เรื่องที่คนบ่นว่า JS มี syntax หรือฟีเจอร์ประหลาดเยอะ ผมเข้าใจได้เต็มที่

    • ถ้าเป็น Perl แทน คงได้รับคำชมแทนที่จะโดนบ่น

  • ผมอ้างอิง pyformat.info(ลิงก์) อยู่ มันอาจไม่ได้ละเอียดสุดขีด แต่ก็รวบรวมตัวอย่างที่สมเหตุสมผลไว้แทบทั้งหมด