งูต้นฉบับกำลังเทลูกปัดตัวเลขจากถ้วยสามแบบลงเครื่องชั่งเศษส่วนโดยมีป้ายข้อความถูกกันไว้นอกโต๊ะ

Python Fraction.from_number: รับเฉพาะตัวเลขโดยไม่เผลอ parse ข้อความ

พี่โชว์Engineering

Fraction(value) รับได้ทั้งตัวเลขและ string ซึ่งสะดวกแต่ boundary บางจุดต้องการยืนยันว่า caller ส่ง numeric object จริงครับ Python 3.14 เพิ่ม Fraction.from_number สำหรับ numbers.Rational, float, Decimal และ object ที่มี as_integer_ratio() โดยไม่รับข้อความ

WHY: ช่องรับเหรียญไม่ควรกลายเป็นช่องกรอกคำสั่ง

เหมือนเครื่องที่รับเหรียญหลายชนิดแต่ไม่รับกระดาษเขียนจำนวน แยก parsing จาก calculation ทำให้ validation อ่านง่าย: ชั้น API แปลงข้อความภายใต้นโยบาย locale/format ก่อน แล้วชั้นคำนวณรับเพียงค่าตัวเลข

from decimal import Decimal
from fractions import Fraction
import unittest


class FractionFromNumberTests(unittest.TestCase):
    def test_supported_numeric_inputs(self):
        self.assertEqual(Fraction.from_number(3), Fraction(3, 1))
        self.assertEqual(Fraction.from_number(Decimal("0.25")), Fraction(1, 4))
        self.assertEqual(
            Fraction.from_number(0.5),
            Fraction(1, 2),
        )

    def test_text_is_not_a_number_boundary(self):
        with self.assertRaises(TypeError):
            Fraction.from_number("1/4")

    def test_binary_float_is_preserved_exactly(self):
        value = Fraction.from_number(0.1)
        self.assertNotEqual(value, Fraction(1, 10))
        self.assertEqual(value.limit_denominator(10), Fraction(1, 10))


if __name__ == "__main__":
    unittest.main()

Exact ไม่ได้แปลว่าตรงกับเลขที่มนุษย์พิมพ์

from_number(0.1) เก็บค่าของ binary float ที่มีอยู่จริง จึงได้เศษส่วนยาว ไม่ใช่ 1/10 หาก input มาจากเงินหรือข้อความทศนิยม ใช้ Decimal จาก string ที่ validate แล้ว หรือ parse Fraction ภายใต้ grammar ที่กำหนด อย่าแปลงผ่าน float โดยไม่ตั้งใจ

limit_denominator เป็นการประมาณ ต้องเลือก denominator สูงสุดตามโดเมน เช่น หน่วยวัดหรือเฟรมเรต ไม่ใช้เพื่อ “ซ่อม” ค่าเงินแบบเดา ๆ

Recap

  • ใช้ from_number เมื่อ API ต้องรับ numeric object เท่านั้น
  • แยก text parsing ออกจาก calculation
  • จำว่า float ถูกแปลงแบบ exact ตาม binary value
  • ใช้ Decimal หรือ grammar เฉพาะโดเมนเมื่อรับข้อความทศนิยม