งูต้นฉบับกดกระดิ่งสามใบให้ปล่อยผลลัพธ์จาก callable ตามลำดับบนฉากมิ้นต์

Python operator.call: ส่งฟังก์ชันเข้า pipeline แบบไม่ต้องห่อ lambda

พี่โชว์Engineering

บาง pipeline เก็บ “งานที่จะเรียกทีหลัง” เป็นรายการ callable แล้วต้องแปลงทุกงานเป็นผลลัพธ์ เรามักเขียน map(lambda fn: fn(), jobs) ทั้งที่ lambda ไม่ได้เพิ่มความหมาย operator.call เป็นฟังก์ชันที่รับ callable แล้วเรียกด้วย arguments ที่ตามมา จึงใช้กับ map หรือ higher-order API ได้ตรง ๆ

from __future__ import annotations

from operator import call
import unittest


def collect(jobs: list[callable]) -> list[str]:
    return list(map(call, jobs))


class OperatorCallTests(unittest.TestCase):
    def test_calls_each_zero_argument_job(self):
        jobs = [lambda: "health", lambda: "metrics", lambda: "ready"]
        self.assertEqual(collect(jobs), ["health", "metrics", "ready"])

    def test_arguments_can_be_passed_directly(self):
        self.assertEqual(call(pow, 2, 5), 32)


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

มองมันเหมือนบัตรคำสั่ง “กดปุ่มนี้” ที่ส่งเป็นวัตถุได้ ไม่ต้องสร้างซอง lambda ใหม่ทุกใบ แต่ความสั้นไม่ควรชนะความอ่านง่าย: loop ปกติดีกว่าเมื่อแต่ละงานต้องมี timeout, logging, error policy หรือ argument ต่างกัน

callable ยังอาจมี side effect หรือโยน exception และ map ประเมินแบบ lazy งานจะยังไม่รันจนมีคน consume iterator ตัวอย่างใช้ list เพื่อทำให้จังหวะรันชัด หากต้องการหยุด/ทำต่อเมื่อ error ต้องเขียน control flow ให้เห็นแทนการซ่อนใน pipeline

Recap

  • ใช้แทน lambda fn: fn() ใน pipeline ที่เรียบง่าย
  • จำว่า map lazy จนกว่าจะถูก consume
  • ใช้ loop เมื่อแต่ละงานมี policy ต่างกัน
  • อย่าเรียก callable ที่มาจาก input ที่ไม่เชื่อถือ