เชี่ยวชาญการใช้ Type Hints ใน Python: คู่มือครบวงจรสำหรับการกำหนดประเภทของอกิวเมนต์

目次

1. บทนำ

Python เป็นภาษาการเขียนโปรแกรมที่ได้รับการสนับสนุนจากผู้เริ่มต้นจนถึงผู้เชี่ยวชาญเนื่องจากความยืดหยุ่นและความง่ายในการใช้งาน อย่างไรก็ตาม ลักษณะ “dynamic typing” ของ Python อาจส่งผลกระทบต่อความสามารถในการอ่านและบำรุงรักษาโปรแกรมได้บ้าง เพื่อแก้ไขปัญหานี้ “type hints” ได้ถูกนำเสนอใน Python 3.5 และเวอร์ชันต่อมา

ด้วยการใช้ type hints เหล่านี้ สามารถปรับปรุงความสามารถในการอ่านโค้ดและคุณภาพ รวมถึงเพิ่มประสิทธิภาพในการพัฒนา ในบทความนี้ เราจะอธิบายตั้งแต่พื้นฐานไปจนถึงการใช้งานจริงของ “การระบุประเภทอาร์กิวเมนต์” โดยใช้ “type hints” ของ Python

ลักษณะของ Dynamic Typing ใน Python

ลักษณะหนึ่งของ Python คือ “dynamic typing” ซึ่งโค้ดทำงานโดยไม่ต้องระบุประเภทตัวแปรหรือฟังก์ชันอย่างชัดเจน ตัวอย่างเช่น โค้ดต่อไปนี้ทำงานได้โดยไม่มีปัญหาใน Python:

def add(a, b):
    return a + b

result = add(1, 2)  # Works normally

ความยืดหยุ่นนี้ให้ข้อดีในการสร้างต้นแบบและพัฒนาอย่างรวดเร็ว แต่ก็อาจนำไปสู่ปัญหาต่อไปนี้:

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

พื้นหลังในการนำเสนอ Type Hints

Type hints ถูกนำเสนอเพื่อแก้ไขปัญหาเหล่านี้และให้กลไกในการเพิ่มข้อมูลประเภทลงในโค้ด ผลลัพธ์ที่ได้คือประโยชน์ต่อไปนี้:

  • ปรับปรุงความสามารถในการอ่าน : โดยการทำให้ข้อมูลประเภทชัดเจน บทบาทของฟังก์ชันและตัวแปรจะเข้าใจง่ายขึ้น
  • การใช้เครื่องมือวิเคราะห์แบบคงที่ : เครื่องมือเช่น mypy สามารถตรวจพบข้อผิดพลาดประเภทก่อนการรัน
  • เพิ่มประสิทธิภาพการพัฒนา : การเติมโค้ดอัตโนมัติของ IDE ได้รับการปรับปรุง ทำให้เขียนโค้ดได้มีประสิทธิภาพมากขึ้น

ในบทความนี้ เราจะมุ่งเน้นที่วิธีการระบุประเภทอาร์กิวเมนต์โดยใช้ type hints ใน Python โดยอธิบายด้วยตัวอย่างที่เป็นรูปธรรม ในส่วนถัดไป เราจะเจาะลึกถึง “Type hints คืออะไร?”

Ad

2. Type Hints คืออะไร?

ใน Python “type hints” ให้กลไกในการอธิบายประเภทของฟังก์ชันหรือตัวแปรในโค้ด สิ่งนี้ทำให้เจตนาของโค้ดชัดเจนและช่วยให้เครื่องมือวิเคราะห์แบบคงที่และ IDE สามารถตรวจสอบประเภทได้ Type hints ถูกนำเสนอใน Python 3.5 ผ่าน PEP 484 และคุณสมบัตินี้ได้ถูกขยายในเวอร์ชันต่อมา

บทบาทของ Type Hints

วัตถุประสงค์ของ type hints คือป้องกันข้อผิดพลาดในขณะเขียนโค้ดมากกว่าที่รันไทม์ พวกมันมีประโยชน์โดยเฉพาะในสถานการณ์ต่อไปนี้:

  • ปรับปรุงความสามารถในการอ่านโค้ด : ด้วยการระบุประเภทอย่างชัดเจน บทบาทของฟังก์ชันและตัวแปรจะชัดเจนในทันที
  • อำนวยความสะดวกในการพัฒนาเป็นทีม : ลดความเข้าใจผิดระหว่างนักพัฒนา และการตรวจสอบโค้ดดำเนินไปอย่างราบรื่นมากขึ้น
  • การใช้การวิเคราะห์แบบคงที่ : เครื่องมือเช่น mypy และ PyCharm ตรวจพบข้อผิดพลาดประเภทล่วงหน้า

ตัวอย่างของการเขียน Type Hint

โดยใช้ type hints คุณสามารถระบุประเภทสำหรับอาร์กิวเมนต์และค่าที่ส่งคืนอย่างชัดเจนดังนี้:

Type Hints สำหรับฟังก์ชัน

def greet(name: str) -> str:
    return f"Hello, {name}!"

ในโค้ดนี้ name ถูกระบุอย่างชัดเจนว่าเป็นสตริง (str) และค่าที่ฟังก์ชันส่งคืนก็เป็นสตริงเช่นกัน เมื่อเทียบกับโค้ดที่ไม่มี type hints เจตนาของฟังก์ชันจะชัดเจนขึ้น

Type Hints สำหรับตัวแปร

ตั้งแต่ Python 3.6 เป็นต้นไป คุณสามารถระบุประเภทสำหรับตัวแปรได้

age: int = 25
names: list = ["Alice", "Bob", "Charlie"]

ลักษณะของ Type Hints

Type hints ยังคงเป็นเพียง “hints” และไม่เปลี่ยนลักษณะของ dynamic typing ของ Python ตัวอย่างเช่น ประเภทที่ไม่ตรงกันไม่ก่อให้เกิดข้อผิดพลาดรันไทม์เพียงเพราะ hint

ตัวอย่างของประเภทที่ไม่ตรงกัน

def add_numbers(a: int, b: int) -> int:
    return a + b

result = add_numbers(10, "20")  # No runtime error solely due to hints

โค้ดด้านบนจะเกิดข้อผิดพลาดรันไทม์ แต่เครื่องมือวิเคราะห์แบบคงที่ (เช่น mypy) สามารถตรวจพบข้อผิดพลาดล่วงหน้าได้

ตัวอย่างการตรวจพบด้วยเครื่องมือวิเคราะห์แบบคงที่

โดยใช้ mypy คุณอาจเห็นผลลัพธ์การไม่ตรงกันของประเภทเช่น:

error: Argument 2 to "add_numbers" has incompatible type "str"; expected "int"

ข้อดีและข้อจำกัดของ Type Hints

ข้อดี

  1. ปรับปรุงความสามารถในการอ่านโค้ด
  2. เสริมสร้างการเติมคำอัตโนมัติของ IDE
  3. ความสามารถในการป้องกันบั๊กก่อนเกิดขึ้นด้วยเครื่องมือวิเคราะห์แบบคงที่

ข้อจำกัด

  1. ประเภทไม่ถูกบังคับใช้ในเวลารันไทม์ (ต้องใช้เครื่องมือวิเคราะห์แบบคงที่)
  2. เมื่อต้องการการกำหนดประเภทที่ซับซ้อน ความสามารถในการอ่านอาจลดลง

ข้อพิจารณาเมื่อนำ Type Hints มาใช้

  1. นำ type hints มาใช้อย่างค่อยเป็นค่อยไป ในโครงการที่มีขนาดใหญ่ที่มีอยู่แล้ว แนะนำให้เริ่มต้นโดยการเพิ่ม hints ให้กับฟังก์ชันหรือโมดูลบางส่วน
  2. หลีกเลี่ยงการกำหนดประเภทที่ซับซ้อนเกินไป การกำหนดที่ซับซ้อนเกินไปสามารถทำลายความสามารถในการอ่านได้ ดังนั้นจึงสำคัญที่จะรักษาความกระชับ
  3. ใช้เครื่องมือวิเคราะห์แบบคงที่ เมื่อเพิ่ม type hints การใช้เครื่องมือเช่น mypy หรือ pylint ร่วมกันจะเพิ่มประสิทธิภาพ

Ad
侍エンジニア塾

3. วิธีการกำหนดประเภทพื้นฐาน

โดยการใช้ type hints ของ Python คุณสามารถกำหนดประเภทอย่างชัดเจนสำหรับอาร์กิวเมนต์ของฟังก์ชัน ค่าที่ส่งคืน และตัวแปร ในส่วนนี้ เราจะอธิบายรายละเอียดวิธีการกำหนดประเภทพื้นฐาน

การกำหนดประเภทอาร์กิวเมนต์และค่าที่ส่งคืนสำหรับฟังก์ชัน

โดยการเพิ่ม type hints ให้กับอาร์กิวเมนต์และค่าที่ส่งคืนของฟังก์ชัน คุณสามารถชี้แจงว่าฟังก์ชันยอมรับและส่งคืนประเภทใด

การกำหนดประเภทแบบง่าย

นี่คือตัวอย่างง่ายๆ ที่ประเภทถูกกำหนดสำหรับอาร์กิวเมนต์และค่าที่ส่งคืน

def add(a: int, b: int) -> int:
    return a + b
  • a และ b : รับประเภทจำนวนเต็ม ( int )
  • ค่าที่ส่งคืน: ส่งคืนประเภทจำนวนเต็ม ( int )

กรณีที่มีอาร์กิวเมนต์หลายตัว

Type hints สามารถใช้ได้อย่างง่ายดายแม้จะมีอาร์กิวเมนต์หลายตัว

def greet(name: str, age: int) -> str:
    return f"Hello, {name}! You are {age} years old."
  • ในฟังก์ชันนี้ มันรับประเภทสตริง name และประเภทจำนวนเต็ม age และส่งคืนประเภทสตริง

การกำหนดประเภทสำหรับตัวแปร

ตั้งแต่ Python 3.6 เป็นต้นไป คุณยังสามารถกำหนด type hints สำหรับตัวแปรได้

การกำหนดประเภทตัวแปรพื้นฐาน

name: str = "Alice"
age: int = 30
is_student: bool = True
  • name : ประเภทสตริง
  • age : ประเภทจำนวนเต็ม
  • is_student : ประเภทบูลีน ( bool )

ตัวแปรที่กำหนดโดยไม่มีค่าเริ่มต้น

หากคุณกำหนดเฉพาะประเภทสำหรับตัวแปรโดยไม่กำหนดค่าเริ่มต้น คุณเขียนดังนี้:

height: float  # Type specified but no initial value

ในกรณีนี้ คุณจะต้องกำหนดค่าที่ตรงกับประเภทให้ height ในภายหลัง

การละเว้นและการอนุมานของ Type Hints

โค้ด Python ทำงานได้แม้ไม่มี type hints แต่เมื่อไม่มี hints ความตั้งใจจะยากต่อการสื่อสาร

เมื่อไม่มี Type Hint

def multiply(a, b):
    return a * b

ในฟังก์ชันนี้ ประเภทของ a และ b ไม่ทราบ ดังนั้นนักพัฒนาหรือ IDE จึงไม่สามารถอนุมานประเภทได้อย่างถูกต้อง

เมื่อเพิ่ม Type Hints

def multiply(a: int, b: int) -> int:
    return a * b

โดยการเพิ่ม type hints มันชัดเจนว่าฟังก์ชันนี้ยอมรับอาร์กิวเมนต์ประเภทจำนวนเต็มและส่งคืนค่าประเภทจำนวนเต็ม

การกำหนดประเภทสำหรับประเภทคอลเลกชัน

ใน Python คุณสามารถกำหนด type hints สำหรับประเภทคอลเลกชันเช่นรายการและพจนานุกรมได้เช่นกัน การใช้โมดูล typing เป็นแนวปฏิบัติทั่วไป

การกำหนดประเภทสำหรับ List

Type hint สำหรับ list ใช้ List จากโมดูล typing

from typing import List

numbers: List[int] = [1, 2, 3]

การกำหนดประเภทสำหรับ Dictionary

คุณกำหนดประเภทของคีย์และค่าสำหรับพจนานุกรม

from typing import Dict

student_ages: Dict[str, int] = {"Alice": 20, "Bob": 25}

ตัวอย่างของฟังก์ชันที่ใช้การกำหนดประเภท

นี่คือตัวอย่างฟังก์ชันที่ใช้ประเภทหลายตัว

from typing import List

def calculate_average(grades: List[float]) -> float:
    return sum(grades) / len(grades)

grades = [85.5, 90.0, 78.5]
average = calculate_average(grades)
print(f"Average grade: {average}")

สรุป

โดยการใช้ type hints คุณจะทำให้เจตนาของโค้ดชัดเจนขึ้นและทำให้การป้องกันบั๊กง่ายขึ้น ส่วนนี้อธิบายวิธีการระบุประเภทพื้นฐานต่อไปคือ “4. การระบุประเภทสำหรับโครงสร้างข้อมูลที่ซับซ้อน” ซึ่งเราจะครอบคลุมวิธีขั้นสูงเพิ่มเติม

Ad

4. การระบุประเภทสำหรับโครงสร้างข้อมูลที่ซับซ้อน

ใน Python คุณสามารถระบุประเภทไม่เพียงแต่สำหรับประเภทคอลเลกชันพื้นฐานเช่น list หรือ dictionary เท่านั้น แต่ยังรวมถึง tuple, โครงสร้างที่ซ้อนกัน, ประเภท optional ฯลฯ ในส่วนนี้เราจะอธิบายวิธีการระบุ type hints สำหรับโครงสร้างข้อมูลที่ซับซ้อนเหล่านี้

การระบุประเภทสำหรับ List และ Tuple

การระบุประเภทสำหรับ List

type hint สำหรับ list ใช้ List จากโมดูล typing โดยการระบุประเภทขององค์ประกอบอย่างชัดเจน คุณสามารถกำหนดเนื้อหาใน list ได้อย่างเคร่งครัด

from typing import List

numbers: List[int] = [1, 2, 3, 4]
names: List[str] = ["Alice", "Bob", "Charlie"]
  • numbers : รายการของประเภทจำนวนเต็ม ( int )
  • names : รายการของประเภทสตริง ( str )

การระบุประเภทสำหรับ Tuple

สำหรับ tuple คุณใช้ Tuple เพื่อระบุประเภท โดยการเขียนประเภทของแต่ละองค์ประกอบตามลำดับ คุณสามารถแสดง tuple ที่มีประเภทหลากหลายได้

from typing import Tuple

person: Tuple[str, int] = ("Alice", 25)
  • ในตัวอย่างนี้ person เป็นคู่ของประเภทสตริง (ชื่อ) และประเภทจำนวนเต็ม (อายุ).

การระบุประเภทสำหรับ Dictionary

เมื่อทำการชี้แจงประเภทของคีย์และค่าใน dictionary คุณใช้ Dict.

การระบุประเภทพื้นฐานสำหรับ Dictionary

from typing import Dict

student_scores: Dict[str, float] = {"Alice": 95.5, "Bob": 87.0}
  • ในตัวอย่างนี้ คีย์เป็นประเภทสตริง ( str ) และค่เป็นประเภทเลขศนิยม ( float ).

Dictionary ซ้อนกัน

เมื่อ dictionary มี dictionary อื่นเป็นค่า คุณก็สามารถระบุประเภทอย่างชัดเจนได้เช่นกัน.

from typing import Dict

class_data: Dict[str, Dict[str, int]] = {
    "Class A": {"Alice": 85, "Bob": 90},
    "Class B": {"Charlie": 88, "Dave": 92},
}
  • ในตัวอย่างนี้ คีย์ของ dictionary ภายนอกเป็นชื่อคลาส (ประเภทสตริง) และค่าคือ dictionary ของชื่อนักเรียน (ประเภทสตริง) และคะแนน (ประเภทจำนวนเต็ม).

ประเภท Optional และ Union

ประเภท Optional

Optional ใช้เมื่ออาร์กิวเมนต์หรือค่าที่คืนอาจเป็นประเภทที่ระบุหรือ None.

from typing import Optional

def find_student(name: str) -> Optional[str]:
    students = ["Alice", "Bob", "Charlie"]
    return name if name in students else None
  • ในตัวอย่างนี้ ฟังก์ชัน find_student คืนค่าประเภทสตริง ( str ) หรือ None .

ประเภท Union

โดยใช้ Union คุณสามารถระบุหลายประเภทที่เป็นไปได้.

from typing import Union

def calculate(value: Union[int, float]) -> float:
    return value * 2.0
  • ในตัวอย่างนี้ value สามารถเป็นประเภทจำนวนเต็ม ( int ) หรือประเภทเลขทศนิยม ( float ).

ประเภทกำหนดเองและ Type Alias

Type Alias

โดยการใช้ type alias คุณสามารถแสดงการระบุประเภทที่ซับซ้อนได้อย่างกระชับ.

from typing import List

Vector = List[float]

def add_vectors(v1: Vector, v2: Vector) -> Vector:
    return [x + y for x, y in zip(v1, v2)]
  • Vector ถูกกำหนดเป็นรายการของประเภทเลขทศนิยม ( List[float] ).

การระบุาสกำหนดเองใน Type Hints

คุณสามารถใช้คลาสของคุณเองใน type hints ได้เช่นกัน.

class Student:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

def enroll_student(student: Student) -> str:
    return f"{student.name} has been enrolled."
  • ในตัวอย่างนี้ คลาส Student ถูกใช้เป็น type hint.

การระบุประเภทโดยใช้ Generics

โดยการใช้ Generic คุณสามารถกำหนดประเภทที่นำกลับมาใช้ใหม่ได้.

from typing import TypeVar, Generic, List

T = TypeVar('T')

class Stack(Generic[T]):
    def __init__(self):
        self.items: List[T] = []

    def push(self, item: T) -> None:
        self.items.append(item)

    def pop(self) -> T:
        return self.items.pop()
  • ในตัวอย่างนี้ สแตกสามารถจัดการกับประเภทใดก็ได้ ( T )

สรุ

ในส่วนนี้เราอธิบายวิธีการระบุประเภทสำหรับโครงสร้างข้อมูลที่ซับซ้อนรวมถึงลิสต์, ทูเพิล, ดิกชันนารี, ประเภท Optional, นามแฝงของประเภท, และเจเนอริกส์ การใช้ type hints จะช่วยปรับปรุงความอ่านง่ายและความปลอดภัยของโค้ดอย่างมาก

ในส่วนต่อไป “5. ข้อดีและข้อจำกัดของ Type Hints” เราจะอธิบายรายละเอียดเกี่ยวกับประโยชน์และความท้าทายของการนำ type hints มาใช้ โปรดอ่านต่อ

Ad
年収訴求

5. ข้อดีและข้อจำกัดของ Type Hints

Type hints ของ Python นำมาซึ่งประโยชน์หลายประการต่อการปรับปรุงคุณภาพของโค้ด อย่างไรก็ตามก็มีข้อจำกัดและความท้าทายที่ต้องจัดการ ในส่วนนี้เราจะอธิบายข้อดีและข้อจำกัดของ type hints อย่างละเอียด

ข้อดีของ Type Hints

1. ปรับปรุงความอ่านง่ายของโค้ด

การใช้ type hints ทำให้วัตถุประสงค์ของฟังก์ชันและตัวแปรชัดเจน ส่งผลให้ความอ่านง่ายของโค้ดเพิ่มขึ้นอย่างมีนัยสำคัญ โดยเฉพาะในการพัฒนาทีม นักพัฒนาคนอื่นจะเข้าใจโค้ดได้ง่ายขึ้น
ตัวอย่าง:

def calculate_area(length: float, width: float) -> float:
    return length * width
  • หากไม่มี type hints จะไม่ชัดเจนว่าตัวแปร length หรือ width คาดหวังประเภทอะไร; เมื่อมี hints จะทำให้เห็นชัดเจน

2. ตรวจจับบั๊กล่วงหน้าด้วยเครื่องมือวิเคราะห์แบบสแตติก

เมื่อใช้ type hints เครื่องมือวิเคราะห์แบบสแตติกเช่น mypy สามารถตรวจสอบโค้ดและตรวจจับความไม่ตรงกันของประเภทหรือข้อผิดพลาดก่อนการรัน
ตัวอย่าง: การตรวจจับความไม่ตรงกันของประเภท

def add(a: int, b: int) -> int:
    return a + b

# mypy check results:
# error: Argument 2 to "add" has incompatible type "str"; expected "int"
result = add(10, "20")  # Type error

3. เพิ่มประสิทธิภาพการเติมอัตโนมัติของ IDE

การเขียน type hints ทำให้ IDE (เช่น PyCharm หรือ VSCode) ให้การเติมอัตโนมัติที่เหมาะสม ซึ่งช่วยเพิ่มประสิทธิภาพการพัฒนาและลดผิดพลาด
ตัวอย่าง:

def greet(name: str) -> str:
    return f"Hello, {name}!"

greet("Alice")  # IDE auto-completes argument and return types

4. ทำหน้าที่เป็นเอกสาร

Type hints ทำหน้าที่เป็นเอกสารเบา ๆ ที่ฝังอยู่ในโค้ด นักพัฒนาสามารถเข้าใจพฤติกรรมของฟังก์ชันจากข้อมูลประเภทโดยไม่ต้องอ้างอิงเอกสารภายนอก

ข้อกัดของ Type Hints

1. ประเภทไม่ได้บังคับใช้ในช่วงรันไทม์

Type hints ไม่มีผลต่อการทำงานของ Python ในช่วงรันไทม์; การตรวจสอบความตรงกันของประเภททำได้เฉพาะโดยเครื่องมือวิเคราะห์แบบสแตติกเท่านั้น ข้อผิดพลาดที่เกิดจากความไม่ตรงกันของประเภทในช่วงรันไทม์ไม่สามารถป้องกันได้โดยเพียงใช้ hints
ตัวอย่าง:

def divide(a: int, b: int) -> float:
    return a / b

result = divide("10", 2)  # Runtime error

2. การระบุประเภทอาจทำให้ซับซ้อน

เมื่อทำงานกับโครงสร้างข้อมูลที่ซับซ้อนหรือเจเนอริกส์ การเขียน type hint อาจกลายเป็นเรื่องยุ่งยากและลดความอ่านง่ายของโค้ดลง
ตัวอย่าง: Type hints ที่ซับซ

from typing import Dict, List

data: Dict[str, List[Dict[str, int]]] = {
    "group1": [{"name": 5}, {"name": 10}],
    "group2": [{"name": 15}],
}
  • เมื่อ type มีรายละเอียดมากเกินไป มีความเสี่ยงต่อการทำให้ความอ่านง่ายของโค้ดลดลง

3. มีค่าใช้จ่ายในการเรียนรู้

สำหรับผู้เริ่มต้นที่ไม่คุ้นเคยกับ type hints จะต้องใช้เวลาเรียนรู้ื่องจากมีสัญลักษณ์ใหม่ ๆ นอกจากนี้ต้องทำความเข้าใจการใช้ประเภทต่าง ๆ ในโมดูล typing อีกด้วย

4. ไม่ช่วยเพิ่มความเร็วในการทำงาน

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

สิ่งที่ควรพิจารณาเมื่อแนะนำ Type Hints

  1. แนะนำ Type Hints อย่างค่อยเป็นค่อยไป สำหรับโครงการที่มีอยู่ขนาดใหญ่ ให้เริ่มเพิ่ม hintsกับฟังก์ชันหรือโมดูลบางส่วน
  2. หลีกเลี่ยงการระบุประเภทที่ซับซ้อนเกินไป รักษาความเรียบง่ายโดยใช้การแยกนามธรรมหรือการตั้งนามแฝงประเภทที่เหมาะสม
  3. ใช้เครื่องมือวิเคราะห์แบบสถิต ใช้เครื่องมือเช่น mypy หรือ pylint เพื่อเพิ่มประสิทธิภาพของการแนะนำ type hint

Ad

6. การตรวจสอบประเภทด้วยเครื่องมือวิเคราะห์แบบสถิต

้ว่า type hints ของ Python จะไม่ส่งผลต่อพฤติกรรมขณะรันไทม์ แต่การใช้เครื่องมือวิเคราะห์แบบสถิตช่วยให้ตรวจพบความไม่ตรงกันของประเภทและบั๊กที่อาจเกิดขึ้น ในส่วนนี้เราจะเน้นที่เครื่องมือที่เป็นตัวแทน “mypy” ซึ่งทำงานร่วมกับ type hints ได้ดี และอธิบายวิธีการใช้งาน

เครื่องมือวิเคราะห์แบบสถิตคืออะไร?

เครื่องมือวิเคราะห์แบบสถิตทำการตรวจสอบประเภทและไวยากรณ์โดยไม่ต้องรันโค้ด เมื่อใช้ร่วมกับ type hints สามารถค้นพบข้อผิดพลาดหรือปัญหาต่อไปนี้ล่วงหน้าได้:

  • ความไม่ตรงกันของประเภทในอาร์กิวเมนต์หรือค่าที่คืนกลับ
  • การเรียกใช้ตัวแปรหรือฟังก์ชันที่ไม่ได้กำหนด
  • การระบุการใช้ประเภทที่คลุมเครือ

การติดตั้งและการใช้งานพื้นฐานของ mypy

1. การติดตั้ง mypy

เริ่มต้นโดยติดตั้ง mypy ด้วย pip

pip install mypy

2. การทำการตรวจสอบประเภทด้วย mypy

วิเคราะห์สคริปต์ Python ที่มี type hints ด้วยการวิเคราะห์แบบสถิต รันคำสั่งดังต่อไปนี้:

mypy your_script.py

ตัวอย่าง: หากคุณวิเคราะห์สคริปต์ example.py ที่มีโค้ไปนี้:

def add(a: int, b: int) -> int:
    return a + b

result = add(10, "20")  # Type error

เมื่อคุณรันคำสั่ง คุณจะเห็นข้อผิดพลาดเช่นต่อไปนี้:

error: Argument 2 to "add" has incompatible type "str"; expected "int"

3. ตัวเลือกพื้นฐานสำหรับ mypy

mypy มีตัวเลือกหลายอย่างเพื่อปรับแต่งการตรวจสอบประเภทุ่น

  • --strict : เปิดการตรวจสอบประเภทอย่างเข้มงวด
  • --ignore-missing-imports : เพิกเฉยต่อข้อผิดพลาดการนำเข้า
  • --disallow-untyped-defs : ไม่อนุญาตฟังก์ชันที่ไม่มี type hints

ตัวอย่าง: เพื่อเปิดการตรวจสอบแบบเข้มงวด:

mypy --strict example.py

การใช้การตรวจสอบประเภทใน IDEs

1. การตรวจสอบประเภทใน PyCharm

PyCharm เป็น IDE ที่รวม type hints กับ mypy การใช้ PyCharm มีข้อได้เปรียบดังต่อไปนี้:

  • การตรวจจับข้อผิดพลาดประเภทแบบเรียลไทม์ขณะเขียนโค้ด
  • การเติมข้อความอัตโนมัติตาม type hints

ขั้นตอนการตั้งค่า:

  1. ใน PyCharm: “Settings” → “Languages & Frameworks” → “Python” → “Type Hinting” แล้วเปิดใช้งาน type hints
  2. ตั้งค่า mypy ตามต้องการ
JetBrains

Built for web, data, and AI/ML professionals. Supercharged w…

2. การตรวจสอบประเภทใน Visual Studio Code (VSCode)

VSCode รองรับ type hints ด้วย การติดตั้งส่วนขยาย “Python” คุณสามารถเปิดการตรวจสอบประเภทและการเติมข้อความตาม hints

  • ติดตั้งส่วนขยาย “pylance” เพื่อเปิดการตรวจสอบประเภทแบบเรียลไทม์ตาม type hints

Visual Studio Code redefines AI-powered coding with GitHub C…

ตัวอย่างการใช้งานจริงของเครื่องมือประเภท

ตัวอย่าง 1: การตรวจสอบประเภทของอาร์กิวเมนต์ที่จำเป็น

def greet(name: str) -> str:
    return f"Hello, {name}!"

print(greet(123))  # Type error

ด้วย mypy คุณจะเห็นว่าประเภทของอาร์กิวเมนต์ไม่ตรงกัน

ตัวอย่าง 2: การตรวจสอบประเภทแบบ Optional

from typing import Optional

def find_student(student_id: int) -> Optional[str]:
    students = {1: "Alice", 2: "Bob"}
    return students.get(student_id)

student_name = find_student(3)
print(student_name.upper())  # Type error (NoneType has no upper)

mypy จะพิจารณาความเป็นไปได้ของ None สำหรับประเภท Optional และตรวจพบการขาดการตรวจสอบ None เป็นข้อผิดพลาด

วิธีการดำเนินการตรวจสอบประเภท

1. อัตโนมัติการตรวจสอบประเภท

โดยการรวม mypy เข้าใน pipeline CI/CD ของคุณ คุณสามารถทำการตรวจสอบประเภทอัตโนมัติได้ ซึ่งจะป้องกันโค้ดที่มีปัญหาไม่ให้ถูก deploy ระหว่าง pull request

2. ผสานเข้ากระบวนการพัฒนา

โดยการตั้งกฎดังต่อไปนี้ คุณสามารถใช้ type hints อย่างมีประสิทธิภาพ:

  • เพิ่ม type hints เสมอในโค้ดใหม่
  • วิเคราะห์โครงการทั้งหมดเป็นประจำด้วย mypy
  • หาก type hints มีความคลุมเครือ ให้เพิ่มคอมเมนต์หรือเอกสารเสริม

สรุป

โดยการใช้เครื่องมือวิเคราะห์แบบสถิติ (static analysis) คุณสามารถใช้ type hints ได้อย่างมีประสิทธิภาพและเพิ่มคุณภาพของโค้ดและการตรวจจับบั๊กตั้งแต่แรกเริ่ม โดยเฉพาะกับ mypy คุณสามารถสร้างสภาพแวดล้อมการพัฒนาที่ทำให้ประโยชน์ของ type hints สูงสุด ในส่วนต่อไป “7. ตัวอย่างการใช้งาน Type Hint อย่างเป็นรูปธรรม” เราจะอธิบายการออกแบบฟังก์ชันและคลาสโดยใช้ type hints อย่างชัดเจน

Ad

7. ตัวอย่างการใช้งาน Type Hint อย่างเป็นรูปธรรม

ในที่นี้ เราจะอธิบายว่าการใช้ type hints สามารถนำไปใช้ในงานจริงได้อย่างไรผ่านตัวอย่างที่เป็นรูปธรรม Type hints ไม่ได้เป็นเพียงเอกสารเท่านั้น; มันเป็นเครื่องมือที่ทรงพลังในการปรับปรุงความอ่านง่ายของโค้ดและความปลอดภัย ในส่วนนี้เราจะแสดงวิธีการใช้ type hints ในฟังก์ชัน, คลาส, พารามิเตอร์แบบตัวแปร, และกรณีต่าง ๆ

การใช้ Type Hints ในฟังก์ชัน

1. การระบุประเภทของฟังก์ชันพื้นฐาน

โดยการใช้ type hints คุณสามารถระบุอินพุตและเอาต์พุตของฟังก์ชันได้อย่างชัดเจน ตัวอย่าง:

def calculate_area(length: float, width: float) -> float:
    return length * width

area = calculate_area(5.0, 3.0)
print(f"Area: {area}")
  • พารามิเตอร์ length และ width มีประเภทเป็นจำนวนทศนิยม ( float ).
  • ค่าที่คืนกลับก็เป็นประเภทจำนวนทศนิยม ( float ).

2. การระบุประเภทสำหรับอาร์กิวเมนต์ค่าเริ่มต้น

แม้ว่าคุณจะมีอาร์กิวเมนต์ที่มีค่าเริ่มต้น คุณก็สามารถระบุ type hints ได้ ตัวอย่าง:

def greet(name: str = "Guest") -> str:
    return f"Hello, {name}!"

print(greet())  # "Hello, Guest!"
print(greet("Alice"))  # "Hello, Alice!"
  • name มีประเภทเป็นสตริงและมีค่าเริ่มต้นเป็น "Guest" .

Type Hints สำหรับอาร์กิวเมนต์ความยาวตัวแปร

1. การระบุประเภทสำหรับอาร์กิวเมนต์ความยาวตัวแปร (*args)

เมื่อรับอาร์กิวเมนต์หลายค่า ใช้ *args และระบุประเภทของมัน ตัวอย่าง:

from typing import List

def sum_numbers(*numbers: int) -> int:
    return sum(numbers)

print(sum_numbers(1, 2, 3))  # 6
  • *numbers รับค่าเป็นทูเพิลของประเภทจำนวนเต็ม ( int ).

2. การระบุประเภทสำหรับอาร์กิวเมนต์คีย์เวิร์ด (**kwargs)

เมื่อใช้อาร์กิวเมนต์แบบคีย์เวิร์ด คุณก็สามารถระบุ type hints ได้เช่นกัน ตัวอย่าง:

from typing import Dict

def display_info(**info: str) -> None:
    for key, value in info.items():
        print(f"{key}: {value}")

display_info(name="Alice", age="25", city="New York")
  • **info เป็นดิกชันนารี (ประเภท Dict[str, str] ) ที่คีย์เป็นสตริงและค่าก็เป็นสตริงเช่นกัน.

Type Hints ในการออกแบบคลาส

1. Type Hints ภายในคลาส

โดยการเพิ่ม type hints ให้กับแอตทริบิวต์และเมธอดของคลาส คุณทำให้การออกแบบชัดเจนขึ้น ตัวอย่าง:

class Student:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def introduce(self) -> str:
        return f"My name is {self.name}, and I am {self.age} years old."

student = Student("Alice", 20)
print(student.introduce())
  • name และ age มีประเภทเป็นสตริง ( str ) และจำนวนเต็ม ( int ) ตามลำดับ.
  • เมธอด introduce คืนค่าประเภทสตริง ( str ).

2. การระบุ Type Hints สำหรับแอตทริบิวต์ของคลาส

คุณยังสามารถเขียน type hints สำหรับแอตทริบิวต์ระดับคลาสได้ ตัวอย่าง:

class School:
    name: str = "Default School"
    students: int = 0
  • name มีประเภทสตริง ( str ), students มีประเภทจำนวนเต็ม ( int ).

การใช้ Type Aliases อย่างเป็นรูปธรรม

การใช้ type aliases ช่วยให้คุณสามารถนำประเภทที่ซับซ้อนมาใช้ซ้ำได้อย่างกระชับ.

1. การกำหนด Type Aliases

from typing import List

Vector = List[float]

def calculate_magnitude(vector: Vector) -> float:
    return sum(x**2 for x in vector) ** 0.5

vector = [1.0, 2.0, 3.0]
print(calculate_magnitude(vector))  # 3.7416573867739413
  • Vector ถูกกำหนดเป็นรายการของประเภทจำนวนทศนิยม ( List[float] ).

2. การใช้ประเภทที่กำหนดเอง

คุณสามารถใช้ type aliases กับโครงสร้างข้อมูลที่ซับซ้อนได้เช่นกัน ตัวอย่าง:

from typing import Dict, List

StudentScores = Dict[str, List[int]]

scores: StudentScores = {
    "Alice": [90, 85, 88],
    "Bob": [72, 75, 78]
}
  • StudentScores คือพจนานุกรมที่คีย์เป็นประเภทสตริงและค่เป็นรายการของประเภทจำนวนเต็ม

การออกแบบโค้ดที่ปลอดภัยด้วยการตรวจสอบประเภท

ผสานกับเครื่องมือการตรวจสอบประเภท (เช่น mypy) คุณสามารถเพิ่มความปลอดภัยของโค้ดที่ใช้งานจริงได้

1. การตรวจสอบประเภทที่อาจรวมค่า None

ใช้ Optional เพื่ออนุญาตให้อาร์กิวเมนต์เป็น None อย่างชัดเจน
ตัวอย่าง:

from typing import Optional

def find_student(name: str) -> Optional[str]:
    students = ["Alice", "Bob", "Charlie"]
    return name if name in students else None
  • ฟังก์ชัน find_student คืนค่าประเภทสตริง (str) หรือ None .

สรุป

ในส่วนนี้เราได้แสดงตัวอย่างการใช้งานจริงรวมถึงฟังก์ชัน, คลาส, และอาร์กิวเมนต์ที่มีความยาวเปลี่ยนแปลงได้ของการใช้ type hint. การใช้ type hint อย่างถูกต้องจะช่วยปรับปรุงความอ่านง่ายของโค้ด, ความสามารถในการบำรุงรักษา, และป้องกันบั๊กล่วงหน้า.
ส่วนต่อไป “8. Frequently Asked Questions (FAQ)” จะอธิบายคำถามทั่วไปและความเข้าใจผิดเกี่ยวกับ type hint.

Ad

8. คำถามที่พบบ่อย (FAQ)

Type hint ใน Python เป็นเครื่องมือที่มีประโยชน์, แต่เมื่อใช้เป็นครั้งแรกอาจเกิดคำถามและความเข้าใจผิดได้ ส่วนนี้จะตอบคำถามที่พบบ่อยเกี่ยวกับ type hint และให้คำตอบที่ชัดเจน

ปัญหาอะไรเกิดขึ้นหากคุณไม่ใช้ Type Hints?

โค้ด Python ทำงานได้แม้ไม่มี type hint, แต่ปัญหาต่อไปนี้มีแนวโน้มจะเกิดบ่อยขึ้น:

  1. ลดความอ่านง่าย หากประเภทของฟังก์ชันหรือ ตัวแปรไม่ได้ระบุ, นักพัฒนาคนอื่นจะใช้เวลานานกว่าในการเข้าใจโค้ด
    def add(a, b):
        return a + b
    

ในฟังก์ชันนี้, ประเภทของ a และ b ไม่ทราบ, ดังนั้นจึงไม่ชัดเจนว่าคาดหวังประเภทตัวเลขหรือสตริง

  1. เพิ่มบั๊ก เนื่องจากประเภทไม่ชัดเจน, การส่งประเภทที่ไม่ถูกต้องอาจไม่ทำให้เกิดข้อผิดพลาดทันทีและบั๊กในระหว่างรันอาจเพิ่มขึ้น

การใช้ Type Hints ช่วยเพิ่มความเร็วการทำงานหรือไม่?

ไม่, type hint ไม่ส่งผลความการทำงาน
Type hint เป็นเพียง “คำแนะนำ” และไม่ส่งผลต่อพฤติกรรมการทำงานของ Python. การตรวจสอบประเภททำที่ไม่ใช่เวลารัน แต่โดยเครื่องมือวิเคราะห์แบบสถิต (เช่น: mypy)

มีวิธีบังคับใช้ Type Hints อย่างเคร่งครัดหรือไม่?

แม้ Python จะไม่มีกลไกบังคับใช้ type hint, คุณสามารถกำหนดกฎเช่น “ห้ามโค้ดที่ไม่มี type hint” ดังนี้:

  1. ใช้เครื่องมือวิเคราะห์แบบสถิติ โดยใช้ตัวเลือก --strict ของ mypy คุณสามารถตรวจจับฟังก์ชันที่ไม่มี type hint เป็นข้อผิดพลาด
    mypy --strict your_script.py
    
  1. ทำให้เป็นกฎในการตรวจสอบโค้ดหรือ CI/CD โดยกำหนดกฎใน pull request หรือ pipeline ของ CI/CD เพื่อตรวจสอบการมีอยู่ของ type hint, คุณสามารถบังคับให้ใช้ได้

จะจัดการกับการตรวจสอบ mypy ที่ช้าอย่างไร?

ในโครงการขนาดใหญ่, การตรวจสอบประเภทของ mypy อาจช้า. คุณสามารถปรับปรุงประสิทธิภาพด้วยวิธีต่อไปนี้:

  1. ใช้โหมด incremental ตัวเลือก --incremental จะทำการตรวจสอบเฉพาะส่วนที่เปลี่ยนแปลง
    mypy --incremental your_script.py
    
  1. ละเว้นบางโมดูล คุณสามารถยกเว้นโมดูลภายนอกที่ไม่ต้องการการตรวจสอบประเภทโดยใช้ --ignore-missing-imports
    mypy --ignore-missing-imports your_script.py
    

แหล่งข้อมูลใดที่ผู้เริ่มต้นต้องการเพื่อเรียนรู้ Type Hints?

คุณสามารถเรียนรู้พื้นฐานและการประยุกต์ใช้ type hint อย่างมีประสิทธิภาพโดยใช้แหล่งข้อมูลต่อไปนี้:

  1. เอกสารอย่างเป็นทางการของ Python (PEP 484) สเปคพื้นฐานของ type hint ถูกอธิบายไว้ PEP 484 – Type Hints
  2. บทแนะนำอย่างเป็นทางการของ Python เกี่ยวกับ Type Hints ตัวอย่างการใช้งานอย่างละเอียดถูกอธิบาย Typing Module
  3. แพลตฟอร์มการเรียนรู้ออนไลน์ บน Udemy หรือ Coursera ค้นหา “Python type hints” เพื่อเรียนอย่างเป็นระบบ

ควรใช้ Type Hints เมื่อใดและเมื่อใดที่ยอมให้ข้ามได้?

สถานการณ์ที่คุณควรใช้ Type Hints:

  1. การพัฒนาทีม โดยการใช้ type hints คุณช่วยให้ผู้พัฒนาคนอื่นเข้าใจโค้ดได้ง่ายขึ้น
  2. โครงการขนาดใหญ่ ยิ่งโครงการใหญ่ขึ้น type hints ยิ่งช่วยป้องกันบั๊กได้มากขึ้น
  3. API หรือไลบรารีภายนอกที่เปิดเผย เมื่อคุณให้ฟังก์ชันหรือคลาสสำหรับผู้อื่นใช้งาน type hints ช่วยให้ผู้ใช้เข้าใจการใช้งานได้ดีขึ้น

สถานการณ์ที่คุณอาจข้าม Type Hints:

  1. สคริปต์ขนาดเล็ก อายุสั้น เช่น สคริปต์วิเคราะห์ข้อมูลง่ายๆ หรือสคริปต์อัตโนมัติ
  2. โค้ดต้นแบบ ในขั้นตอนการสร้างต้นแบบ คุณอาจละเว้น type hints เพื่อเร่งการพัฒนา

ประโยชน์ทางปฏิบัติจากการใช้ Type Hints คืออะไร?

โดยการใช้ type hints คุณจะได้รับประโยชน์ทางปฏิบัติดังต่อไปนี้:

  1. การตรวจพบบั๊กตั้งแต่เนิ่นๆ การวิเคราะห์แบบคงที่ที่ใช้ type hints ป้องกันบั๊กก่อนการรันโค้ด
  2. เพิ่มประสิทธิภาพการพัฒนา การเติมโค้ดอัตโนมัติของ IDE ช่วยเพิ่มความเร็วในการเขียนโค้ดและลดข้อผิดพลาด
  3. ปรับปรุงความสามารถในการบำรุงรักษา ด้วยประเภทที่ชัดเจน ผู้ที่อ่านโค้ดในอนาคตจะเข้าใจได้ง่ายขึ้น

สรุป

ในส่วนนี้เราได้ตอบคำถามทั่วไปเกี่ยวกับ type hints Type hints เรียนรู้ได้ง่ายและสามารถปรับปรุงประสิทธิภาพการพัฒนาและคุณภาพโค้ดได้อย่างมาก เมื่อรวมกับเครื่องมือวิเคราะห์แบบคงที่ คุณสามารถดึงประโยชน์เต็มที่จากมันได้

Ad

9. สรุป

ในบทความนี้เราได้อธิบายอย่างละเอียดเกี่ยวกับวิธีการระบุประเภทอาร์กิวเมนต์โดยใช้ “type hints” ของ Python ตั้งแต่พื้นฐานไปจนถึงการใช้งานขั้นสูง การใช้เครื่องมือสำหรับตรวจสอบประเภท และตัวอย่างการใช้งานจริง สุดท้ายเราสรุปเนื้อหาและแบ่งปันประเด็นสำคัญสำหรับการใช้ type hints อย่างมีประสิทธิภาพ

ความสำคัญของ Type Hints

Type hints รักษาความยืดหยุ่นของการพิมพ์แบบไดนามิกของ Python ในขณะที่นำเสนอข้อดีมากมายดังต่อไปนี้:

  1. ปรับปรุงความสามารถในการอ่าน โดยการระบุข้อมูลประเภทในโค้ด บทบาทของฟังก์ชันและตัวแปรจะชัดเจนในทันที
  2. ป้องกันบั๊กผ่านการวิเคราะห์แบบคงที่ การตรวจพบความไม่ตรงกันของประเภทก่อนการรันโค้ดช่วยลดบั๊กที่อาจเกิดขึ้น
  3. เพิ่มประสิทธิภาพการพัฒนา การใช้การเติมโค้ดอัตโนมัติของ IDE ช่วยเร่งการเขียนโค้ดและลดข้อผิดพลาด
  4. ปรับปรุงความสามารถในการบำรุงรักษา ประเภทที่ชัดเจนหมายถึงผู้ที่อ่านโค้ดในอนาคตจะเข้าใจได้ง่ายขึ้น

ขั้นตอนสำหรับการนำ Type Hints มาใช้

นี่คือขั้นตอนสำหรับการรวม type hints อย่างมีประสิทธิภาพ:

1. นำมาใช้อย่างค่อยเป็นค่อยไป

หากเพิ่ม type hints ในโครงการที่มีอยู่แล้ว ลำดับต่อไปนี้จะมีประโยชน์:

  • เพิ่ม type hints ในฟังก์ชันหรือคลาสหลัก
  • ใช้เครื่องมือวิเคราะห์แบบคงที่ (เช่น: mypy) เพื่อตรวจสอบประเภทอัตโนมัติ
  • แบ่งปันกฎการใช้ type hints ภายในทีมของคุณ

2. หลีกเลี่ยงการระบุประเภทที่ซับซ้อนเกินไป

หากประเภทซับซ้อนเกินไป ความสามารถในการอ่านอาจลดลง ใช้การแยกส่วนที่เหมาะสมหรือชื่อแฝงประเภทเพื่อให้กระชับ

3. ใช้เครื่องมือวิเคราะห์แบบคงที่

นำเครื่องมือเช่น mypy หรือ PyCharm มาใช้เพื่อควบคุมคุณภาพโดยใช้ type hints

ประเด็นสำหรับการใช้ Type Hints อย่างมีประสิทธิภาพ

พิจารณาสิ่งต่อไปนี้เพื่อให้ได้คุณค่าจาก type hints อย่างสูงสุด:

  1. คุณไม่จำเป็นต้องเพิ่ม type hints ทุกที่ ในสคริปต์ขนาดเล็กหรือต้นแบบ คุณอาจข้ามได้ สิ่งสำคัญคือความสมดุล
  2. ใช้ทรัพยากรอย่างเป็นทางการของ Python การอ้างอิงเอกสารอย่างเป็นทางการของ Python (PEP 484, โมดูล typing) ช่วยให้คุณเรียนรู้ข้อกำหนดล่าสุด
  3. เลือกเครื่องมือตรวจสอบประเภทที่เหมาะกับสภาพแวดล้อมของคุณ เลือกเครื่องมือที่เหมาะสม (เช่น: mypy, pylance) ตามขนาดทีมและลักษณะโครงการ

อนาคตของ Type Hints

ระบบ type hints ของ Python อาจพัฒนาต่อไป ด้วย Python Enhancement Proposals (PEPs) ใหม่ๆ ที่เกิดขึ้น การระบุประเภทที่ยืดหยุ่นและแสดงออกได้มากขึ้นอาจเป็นไปได้ โดยการเรียนรู้ตั้งแต่เนิ่นๆ และเข้าใจวิธีการใช้ คุณสามารถได้เปรียบในโครงการ Python ในอนาคต

ขั้นตอนถัดไป

ตอนนี้คุณได้เรียนรู้พื้นฐานและการประยุกต์ใช้ type hints แล้ว ให้ทำตามขั้นตอนต่อไปนี้:

  1. เพิ่ม type hints ในโครงการของคุณเอง
  2. นำเครื่องมือวิเคราะห์แบบคงที่มาใช้และทำการตรวจสอบประเภท
  3. อ้างอิงเอกสารและทรัพยากรอย่างเป็นทางการเกี่ยวกับ type hints และเพิ่มความรู้ของคุณ

สุดท้าย

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

Ad
年収訴求