মূল content-এ যাও

Python for AI/Functions, Modules ও Packages/Lesson 16

Default, *args ও **kwargs

Function-কে flexible বানাও — default আর keyword argument, যত খুশি argument নেওয়া (*args, **kwargs), আর mutable default-এর বিখ্যাত ফাঁদ।

সময়
22 মিনিট
Exercise
1
Challenge
1
Quiz
3 প্রশ্ন

সহজ ভাষায়

এখন পর্যন্ত আমাদের function নির্দিষ্ট সংখ্যক argument নিত। কিন্তু print() দেখো — যতগুলো খুশি জিনিস দেওয়া যায়, আবার sep=", "-এর মতো ঐচ্ছিক setting-ও দেওয়া যায়:

main.py

আজ শিখব কীভাবে নিজের function-কে এমন flexible বানানো যায়।

কেন দরকার?

ML library-গুলোর function-এ প্রচুর setting থাকে, কিন্তু বেশিরভাগের একটা ভালো default আছে:

main.py

scikit-learn-এর RandomForestClassifier-এ ২০টার বেশি parameter আছে — কিন্তু তুমি শুধু যেটা বদলাতে চাও সেটাই দাও। এই design সম্ভব হয় default আর keyword argument দিয়ে।

Positional বনাম Keyword argument

main.py
  • Positional — position (ক্রম) অনুযায়ী মেলে।
  • Keyword — নাম ধরে দেওয়া, ক্রম যা খুশি।

Keyword argument code-কে পড়া সহজ করে: train("resnet", 50, 0.01) দেখে বোঝা কঠিন কোন সংখ্যা কী, কিন্তু train("resnet", epochs=50, learning_rate=0.01) নিজেই নিজেকে ব্যাখ্যা করে।

*args: যত খুশি positional argument

Parameter-এর আগে * দিলে বাড়তি সব positional argument একটা tuple-এ জমা হয়:

main.py

নাম args হওয়া বাধ্যতামূলক না — * চিহ্নটাই আসল। কিন্তু কিছু না বোঝাতে convention হলো *args।

**kwargs: যত খুশি keyword argument

** দিলে বাড়তি সব keyword argument একটা dictionary-তে জমা হয়:

main.py

Unpacking: উল্টো দিকে * আর **

Function ডাকার সময় * আর ** উল্টো কাজ করে — list/dict খুলে আলাদা argument বানায়:

main.py

Real project-এ config file (JSON/YAML) থেকে dictionary পড়ে **config দিয়ে function-এ পাঠানো খুব common pattern।

Keyword-only argument

*args-এর পরে যেসব parameter থাকে, সেগুলো শুধু নাম ধরে দেওয়া যায়:

main.py

শেষ লাইনে "-" আরেকটা word হিসেবে গেছে, sep হয়নি — ঠিক এটাই চাই।

সাবধান: mutable default-এর ফাঁদ

Python-এর সবচেয়ে বিখ্যাত ফাঁদগুলোর একটা:

main.py

দ্বিতীয় call-এ [75] আশা করেছিলাম, কিন্তু এসেছে [90, 75]! Default মান [] একবারই তৈরি হয় — function define করার সময় — তারপর সব call সেই একই list ব্যবহার করে।

সঠিক উপায় — default হিসেবে None, ভেতরে নতুন list:

main.py

নিয়ম: default মান হিসেবে কখনো list, dict বা set দিও না। None দাও।

Exercise

Exercise

যতগুলো খুশি সংখ্যার গড়

+20 XP

average(*numbers) function লেখো যেটা যতগুলো খুশি সংখ্যা নিতে পারে এবং তাদের গড় return করে।

কোনো সংখ্যা না দিলে (average()) 0 return করবে।

solution.py

Quiz

  1. Q1def f(a, b=2, *args, **kwargs) — f(1, 5, 7, 9, x=3) ডাকলে args কী?
  2. Q2**kwargs-এর type কী?
  3. Q3নিচের code-এর output কী?
    def add(item, bag=[]):
        bag.append(item)
        return bag
    
    add("a")
    print(add("b"))
    
0/3 answered

Challenge

Challenge

নিজের log() function

+50 XP

log() function লেখো যেটা যতগুলো খুশি message নেয় এবং একটা string return করে:

  • message-গুলো sep দিয়ে জোড়া (default একটা space)
  • সামনে [LEVEL] — level-এর default "INFO"
  • sep আর level শুধু নাম ধরে দেওয়া যাবে (keyword-only)

যেমন log("epoch", 3, "done") → "[INFO] epoch 3 done" আর log("loss", 0.5, sep="=", level="DEBUG") → "[DEBUG] loss=0.5"।

solution.py

বাস্তবে কোথায় ব্যবহার হয়?

Wrapper function — অন্য একটা function-কে ডাকার আগে-পরে কিছু করা, কিন্তু argument যা আসে সব হুবহু পাঠিয়ে দেওয়া। *args, **kwargs ছাড়া এটা লেখা অসম্ভব:

main.py

PyTorch-এর nn.Module, Hugging Face-এর from_pretrained(...) — সবখানে **kwargs দিয়ে setting পাস করা হয়। পরে decorator শিখলে এই pattern আরও শক্তিশালী হবে।

Interview প্রশ্ন

  • Beginner: *args আর **kwargs কী? এদের type কী?
  • Intermediate: Mutable default argument কেন সমস্যা? কীভাবে ঠিক করবে?
  • Advanced: Parameter list-এ / আর * আলাদাভাবে (যেমন def f(a, /, b, *, c)) কী বোঝায়? (/-এর আগেরগুলো positional-only, *-এর পরেরগুলো keyword-only।)

এরপর কী?

Function-কে আমরা এক জায়গায় define করে আরেক জায়গায় ডাকছি। কিন্তু function নিজেও একটা value — variable-এ রাখা যায়, অন্য function-এ পাঠানো যায়। পরের lesson: Lambda, map ও filter।