Python 3.0-এ প্রবর্তিত ফাংশন টীকাগুলি এমন একটি বৈশিষ্ট্য যুক্ত করে যা আপনাকে ফাংশন প্যারামিটার এবং রিটার্ন মানগুলিতে নির্বিচারে মেটাডেটা যোগ করতে দেয়। পাইথন 3 থেকে, ফাংশন টীকাগুলি আনুষ্ঠানিকভাবে পাইথনে (PEP-3107) যোগ করা হয়েছে। প্রাথমিক উদ্দেশ্য ছিল ফাংশন প্যারামিটার এবং রিটার্ন মানের সাথে মেটাডেটা লিঙ্ক করার একটি আদর্শ উপায়।
ফাংশন টীকাগুলির মূল বিষয়গুলি
আসুন ফাংশন টীকা-
-এর কিছু মৌলিক বিষয় বুঝুন-
ফাংশন টীকা প্যারামিটার এবং রিটার্ন মান উভয়ের জন্য সম্পূর্ণ ঐচ্ছিক।
-
ফাংশন টীকা কম্পাইলের সময় নির্বিচারে পাইথন এক্সপ্রেশনের সাথে ফাংশনের বিভিন্ন অংশকে সংযুক্ত করার একটি উপায় প্রদান করে।
-
PEP-3107 কোনো ধরনের স্ট্যান্ডার্ড শব্দার্থ প্রবর্তনের কোনো চেষ্টা করে না, এমনকি বিল্ট-ইন ধরনের জন্যও। এই সমস্ত কাজ তৃতীয় পক্ষের লাইব্রেরিতে ছেড়ে দেওয়া হয়েছে৷
৷
সিনট্যাক্স
সাধারণ প্যারামিটারের টীকা
পরামিতিগুলির জন্য টীকাগুলি নিম্নলিখিত ফর্মটি নেয় -
def foo(x: expression, y: expression = 20): ….
যেখানে অতিরিক্ত প্যারামিটারের জন্য টীকাগুলি হল −
৷def foo(**args: expression, **kwargs: expression): …..
নেস্টেড প্যারামিটারের ক্ষেত্রে, টীকাগুলি সর্বদা পরামিতিগুলির নাম অনুসরণ করে এবং শেষ বন্ধনী পর্যন্ত নয়। একটি নেস্টেড প্যারামিটারের সমস্ত প্যারামিটার টীকা করার প্রয়োজন নেই৷
৷def foo(x1, y1: expression), (x2: expression, y2: expression)=(None, None)): ……
এটা বোঝা গুরুত্বপূর্ণ যে পাইথন টীকা সহ কোন শব্দার্থবিদ্যা প্রদান করে না। এটি শুধুমাত্র মেটাডেটা সংযুক্ত করার পাশাপাশি এটি অ্যাক্সেস করার একটি সহজ উপায়ের জন্য চমৎকার সিনট্যাকটিক সমর্থন প্রদান করে। এছাড়াও, টীকা বাধ্যতামূলক নয়।
>>> def func(x:'annotating x', y: 'annotating y', z: int) -> float: print(x + y + z)
উপরের উদাহরণে, ফাংশন func() x,y এবং z নামে তিনটি প্যারামিটার নেয়, অবশেষে তাদের যোগফল প্রিন্ট করে। প্রথম আর্গুমেন্ট x স্ট্রিং 'এনোটেটিং x' দিয়ে টীকা করা হয়, দ্বিতীয় আর্গুমেন্ট y স্ট্রিং 'টীকা y' দিয়ে টীকা করা হয় এবং তৃতীয় আর্গুমেন্ট z টাইপ int দিয়ে টীকা করা হয়। রিটার্ন মান টাইপ ফ্লোট দিয়ে টীকা করা হয়। এখানে রিটার্ন মান টীকা করার জন্য '->' সিনট্যাক্স।
আউটপুট
>>> func(2,3,-4)
1
>>> func('Function','-','Annotation')
Function-Annotation উপরে আমরা দুইবার func() কল করি, একবার int আর্গুমেন্ট সহ এবং একবার স্ট্রিং আর্গুমেন্ট সহ। উভয় ক্ষেত্রেই, func() সঠিক কাজ করে এবং টীকাগুলিকে উপেক্ষা করা হয়। সুতরাং, আমরা দেখতে পাচ্ছি যে ফাংশন ফাংশনটি কার্যকর করার উপর টীকাগুলির কোন প্রভাব নেই।
ফাংশন টীকা অ্যাক্সেস করা
সমস্ত টীকা __এনোটেশন__ নামে একটি অভিধানে সংরক্ষিত থাকে, যেটি নিজেই ফাংশনের একটি বৈশিষ্ট্য -
>>> def func(x:'annotating x', y: 'annotating y', z: int) -> float: print(x + y + z)
>>> func.__annotations__
{'x': 'annotating x', 'y': 'annotating y', 'z': <class 'int'>, 'return': <class 'float'>} আমরা পূর্ববর্তী কোড উদাহরণে দেখতে পাচ্ছি, টীকাগুলি টাইপ করা ঘোষণা নয়, যদিও সেগুলি অবশ্যই সেই উদ্দেশ্যে ব্যবহার করা যেতে পারে এবং সেগুলি অন্য কিছু ভাষায় ব্যবহৃত টাইপিং সিনট্যাক্সের সাথে সাদৃশ্যপূর্ণ, যেমনটি নীচে দেখানো হয়েছে -
>>> def func(a: 'python', b: {'category: ' 'language'}) -> 'yep':
pass
>>> func.__annotations__
{'a': 'python', 'b': {'category: language'}, 'return': 'yep'}
>>> এগুলি স্বেচ্ছাচারী অভিব্যক্তি, যার অর্থ হল নির্বিচারে মানগুলি __ টীকা__ অভিধানে সংরক্ষণ করা যেতে পারে। যদিও, তারা পাইথনের সাথে খুব বেশি তাত্পর্য যোগ করে না, তবে এটির মানগুলি সংরক্ষণ করা উচিত। তাতে বলা হয়েছে, প্যারামিটার এবং রিটার্নের ধরন সংজ্ঞায়িত করা ফাংশন টীকাগুলির একটি সাধারণ ব্যবহার।
@no_type_check ডেকোরেটর
আপনি যদি নিজেকে এমন একটি টুল ব্যবহার করেন যা অনুমান করে যে টীকাগুলি টাইপ ঘোষণা কিন্তু আপনি সেগুলি অন্য কোনও উদ্দেশ্যে ব্যবহার করতে চান, তাহলে এই ধরনের প্রক্রিয়াকরণ থেকে আপনার ফাংশনকে অব্যাহতি দিতে স্ট্যান্ডার্ড @no_type_check ডেকোরেটর ব্যবহার করুন, যেমনটি এখানে দেখানো হয়েছে −
>>> from typing import no_type_check
>>> @no_type_check
def func(a: 'python', b: {'category: ' 'language'}) -> 'yep':
pass
>>> সাধারণত, এটির প্রয়োজন হয় না কারণ টীকাগুলি ব্যবহার করে এমন বেশিরভাগ সরঞ্জামগুলির তাদের জন্য বোঝানোর জন্য একটি উপায় রয়েছে৷ ডেকোরেটর কোণার কেসগুলিকে রক্ষা করার জন্য যেখানে জিনিসগুলি অস্পষ্ট।
ফাংশন ডেকোরেটরগুলিতে ইনপুট হিসাবে টীকা
টীকাগুলি ডেকোরেটরগুলির সাথে ভালভাবে একত্রিত হয় কারণ টীকা মানগুলি একটি ডেকোরেটরকে ইনপুট দেওয়ার একটি ভাল উপায় করে এবং ডেকোরেটর-উত্পাদিত র্যাপারগুলি কোড রাখার একটি ভাল জায়গা যা টীকাগুলির অর্থ দেয়৷
from functools import wraps
def adapted(func):
@wraps(func)
def wrapper(**kwargs):
final_args = {}
for name, value in kwargs. items():
adapt = func.__annotations__.get(name)
if adapt is not None:
final_args[name] = adapt(value)
else:
final_args[name] = value
result = func(**final_args)
adapt = func.__annotations__.get('result')
if adapt is not None:
return adapt(result)
return result
return wrapper
@adapted
def func(a: int, b: repr) -> str:
return a সুতরাং, অভিযোজিত ডেকোরেটর একটি মোড়কে ফাংশনটি আবদ্ধ করে। এই মোড়কটি শুধুমাত্র কীওয়ার্ড আর্গুমেন্ট গ্রহণ করে, যার অর্থ হল, এমনকি যদি মূল ফাংশনটি অবস্থানগত আর্গুমেন্ট গ্রহণ করতে পারে, তবে সেগুলিকে নাম দ্বারা নির্দিষ্ট করতে হবে৷
একবার ফাংশনটি মোড়ানো হয়ে গেলে, র্যাপার ফাংশনের প্যারামিটার টীকাগুলিতে অ্যাডাপ্টারগুলিও সন্ধান করে এবং বাস্তব ফাংশনে আর্গুমেন্টগুলি পাস করার আগে সেগুলি প্রয়োগ করে৷
একবার ফাংশনটি ফিরে গেলে, মোড়ক একটি রিটার্ন মান অ্যাডাপ্টারের জন্য পরীক্ষা করে; যদি এটি একটি খুঁজে পায়, শেষ পর্যন্ত এটি ফেরত দেওয়ার আগে এটি রিটার্ন মানের সাথে প্রয়োগ করে৷
যখন আমরা এখানে যা ঘটছে তার প্রভাব বিবেচনা করি, তারা বেশ চিত্তাকর্ষক। একটি ফাংশনে একটি প্যারামিটার পাস করা বা একটি মান ফেরত দেওয়ার অর্থ আমরা আসলে পরিবর্তন করেছি৷
কীওয়ার্ড আর্গুমেন্ট
কখনও কখনও, একটি বা একাধিক পদ্ধতির পরামিতিগুলির কোনও প্রক্রিয়াকরণের প্রয়োজন হয় না, সেগুলিকে স্ব-এর একটি বৈশিষ্ট্যে বরাদ্দ করা ছাড়া৷ এটি স্বয়ংক্রিয়ভাবে ঘটতে আমরা কি সাজসজ্জা এবং টীকা ব্যবহার করতে পারি? অবশ্যই, আমরা পারি।
from functools import wraps def store_args(func): @wraps(func) def wrapper(self, **kwargs): for name, value in kwargs.items(): attrib = func.__annotations__.get(name) if attrib is True: attrib = name if isinstance(attrib, str): setattr(self, attrib, value) return func(self, **kwargs) return wrapper class A: @store_args def __init__(self, first: True, second: 'example'): pass a = A(first = 5, second = 6) assert a.first == 5 assert a.example == 6