কনটেন্টে যান

পাইথন এর টাইপ্স পরিচিতি

Python-এ ঐচ্ছিক "টাইপ হিন্ট" (যা "টাইপ অ্যানোটেশন" নামেও পরিচিত) এর জন্য সাপোর্ট রয়েছে।

এই "টাইপ হিন্ট" বা অ্যানোটেশনগুলি এক ধরণের বিশেষ সিনট্যাক্স যা একটি ভেরিয়েবলের টাইপ ঘোষণা করতে দেয়।

ভেরিয়েবলগুলির জন্য টাইপ ঘোষণা করলে, এডিটর এবং টুলগুলি আপনাকে আরও ভালো সাপোর্ট দিতে পারে।

এটি পাইথন টাইপ হিন্ট সম্পর্কে একটি দ্রুত টিউটোরিয়াল / রিফ্রেশার মাত্র। এটি FastAPI এর সাথে ব্যবহার করার জন্য শুধুমাত্র ন্যূনতম প্রয়োজনীয়তা কভার করে... যা আসলে খুব একটা বেশি না।

FastAPI এই টাইপ হিন্টগুলির উপর ভিত্তি করে নির্মিত, যা এটিকে অনেক সুবিধা এবং লাভ প্রদান করে।

তবে, আপনি যদি কখনো FastAPI ব্যবহার নাও করেন, তবুও এগুলি সম্পর্কে একটু শেখা আপনার উপকারে আসবে।

Note

যদি আপনি একজন Python বিশেষজ্ঞ হন, এবং টাইপ হিন্ট সম্পর্কে সবকিছু জানেন, তাহলে পরবর্তী অধ্যায়ে চলে যান।

প্রেরণা

চলুন একটি সাধারণ উদাহরণ দিয়ে শুরু করি:

def get_full_name(first_name, last_name):
    full_name = first_name.title() + " " + last_name.title()
    return full_name


print(get_full_name("john", "doe"))

এই প্রোগ্রামটি কল করলে আউটপুট হয়:

John Doe

ফাংশনটি নিম্নলিখিত কাজ করে:

  • first_name এবং last_name নেয়।
  • প্রতিটির প্রথম অক্ষরকে title() ব্যবহার করে বড় হাতের অক্ষরে রূপান্তর করে।
  • তাদেরকে মাঝখানে একটি স্পেস দিয়ে concatenate করে।
def get_full_name(first_name, last_name):
    full_name = first_name.title() + " " + last_name.title()
    return full_name


print(get_full_name("john", "doe"))

এটি সম্পাদনা করুন

এটি একটি খুব সাধারণ প্রোগ্রাম।

কিন্তু এখন কল্পনা করুন যে আপনি এটি শুরু থেকে লিখছিলেন।

এক পর্যায়ে আপনি ফাংশনের সংজ্ঞা শুরু করেছিলেন, আপনার প্যারামিটারগুলি প্রস্তুত ছিল...

কিন্তু তারপর আপনাকে "সেই method কল করতে হবে যা প্রথম অক্ষরকে বড় হাতের অক্ষরে রূপান্তর করে"।

এটা কি upper ছিল? নাকি uppercase? first_uppercase? capitalize?

তারপর, আপনি পুরোনো প্রোগ্রামারের বন্ধু, এডিটর অটোকমপ্লিশনের সাহায্যে নেওয়ার চেষ্টা করেন।

আপনি ফাংশনের প্রথম প্যারামিটার first_name টাইপ করেন, তারপর একটি ডট (.) টাইপ করেন এবং Ctrl+Space চাপেন অটোকমপ্লিশন ট্রিগার করার জন্য।

কিন্তু, দুর্ভাগ্যবশত, আপনি কিছুই উপযোগী পান না:

টাইপ যোগ করুন

আসুন আগের সংস্করণ থেকে একটি লাইন পরিবর্তন করি।

আমরা ঠিক এই অংশটি পরিবর্তন করব অর্থাৎ ফাংশনের প্যারামিটারগুলি, এইগুলি:

    first_name, last_name

থেকে এইগুলি:

    first_name: str, last_name: str

ব্যাস।

এগুলিই "টাইপ হিন্ট":

def get_full_name(first_name: str, last_name: str):
    full_name = first_name.title() + " " + last_name.title()
    return full_name


print(get_full_name("john", "doe"))

এটি ডিফল্ট ভ্যালু ঘোষণা করার মত নয় যেমন:

    first_name="john", last_name="doe"

এটি একটি ভিন্ন জিনিস।

আমরা সমান (=) নয়, কোলন (:) ব্যবহার করছি।

এবং টাইপ হিন্ট যোগ করা সাধারণত তেমন কিছু পরিবর্তন করে না যা টাইপ হিন্ট ছাড়াই ঘটত।

কিন্তু এখন, কল্পনা করুন আপনি আবার সেই ফাংশন তৈরির মাঝখানে আছেন, কিন্তু টাইপ হিন্ট সহ।

একই পর্যায়ে, আপনি অটোকমপ্লিট ট্রিগার করতে Ctrl+Space চাপেন এবং আপনি দেখতে পান:

এর সাথে, আপনি অপশনগুলি দেখে, স্ক্রল করতে পারেন, যতক্ষণ না আপনি এমন একটি অপশন খুঁজে পান যা কিছু মনে পরিয়ে দেয়:

আরও প্রেরণা

এই ফাংশনটি দেখুন, এটিতে ইতিমধ্যে টাইপ হিন্ট রয়েছে:

def get_name_with_age(name: str, age: int):
    name_with_age = name + " is this old: " + age
    return name_with_age

এডিটর ভেরিয়েবলগুলির টাইপ জানার কারণে, আপনি শুধুমাত্র অটোকমপ্লিশনই পান না, আপনি এরর চেকও পান:

এখন আপনি জানেন যে আপনাকে এটি ঠিক করতে হবে, age-কে একটি স্ট্রিং হিসেবে রূপান্তর করতে str(age) ব্যবহার করতে হবে:

def get_name_with_age(name: str, age: int):
    name_with_age = name + " is this old: " + str(age)
    return name_with_age

টাইপ ঘোষণা

আপনি এতক্ষন টাইপ হিন্ট ঘোষণা করার মূল স্থানটি দেখে ফেলেছেন-- ফাংশন প্যারামিটার হিসেবে।

সাধারণত এটি FastAPI এর ক্ষেত্রেও একই।

সিম্পল টাইপ

আপনি str ছাড়াও সমস্ত স্ট্যান্ডার্ড পাইথন টাইপ ঘোষণা করতে পারেন।

উদাহরণস্বরূপ, আপনি এগুলো ব্যবহার করতে পারেন:

  • int
  • float
  • bool
  • bytes
def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes):
    return item_a, item_b, item_c, item_d, item_d, item_e

টাইপ প্যারামিটার সহ জেনেরিক টাইপ

কিছু ডাটা স্ট্রাকচার অন্যান্য মান ধারণ করতে পারে, যেমন dict, list, set এবং tuple। এবং অভ্যন্তরীণ মানগুলোরও নিজেদের টাইপ থাকতে পারে।

এই ধরনের টাইপগুলিকে বলা হয় "জেনেরিক" টাইপ এবং এগুলিকে তাদের অভ্যন্তরীণ টাইপগুলি সহ ঘোষণা করা সম্ভব।

এই টাইপগুলি এবং অভ্যন্তরীণ টাইপগুলি ঘোষণা করতে, আপনি Python মডিউল typing ব্যবহার করতে পারেন। এটি বিশেষভাবে এই টাইপ হিন্টগুলি সমর্থন করার জন্য রয়েছে।

Python এর নতুন সংস্করণ

typing ব্যবহার করা সিনট্যাক্সটি Python 3.6 থেকে সর্বশেষ সংস্করণগুলি পর্যন্ত, অর্থাৎ Python 3.9, Python 3.10 ইত্যাদি সহ সকল সংস্করণের সাথে সামঞ্জস্যপূর্ণ

Python যত এগিয়ে যাচ্ছে, নতুন সংস্করণগুলি এই টাইপ অ্যানোটেশনগুলির জন্য তত উন্নত সাপোর্ট নিয়ে আসছে এবং অনেক ক্ষেত্রে আপনাকে টাইপ অ্যানোটেশন ঘোষণা করতে typing মডিউল ইম্পোর্ট এবং ব্যবহার করার প্রয়োজন হবে না।

যদি আপনি আপনার প্রজেক্টের জন্য Python-এর আরও সাম্প্রতিক সংস্করণ নির্বাচন করতে পারেন, তাহলে আপনি সেই অতিরিক্ত সরলতা থেকে সুবিধা নিতে পারবেন।

ডক্সে রয়েছে Python-এর প্রতিটি সংস্করণের সাথে সামঞ্জস্যপূর্ণ উদাহরণগুলি (যখন পার্থক্য আছে)।

উদাহরণস্বরূপ, "Python 3.6+" মানে এটি Python 3.6 বা তার উপরে সামঞ্জস্যপূর্ণ (যার মধ্যে 3.7, 3.8, 3.9, 3.10, ইত্যাদি অন্তর্ভুক্ত)। এবং "Python 3.9+" মানে এটি Python 3.9 বা তার উপরে সামঞ্জস্যপূর্ণ (যার মধ্যে 3.10, ইত্যাদি অন্তর্ভুক্ত)।

যদি আপনি Python-এর সর্বশেষ সংস্করণগুলি ব্যবহার করতে পারেন, তাহলে সর্বশেষ সংস্করণের জন্য উদাহরণগুলি ব্যবহার করুন, সেগুলি আপনাকে সর্বোত্তম এবং সহজতম সিনট্যাক্স প্রদান করবে, যেমন, "Python 3.10+"।

লিস্ট

উদাহরণস্বরূপ, একটি ভেরিয়েবলকে str-এর একটি list হিসেবে সংজ্ঞায়িত করা যাক।

ভেরিয়েবলটি ঘোষণা করুন, একই কোলন (:) সিনট্যাক্স ব্যবহার করে।

টাইপ হিসেবে, list ব্যবহার করুন।

যেহেতু লিস্ট এমন একটি টাইপ যা অভ্যন্তরীণ টাইপগুলি ধারণ করে, আপনি তাদের স্কোয়ার ব্রাকেটের ভিতরে ব্যবহার করুন:

def process_items(items: list[str]):
    for item in items:
        print(item)

typing থেকে List (বড় হাতের L দিয়ে) ইমপোর্ট করুন:

from typing import List


def process_items(items: List[str]):
    for item in items:
        print(item)

ভেরিয়েবলটি ঘোষণা করুন, একই কোলন (:) সিনট্যাক্স ব্যবহার করে।

টাইপ হিসেবে, typing থেকে আপনার ইম্পোর্ট করা List ব্যবহার করুন।

যেহেতু লিস্ট এমন একটি টাইপ যা অভ্যন্তরীণ টাইপগুলি ধারণ করে, আপনি তাদের স্কোয়ার ব্রাকেটের ভিতরে করুন:

from typing import List


def process_items(items: List[str]):
    for item in items:
        print(item)

Info

স্কোয়ার ব্রাকেট এর ভিতরে ব্যবহৃত এইসব অভন্তরীন টাইপগুলোকে "ইন্টারনাল টাইপ" বলে।

এই উদাহরণে, এটি হচ্ছে List(অথবা পাইথন ৩.৯ বা তার উপরের সংস্করণের ক্ষেত্রে list) এ পাস করা টাইপ প্যারামিটার।

এর অর্থ হচ্ছে: "ভেরিয়েবল items একটি list, এবং এই লিস্টের প্রতিটি আইটেম একটি str।"

Tip

যদি আপনি Python 3.9 বা তার উপরে ব্যবহার করেন, আপনার typing থেকে List আমদানি করতে হবে না, আপনি সাধারণ list ওই টাইপের পরিবর্তে ব্যবহার করতে পারেন।

এর মাধ্যমে, আপনার এডিটর লিস্ট থেকে আইটেম প্রসেস করার সময় সাপোর্ট প্রদান করতে পারবে:

টাইপগুলি ছাড়া, এটি করা প্রায় অসম্ভব।

লক্ষ্য করুন যে ভেরিয়েবল item হল items লিস্টের একটি এলিমেন্ট।

তবুও, এডিটর জানে যে এটি একটি str, এবং তার জন্য সাপোর্ট প্রদান করে।

টাপল এবং সেট

আপনি tuple এবং set ঘোষণা করার জন্য একই প্রক্রিয়া অনুসরণ করবেন:

def process_items(items_t: tuple[int, int, str], items_s: set[bytes]):
    return items_t, items_s
from typing import Set, Tuple


def process_items(items_t: Tuple[int, int, str], items_s: Set[bytes]):
    return items_t, items_s

এর মানে হল:

  • ভেরিয়েবল items_t হল একটি tuple যা ৩টি আইটেম ধারণ করে, একটি int, অন্য একটি int, এবং একটি str
  • ভেরিয়েবল items_s হল একটি set, এবং এর প্রতিটি আইটেম হল bytes টাইপের।

ডিক্ট

একটি dict সংজ্ঞায়িত করতে, আপনি ২টি টাইপ প্যারামিটার কমা দ্বারা পৃথক করে দেবেন।

প্রথম টাইপ প্যারামিটারটি হল dict-এর কীগুলির জন্য।

দ্বিতীয় টাইপ প্যারামিটারটি হল dict-এর মানগুলির জন্য:

def process_items(prices: dict[str, float]):
    for item_name, item_price in prices.items():
        print(item_name)
        print(item_price)
from typing import Dict


def process_items(prices: Dict[str, float]):
    for item_name, item_price in prices.items():
        print(item_name)
        print(item_price)

এর মানে হল:

  • ভেরিয়েবল prices হল একটি dict:
    • এই dict-এর কীগুলি হল str টাইপের (ধরা যাক, প্রতিটি আইটেমের নাম)।
    • এই dict-এর মানগুলি হল float টাইপের (ধরা যাক, প্রতিটি আইটেমের দাম)।

ইউনিয়ন

আপনি একটি ভেরিয়েবলকে এমনভাবে ঘোষণা করতে পারেন যেন তা একাধিক টাইপের হয়, উদাহরণস্বরূপ, একটি int অথবা str

Python 3.6 এবং তার উপরের সংস্করণগুলিতে (Python 3.10 অন্তর্ভুক্ত) আপনি typing থেকে Union টাইপ ব্যবহার করতে পারেন এবং স্কোয়ার ব্র্যাকেটের মধ্যে গ্রহণযোগ্য টাইপগুলি রাখতে পারেন।

Python 3.10-এ একটি নতুন সিনট্যাক্স আছে যেখানে আপনি সম্ভাব্য টাইপগুলিকে একটি ভার্টিকাল বার (|) দ্বারা পৃথক করতে পারেন।

def process_item(item: int | str):
    print(item)
from typing import Union


def process_item(item: Union[int, str]):
    print(item)

উভয় ক্ষেত্রেই এর মানে হল যে item হতে পারে একটি int অথবা str

সম্ভবত None

আপনি এমনভাবে ঘোষণা করতে পারেন যে একটি মান হতে পারে এক টাইপের, যেমন str, আবার এটি None-ও হতে পারে।

Python 3.6 এবং তার উপরের সংস্করণগুলিতে (Python 3.10 অনতর্ভুক্ত) আপনি typing মডিউল থেকে Optional ইমপোর্ট করে এটি ঘোষণা এবং ব্যবহার করতে পারেন।

from typing import Optional


def say_hi(name: Optional[str] = None):
    if name is not None:
        print(f"Hey {name}!")
    else:
        print("Hello World")

Optional[str] ব্যবহার করা মানে হল শুধু str নয়, এটি হতে পারে None-ও, যা আপনার এডিটরকে সেই ত্রুটিগুলি শনাক্ত করতে সাহায্য করবে যেখানে আপনি ধরে নিচ্ছেন যে একটি মান সবসময় str হবে, অথচ এটি None-ও হতে পারেও।

Optional[Something] মূলত Union[Something, None]-এর একটি শর্টকাট, এবং তারা সমতুল্য।

এর মানে হল, Python 3.10-এ, আপনি টাইপগুলির ইউনিয়ন ঘোষণা করতে Something | None ব্যবহার করতে পারেন:

def say_hi(name: str | None = None):
    if name is not None:
        print(f"Hey {name}!")
    else:
        print("Hello World")
from typing import Optional


def say_hi(name: Optional[str] = None):
    if name is not None:
        print(f"Hey {name}!")
    else:
        print("Hello World")
from typing import Union


def say_hi(name: Union[str, None] = None):
    if name is not None:
        print(f"Hey {name}!")
    else:
        print("Hello World")

Union বা Optional ব্যবহার

যদি আপনি Python 3.10-এর নীচের সংস্করণ ব্যবহার করেন, তবে এখানে আমার খুবই ব্যক্তিগত দৃষ্টিভঙ্গি থেকে একটি টিপস:

  • 🚨 Optional[SomeType] ব্যবহার এড়িয়ে চলুন।
  • এর পরিবর্তে ✨ Union[SomeType, None] ব্যবহার করুন ✨।

উভয়ই সমতুল্য এবং মূলে একই, কিন্তু আমি Union-এর পক্ষে সুপারিশ করব কারণ "অপশনাল" শব্দটি মনে হতে পারে যে মানটি ঐচ্ছিক,অথচ এটি আসলে মানে "এটি হতে পারে None", এমনকি যদি এটি ঐচ্ছিক না হয়েও আবশ্যিক হয়।

আমি মনে করি Union[SomeType, None] এর অর্থ আরও স্পষ্টভাবে প্রকাশ করে।

এটি কেবল শব্দ এবং নামের ব্যাপার। কিন্তু সেই শব্দগুলি আপনি এবং আপনার সহকর্মীরা কোড সম্পর্কে কীভাবে চিন্তা করেন তা প্রভাবিত করতে পারে।

একটি উদাহরণ হিসেবে, এই ফাংশনটি নিন:

from typing import Optional


def say_hi(name: Optional[str]):
    print(f"Hey {name}!")

name প্যারামিটারটি Optional[str] হিসেবে সংজ্ঞায়িত হয়েছে, কিন্তু এটি অপশনাল নয়, আপনি প্যারামিটার ছাড়া ফাংশনটি কল করতে পারবেন না:

say_hi()  # ওহ না, এটি একটি ত্রুটি নিক্ষেপ করবে! 😱

name প্যারামিটারটি এখনও আবশ্যিক (নন-অপশনাল) কারণ এটির কোনো ডিফল্ট মান নেই। তবুও, name এর মান হিসেবে None গ্রহণযোগ্য:

say_hi(name=None)  # এটি কাজ করে, None বৈধ 🎉

সুখবর হল, একবার আপনি Python 3.10 ব্যবহার করা শুরু করলে, আপনাকে এগুলোর ব্যাপারে আর চিন্তা করতে হবে না, যেহুতু আপনি | ব্যবহার করেই ইউনিয়ন ঘোষণা করতে পারবেন:

def say_hi(name: str | None):
    print(f"Hey {name}!")

এবং তারপর আপনাকে নামগুলি যেমন Optional এবং Union নিয়ে আর চিন্তা করতে হবে না। 😎

জেনেরিক টাইপস

স্কোয়ার ব্র্যাকেটে টাইপ প্যারামিটার নেওয়া এই টাইপগুলিকে জেনেরিক টাইপ বা জেনেরিকস বলা হয়, যেমন:

আপনি সেই একই বিল্টইন টাইপ জেনেরিক্স হিসেবে ব্যবহার করতে পারবেন(ভিতরে টাইপ সহ স্কয়ারে ব্রাকেট দিয়ে):

  • list
  • tuple
  • set
  • dict

এবং Python 3.8 এর মতোই, typing মডিউল থেকে:

  • Union
  • Optional (Python 3.8 এর মতোই)
  • ...এবং অন্যান্য।

Python 3.10-এ, Union এবং Optional জেনেরিকস ব্যবহার করার বিকল্প হিসেবে, আপনি টাইপগুলির ইউনিয়ন ঘোষণা করতে ভার্টিকাল বার (|) ব্যবহার করতে পারেন, যা ওদের থেকে অনেক ভালো এবং সহজ।

আপনি সেই একই বিল্টইন টাইপ জেনেরিক্স হিসেবে ব্যবহার করতে পারবেন(ভিতরে টাইপ সহ স্কয়ারে ব্রাকেট দিয়ে):

  • list
  • tuple
  • set
  • dict

এবং Python 3.8 এর মতোই, typing মডিউল থেকে:

  • Union
  • Optional
  • ...এবং অন্যান্য।
  • List
  • Tuple
  • Set
  • Dict
  • Union
  • Optional
  • ...এবং অন্যান্য।

ক্লাস হিসেবে টাইপস

আপনি একটি ভেরিয়েবলের টাইপ হিসেবে একটি ক্লাস ঘোষণা করতে পারেন।

ধরুন আপনার কাছে Person নামে একটি ক্লাস আছে, যার একটি নাম আছে:

class Person:
    def __init__(self, name: str):
        self.name = name


def get_person_name(one_person: Person):
    return one_person.name

তারপর আপনি একটি ভেরিয়েবলকে Person টাইপের হিসেবে ঘোষণা করতে পারেন:

class Person:
    def __init__(self, name: str):
        self.name = name


def get_person_name(one_person: Person):
    return one_person.name

এবং তারপর, আবার, আপনি এডিটর সাপোর্ট পেয়ে যাবেন:

লক্ষ্য করুন যে এর মানে হল "one_person হল ক্লাস Person-এর একটি ইন্সট্যান্স।"

এর মানে এটি নয় যে "one_person হল ক্লাস যাকে বলা হয় Person।"

Pydantic মডেল

Pydantic হল একটি Python লাইব্রেরি যা ডাটা ভ্যালিডেশন সম্পাদন করে।

আপনি ডাটার "আকার" এট্রিবিউট সহ ক্লাস হিসেবে ঘোষণা করেন।

এবং প্রতিটি এট্রিবিউট এর একটি টাইপ থাকে।

তারপর আপনি যদি কিছু মান দিয়ে সেই ক্লাসের একটি ইন্সট্যান্স তৈরি করেন-- এটি মানগুলিকে ভ্যালিডেট করবে, প্রয়োজন অনুযায়ী তাদেরকে উপযুক্ত টাইপে রূপান্তর করবে এবং আপনাকে সমস্ত ডাটা সহ একটি অবজেক্ট প্রদান করবে।

এবং আপনি সেই ফলাফল অবজেক্টের সাথে এডিটর সাপোর্ট পাবেন।

অফিসিয়াল Pydantic ডক্স থেকে একটি উদাহরণ:

from datetime import datetime

from pydantic import BaseModel


class User(BaseModel):
    id: int
    name: str = "John Doe"
    signup_ts: datetime | None = None
    friends: list[int] = []


external_data = {
    "id": "123",
    "signup_ts": "2017-06-01 12:22",
    "friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123
from datetime import datetime
from typing import Union

from pydantic import BaseModel


class User(BaseModel):
    id: int
    name: str = "John Doe"
    signup_ts: Union[datetime, None] = None
    friends: list[int] = []


external_data = {
    "id": "123",
    "signup_ts": "2017-06-01 12:22",
    "friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123
from datetime import datetime
from typing import List, Union

from pydantic import BaseModel


class User(BaseModel):
    id: int
    name: str = "John Doe"
    signup_ts: Union[datetime, None] = None
    friends: List[int] = []


external_data = {
    "id": "123",
    "signup_ts": "2017-06-01 12:22",
    "friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123

FastAPI মূলত Pydantic-এর উপর নির্মিত।

আপনি এই সমস্ত কিছুর অনেক বাস্তবসম্মত উদাহরণ পাবেন টিউটোরিয়াল - ইউজার গাইডে

Tip

যখন আপনি Optional বা Union[Something, None] ব্যবহার করেন এবং কোনো ডিফল্ট মান না থাকে, Pydantic-এর একটি বিশেষ আচরণ রয়েছে, আপনি Pydantic ডকুমেন্টেশনে Required Optional fields সম্পর্কে আরও পড়তে পারেন।

মেটাডাটা অ্যানোটেশন সহ টাইপ হিন্টস

Python-এ এমন একটি ফিচার আছে যা Annotated ব্যবহার করে এই টাইপ হিন্টগুলিতে অতিরিক্ত মেটাডাটা রাখতে দেয়।

Python 3.9-এ, Annotated স্ট্যান্ডার্ড লাইব্রেরিতে অন্তর্ভুক্ত, তাই আপনি এটি typing থেকে ইমপোর্ট করতে পারেন।

from typing import Annotated


def say_hello(name: Annotated[str, "this is just metadata"]) -> str:
    return f"Hello {name}"

Python 3.9-এর নীচের সংস্করণগুলিতে, আপনি Annotated-কে typing_extensions থেকে ইমপোর্ট করেন।

এটি FastAPI এর সাথে ইতিমদ্ধে ইনস্টল হয়ে থাকবে।

from typing_extensions import Annotated


def say_hello(name: Annotated[str, "this is just metadata"]) -> str:
    return f"Hello {name}"

Python নিজে এই Annotated দিয়ে কিছুই করে না। এবং এডিটর এবং অন্যান্য টুলগুলির জন্য, টাইপটি এখনও str

কিন্তু আপনি এই Annotated এর মধ্যকার জায়গাটির মধ্যে FastAPI-এ কীভাবে আপনার অ্যাপ্লিকেশন আচরণ করুক তা সম্পর্কে অতিরিক্ত মেটাডাটা প্রদান করার জন্য ব্যবহার করতে পারেন।

মনে রাখার গুরুত্বপূর্ণ বিষয় হল যে প্রথম টাইপ প্যারামিটার আপনি Annotated-এ পাস করেন সেটি হল আসল টাইপ। বাকি শুধুমাত্র অন্যান্য টুলগুলির জন্য মেটাডাটা।

এখন আপনার কেবল জানা প্রয়োজন যে Annotated বিদ্যমান, এবং এটি স্ট্যান্ডার্ড Python। 😎

পরবর্তীতে আপনি দেখবেন এটি কতটা শক্তিশালী হতে পারে।

Tip

এটি স্ট্যান্ডার্ড Python হওয়ার মানে হল আপনি আপনার এডিটরে, আপনি যে টুলগুলি কোড বিশ্লেষণ এবং রিফ্যাক্টর করার জন্য ব্যবহার করেন তাতে সেরা সম্ভাব্য ডেভেলপার এক্সপেরিয়েন্স পাবেন। ✨

এবং এছাড়াও আপনার কোড অন্যান্য অনেক Python টুল এবং লাইব্রেরিগুলির সাথে খুব সামঞ্জস্যপূর্ণ হবে। 🚀

FastAPI-এ টাইপ হিন্টস

FastAPI এই টাইপ হিন্টগুলি ব্যবহার করে বেশ কিছু জিনিস করে।

FastAPI-এ আপনি টাইপ হিন্টগুলি সহ প্যারামিটার ঘোষণা করেন এবং আপনি পান:

  • এডিটর সাপোর্ট
  • টাইপচেক

...এবং FastAPI একই ঘোষণাগুলি ব্যবহার করে:

  • রিকুইরেমেন্টস সংজ্ঞায়িত করে: রিকোয়েস্ট পাথ প্যারামিটার, কুয়েরি প্যারামিটার, হেডার, বডি, ডিপেন্ডেন্সিস, ইত্যাদি থেকে।
  • ডেটা রূপান্তর করে: রিকোয়েস্ট থেকে প্রয়োজনীয় টাইপে ডেটা।
  • ডেটা যাচাই করে: প্রতিটি রিকোয়েস্ট থেকে আসা ডেটা:
    • যখন ডেটা অবৈধ হয় তখন স্বয়ংক্রিয় ত্রুটি গ্রাহকের কাছে ফেরত পাঠানো।
  • API ডকুমেন্টেশন তৈরি করে: OpenAPI ব্যবহার করে:
    • যা স্বয়ংক্রিয় ইন্টার‌্যাক্টিভ ডকুমেন্টেশন ইউজার ইন্টারফেস দ্বারা ব্যবহৃত হয়।

এই সব কিছু আপনার কাছে অস্পষ্ট মনে হতে পারে। চিন্তা করবেন না। আপনি টিউটোরিয়াল - ইউজার গাইড এ এই সব কিছু প্র্যাকটিসে দেখতে পাবেন।

গুরুত্বপূর্ণ বিষয় হল, আপনি যদি স্ট্যান্ডার্ড Python টাইপগুলি ব্যবহার করেন, তবে আরও বেশি ক্লাস, ডেকোরেটর ইত্যাদি যোগ না করেই একই স্থানে FastAPI আপনার অনেক কাজ করে দিবে।

Info

যদি আপনি টিউটোরিয়ালের সমস্ত বিষয় পড়ে ফেলে থাকেন এবং টাইপ সম্পর্কে আরও জানতে চান, তবে একটি ভালো রিসোর্স হল mypy এর "cheat sheet"। এই "cheat sheet" এ আপনি Python টাইপ হিন্ট সম্পর্কে বেসিক থেকে উন্নত লেভেলের ধারণা পেতে পারেন, যা আপনার কোডে টাইপ সেফটি এবং স্পষ্টতা বাড়াতে সাহায্য করবে।