2 điểm bởi GN⁺ 2025-07-20 | 1 bình luận | Chia sẻ qua WhatsApp
  • fstrings.wtf là một bài kiểm tra trực tuyến nhằm đánh giá mức độ hiểu biết về tính năng f-string của Python
  • Nội dung gồm các câu hỏi kiểm tra nhiều hành vi khác nhau và các trường hợp ngoại lệ của f-string được áp dụng trong phiên bản Python 3.13 mới nhất
  • Người dùng có thể bắt đầu làm bài ngay lập tức mà không cần qua bước chuẩn bị nào
  • Có thể trải nghiệm trước các mẹo hoặc lỗi hoạt động liên quan đến f-string thường gặp trong công việc thực tế

1 bình luận

 
GN⁺ 2025-07-20
Ý kiến Hacker News
  • Tính năng nội suy chuỗi cũng giống như suy luận kiểu: một khi đã quen thì sẽ thấy cực kỳ bất tiện khi không có. Có vẻ như càng bổ sung dần thì càng tốt hơn, nhưng đến một lúc nào đó sẽ nhận ra mã trở nên khó đọc. Nói chung trong lĩnh vực CS, người ta luôn muốn thêm nhiều tính năng hơn, nhưng đôi khi điều đó lại khó về mặt toán học. Ở đây cần tránh cả hai cực: không có gì và có quá nhiều. Python và C# chọn cách để tùy gu người dùng. Bạn có thể viết chuỗi nội suy phức tạp dài 16 trang, nhưng đồng nghiệp có thể ghét nó và nó cũng có thể trượt trong code review. C++ 23 thì theo phong cách cấm nội suy ngay từ đầu. Rust chọn một lựa chọn cực kỳ hạn chế là chỉ cho phép nội suy identifier, điều này với người thì thấy thiếu, với người khác lại thấy đã quá nhiều

    • Tôi nghĩ đội Java String Template cũng đã trải qua quá trình tương tự. Nhìn bề ngoài thì đó là một hệ thống khá ngầu, nhưng khi thực sự dùng thử thì họ cảm thấy hướng đi đó là bất khả thi nên cuối cùng đã loại bỏ hoàn toàn. Xét đến nhu cầu với tính năng nội suy và cả công sức đã bỏ ra đến nay, đây là một quyết định khá thú vị. Cuối cùng họ đánh giá là không thể quay đầu nữa nên quay lại vạch xuất phát

    • Tính thuần khiết và tính thực dụng xung đột với nhau, và mỗi ngôn ngữ lại tìm một điểm cân bằng khác nhau. Không có đáp án cố định nên các lập trình viên cứ lặp đi lặp lại rằng mình có tiêu chuẩn đúng đắn riêng

    • Mỗi lần cần định dạng số hoặc ngày tháng trong C#, tôi lại phải đi tìm tài liệu trước. Cái mini-language đó dở quá nên tôi chẳng buồn học thuộc

    • Việc kiểm soát nội suy một cách hợp lý mà không cố gắng bao quát mọi ví dụ phức tạp hóa ra không khó. Tôi chưa từng thấy cần phải lồng f-string bên trong f-string, và format specifier duy nhất tôi hay dùng là :02x

    • Tôi hoàn toàn không nghĩ cách nội suy hạn chế của Rust là lời giải. Vì nó chỉ hoạt động trong một số tình huống nhất định nên lúc refactor mã cứ phải để ý liên tục và phát sinh nhiều chỉnh sửa không cần thiết. Ít nhất cũng nên cho phép truy cập field. Ngược lại, trong Python dù có vài trường hợp kỳ quặc như ví dụ, người dùng thực tế chẳng để tâm mà vẫn vui vẻ dùng f-string

  • Gần đây tôi mới biết vài mẹo được giải thích ở fstring.help như canh giữa, tiền tố 0x/0b/0o, hiển thị ASCII, v.v. Tôi cũng quan tâm đến vấn đề f-string lồng nhau, và đến 3.11 thì vẫn làm được nếu chỉ dùng loại dấu ngoặc kép khác nhau. Tôi biết là trong 3.12 nhiều hạn chế đã được dọn dẹp. f-string đúng là tiện, nhưng việc phải thường xuyên chuyển qua lại giữa kiểu % formatting cũ, cách .format(), rồi cách mới với các khác biệt tinh tế lại phiền hơn tưởng tượng, mà cũng thường xuyên gặp những tình huống không tránh được. Tính dễ dùng đã tiến bộ, nhưng việc vẫn phải dùng cách cũ đôi lúc khiến tôi khá tiếc

    • Có thể xác nhận phần này trong tài liệu chính thức về những gì đã được dọn dẹp trong 3.12

    • Thỉnh thoảng tôi thấy đồng nghiệp hoặc AI dùng f-string trong lời gọi logger, trong khi logger vốn được thiết kế là lazy interpolation, nên tôi thấy khó hiểu khi lại bỏ phí tính năng hay như vậy

    • Tôi nghĩ f-string lồng nhau là kiểu vấn đề mang tính mẹo mực. Tôi có biết là sau này có thêm khả năng lồng với cùng kiểu dấu ngoặc kép, nhưng không nhớ là bản nào. Tôi vẫn dùng mẹo f'{f"{}"}', lý do là tôi muốn mã của mình hỗ trợ thêm vài phiên bản Python cũ hơn

  • Tôi mới biết trong f-string có tính năng dùng dấu bằng (=) để in cả biểu thức lẫn giá trị của nó

    • Tôi thực sự nghĩ release note của Python rất đáng đọc. Lúc nào cũng có những điều bất ngờ thú vị. Tính năng dấu bằng được thêm vào từ Python 3.8 liên kết liên quan

    • Tôi thấy tiếc vì một PEP tương tự đã không được chấp nhận cho keyword argument của hàm. Nếu có thể viết foo(bar=) thay vì foo(bar=bar), thì sự khác biệt với trường hợp chỉ đơn giản truyền biến vào cũng sẽ lộ rõ hơn, rất hiệu quả cho việc debug

    • Tôi nghĩ đây là một tính năng gây bất ngờ nhiều hơn là mang lại giá trị tương xứng. Nó có khả năng tạo ra hành vi ngoài dự đoán, nên tôi lo nó có thể trở thành nguồn phát sinh bug. Có lẽ một hàm chuẩn chỉ in ra một phần của locals() sẽ tốt hơn

    • Đây là pattern được dùng cực kỳ thường xuyên cho output debug. Trong C++ tôi hình thành thói quen để một biểu thức trong dấu ngoặc kép, một biểu thức để trần. Nó dễ hiểu hơn và không cần suy nghĩ nhiều nên rất tiện

    • Rất hữu ích khi debug bằng print(f)

  • Khác với URL, tôi nghĩ thực tế gần như không có câu hỏi nào đạt mức WTF. Có vài cái thực sự gây sốc như câu 20, 21

    • Tôi thấy walrus operator quá hữu ích nên tuyệt đối không thể bỏ. Khi xử lý pattern matching và phân nhánh nhiều nhánh, mã trở nên gọn gàng hơn hẳn. Tôi không dùng thường xuyên, nhưng trong đúng tình huống thì hiệu quả rất lớn

    • Cái này không phải do walrus operator mà là do cách hoạt động của python string.format, xem tài liệu liên quan

  • Tôi chưa thực sự dùng Python nghiêm túc từ trước đến sau khi f-string được đưa vào, nhưng tôi đoán đúng gần như toàn bộ quy tắc cú pháp, ngược lại chỉ mắc vài lỗi liên quan đến việc trả về giá trị. Tôi còn nghĩ f-string có lẽ là phần ít WTF nhất trong Python

  • Khi làm một thư viện kiểu f-string cho Lua, tôi đã phải học khá nhiều cú pháp, nhưng f"{...}" và walrus operator thì quả là ngoài dự đoán. Dù vậy nó vẫn còn xa mới đạt mức kỳ quặc như Wat. Có thể xem thư viện liên quan tại đây

    • Thư viện đó trông thật sự rất ngầu
  • Tôi không thấy có gì đặc biệt đáng WTF cả. Phần lớn nội dung ở đây thật ra là về cú pháp mini-language của str.format() hơn là về chính f-string

    • Đúng là có một vài chỗ đủ WTF, nhưng đa phần chỉ là vấn đề bạn có biết cú pháp định dạng chuỗi hay không thôi
  • Có vẻ tính năng đã quá nhiều và vượt qua ngưỡng tới hạn. Một lập trình viên không cần nắm hết mọi thứ, nhưng thực tế là mỗi lần phải dùng lại phải tra tài liệu nên rất kém hiệu quả. Vì dùng hiếm nên lại quên cú pháp, và tự cài đặt cùng tính năng thường nhanh hơn nhiều, lại có lợi ở chỗ đồng nghiệp nhìn vào cũng dễ tùy biến. Left padding à? Chỉ cần hàm 2 dòng là đủ. Thay vì phải bối rối không nhớ cú pháp định dạng là n đứng trước hay < đứng trước, tự làm ad-hoc còn nhanh hơn

    • Mấy thứ như left padding vẫn dùng được cả trong phương thức string.format, và cách này đã có từ Python 2.6 (ra mắt năm 2008), xem tài liệu liên quan. Cá nhân tôi thì cú pháp format lại lưu rất tốt trong đầu nên thấy khá hữu ích. Hơn nữa, formatting còn mở hook để tùy biến

    • Tôi muốn chọn điểm ở giữa. Có các hàm pad_left/pad_right và cho phép chỉ định luôn ký tự đệm bằng keyword argument sẽ là dễ chịu nhất. Vì đây là thứ thỉnh thoảng vẫn cần trong đời thường nên sẽ tốt hơn nếu có trong standard library. Nếu thư viện ngôn ngữ không có mấy thứ này thì về sau mỗi project lại đầy rẫy các bản cài đặt chất lượng kém, giống như JavaScript. Trong project của tôi có lẽ sẽ không cần đến kiểu định dạng Python như ^ hay <>, nhưng trong phần mềm mà output 'monospace' là quan trọng thì đây lại có thể là tính năng cực kỳ thiết yếu

    • Có những lúc trong cùng một codebase, người ta lặp đi lặp lại rất nhiều tính năng kỳ lạ hoặc workaround. Thường là làm một lần rồi copy-paste để tái sử dụng mãi

  • Nếu cú pháp này là của JavaScript thì có lẽ đa số đã than phiền rằng đây là cú pháp thiếu trực quan và đầy tính năng kỳ quặc

    • Theo tôi, điểm mấu chốt thật sự của bài quiz này là Python cũng có nhiều footgun chẳng kém JavaScript. Có lẽ vì bên JS mấy bài post kiểu 'WTF' như thế này xuất hiện thường xuyên

    • Dù bỏ qua các mẹo vặt nhỏ lẻ, tôi vẫn nghĩ JavaScript áp đảo ở ngôi vương của cú pháp thiếu trực quan. Các yếu tố f-string của Python cũng hơi lạ thật, nhưng chỉ lộ ra trong vài tình huống nhất định, còn với JS thì trước cả khi so sánh hai mảng bạn đã phải ngồi chờ cài dependencies rồi

    • Tôi muốn hỏi về template literal của JavaScript. Có vẻ như JS không làm được kiểu như Python: let template = 'hello ${name}';, rồi template.format({ name: 'joe' }) để bơm giá trị động nhiều lần. Vì vậy tôi đã buộc phải tự cài. Tôi cũng đã xem qua tagged template, nhưng việc tái sử dụng chính template đó khá khó. Cảm giác than phiền về cú pháp và các tính năng kỳ quặc của JS thì tôi hoàn toàn đồng cảm

    • Nếu là Perl thì có khi lại toàn lời khen

  • Tôi tham khảo pyformat.info(liên kết); dù không cực kỳ chi tiết, nó vẫn tổng hợp hầu hết các ví dụ hợp lý cần dùng