آموزش پایتون - حاشیه‌نویسی توابع

آموزش حاشیه‌نویسی توابع (Function Annotations)

ویژگی حاشیه‌نویسی تابع (Function Annotation) در پایتون این امکان را به شما می‌دهد تا متاداده‌های توضیحی اضافی درباره آرگومان‌های تعریف‌شده در یک تابع و همچنین نوع داده بازگشتی آن اضافه کنید. این حاشیه‌نویسی‌ها در هنگام اجرای تابع توسط مفسر پایتون در نظر گرفته نمی‌شوند و عمدتاً برای محیط‌های توسعه (IDE) پایتون جهت ارائه مستندات دقیق به برنامه‌نویس کاربرد دارند.

اگرچه می‌توانید از ویژگی رشته‌های مستندسازی (docstring) پایتون برای مستندسازی تابع استفاده کنید، اما با اعمال برخی تغییرات در پروتوتایپ تابع، این مستندات ممکن است قدیمی و منسوخ شوند. از این رو، ویژگی حاشیه‌نویسی در نتیجه پیشنهاد PEP 3107 به پایتون اضافه شد.

حاشیه‌نویسی‌ها می‌توانند هر عبارت معتبر پایتون باشند که به آرگومان‌ها یا نوع داده بازگشتی اضافه می‌شوند. ساده‌ترین مثال حاشیه‌نویسی، مشخص کردن نوع داده آرگومان‌ها است. حاشیه‌نویسی به‌صورت یک عبارت، پس از قرار دادن علامت دو نقطه (:) در جلوی آرگومان ذکر می‌شود.

مثال

به یاد داشته باشید که پایتون یک زبان با تایپ پویا (Dynamically Typed) است و هیچ‌گونه بررسی نوعی را در زمان اجرا اعمال نمی‌کند. بنابراین، حاشیه‌نویسی آرگومان‌ها با انواع داده‌ها هیچ تاثیری هنگام فراخوانی تابع ندارد. حتی اگر آرگومان‌های غیر صحیح (غیر int) داده شوند، پایتون هیچ خطایی را تشخیص نمی‌دهد.

def myfunction(a: int, b: int):
   c = a+b
   return c
   
print (myfunction(10,20))
print (myfunction("Hello ", "Python"))

این کد خروجی زیر را تولید خواهد کرد −

30
Hello Python

حاشیه‌نویسی توابع همراه با نوع بازگشتی

حاشیه‌نویسی‌ها در زمان اجرا نادیده گرفته می‌شوند، اما برای IDEها و کتابخانه‌های بررسی ایستای نوع (Static Type Checker) مانند mypy بسیار مفید هستند.

شما می‌توانید برای نوع داده بازگشتی نیز حاشیه‌نویسی کنید. بعد از پرانتزها و قبل از علامت دو نقطه، یک فلش (<-) و به دنبال آن حاشیه‌نویسی قرار دهید.

مثال

در این مثال، ما در حال ارائه حاشیه‌نویسی برای نوع بازگشتی هستیم.

def myfunction(a: int, b: int) -> int:
   c = a+b
   return c
print(myfunction(56,88))
print(myfunction.__annotations__)

این کد خروجی زیر را تولید خواهد کرد −

144
{'a': <class 'int'>, 'b': <class 'int'>, 'return': <class 'int'>}

حاشیه‌نویسی توابع با عبارت (Expression)

از آنجا که استفاده از نوع داده به عنوان حاشیه‌نویسی در زمان اجرا نادیده گرفته می‌شود، می‌توانید هر عبارتی را که به عنوان متاداده برای آرگومان‌ها عمل می‌کند قرار دهید. بنابراین، تابع می‌تواند هر عبارت دلخواهی را به عنوان حاشیه‌نویسی داشته باشد.

مثال

در مثال زیر، از عبارت به عنوان حاشیه‌نویسی تابع استفاده می‌کنیم.

def total(x : 'marks in Physics', y: 'marks in chemistry'):
   return x+y
print(total(86, 88))
print(total.__annotations__)

خروجی به صورت زیر است −

174
{'x': 'marks in Physics', 'y': 'marks in chemistry'}

حاشیه‌نویسی توابع با آرگومان‌های پیش‌فرض

اگر می‌خواهید یک آرگومان پیش‌فرض را همراه با حاشیه‌نویسی مشخص کنید، باید آن را بعد از عبارت حاشیه‌نویسی قرار دهید. آرگومان‌های پیش‌فرض باید بعد از آرگومان‌های اجباری در لیست آرگومان‌ها بیایند.

مثال ۱

مثال زیر نحوه ارائه حاشیه‌نویسی برای آرگومان‌های پیش‌فرض یک تابع را نشان می‌دهد.

def myfunction(a: "physics", b:"Maths" = 20) -> int:
   c = a+b
   return c
print (myfunction(10))

تابع در پایتون یک شیء (Object) نیز هست و یکی از ویژگی‌های (Attributes) آن __annotations__ است. می‌توانید آن را با تابع ()dir بررسی کنید.

print (dir(myfunction))

این دستور لیستی از شیء myfunction را چاپ می‌کند که شامل __annotations__ به عنوان یکی از ویژگی‌ها است.

['__annotations__', '__builtins__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__getstate__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

مثال ۲

ویژگی __annotations__ خود یک دیکشنری است که در آن آرگومان‌ها کلیدها و حاشیه‌نویسی‌ها مقادیر آن‌ها هستند.

def myfunction(a: "physics", b:"Maths" = 20) -> int:
   c = a+b
   return c
print (myfunction.__annotations__)

این کد خروجی زیر را تولید خواهد کرد −

{'a': 'physics', 'b': 'Maths', 'return': <class 'int'>}

مثال ۳

شما می‌توانید آرگومان‌های موقعیتی دلخواه و/یا آرگومان‌های کلیدواژه‌ای دلخواه برای یک تابع داشته باشید. برای آن‌ها نیز می‌توان حاشیه‌نویسی ارائه داد.

def myfunction(*args: "arbitrary args", **kwargs: "arbitrary keyword args") -> int:
   pass
print (myfunction.__annotations__)

این کد خروجی زیر را تولید خواهد کرد −

{'args': 'arbitrary args', 'kwargs': 'arbitrary keyword args', 'return': <class 'int'>}

مثال ۴

در صورتی که نیاز به ارائه بیش از یک عبارت حاشیه‌نویسی برای یک آرگومان تابع دارید، آن را به شکل یک شیء دیکشنری در جلوی خود آرگومان قرار دهید.

def division(num: dict(type=float, msg='numerator'), den: dict(type=float, msg='denominator')) -> float:
   return num/den
print (division.__annotations__)

این کد خروجی زیر را تولید خواهد کرد −

{'num': {'type': <class 'float'>, 'msg': 'numerator'}, 'den': {'type': <class 'float'>, 'msg': 'denominator'}, 'return': <class 'float'>}

پیشرفت مطالعه: وضعیت خوانده‌شدن این درس فقط در همین مرورگر ذخیره می‌شود؛ بدون نیاز به حساب کاربری.