পাইথন চিট শিট: জাভা ডেভেলপারের চোখে পাইথন: তফাৎ, নতুন বৈশিষ্ট বা ফিচার - ২

পাইথন চিট শিট: জাভা ডেভেলপারের চোখে পাইথন: তফাৎ, নতুন বৈশিষ্ট বা ফিচার - ২
১৩ ডিসেম্বর, বৃহস্পতিবার, ২০১৮


আমেরিকায় ইউনিভার্সিটি গুলোতে বিভিন্ন কোর্স ফাইনালে বৈধ উপায়ে নকল করার একটা খুব ভালো ব্যবস্থা আছে - চিট শিট (Cheat Sheet) । সাধারণত A4 সাইজের একটা সাদা কাগজে (প্রিন্টার পেপার) দুই পাশেই হাতে লিখে যত ইচ্ছা নোট করে আনা যায়। সব কোর্সে অবশ্য এটা সম্ভব না।  এটা কোর্সের প্রফেসরের উপর নির্ভর করে। কিছু কিছু ছাত্র-ছাত্রীরা বিভিন্ন রঙের পেন্সিলে কুটি কুটি অক্ষরে পারলে পুরো বই লিখে নিয়ে আসে।  প্রথমে শুনতে অবাক আর অবিশ্বাস্য লাগলেও একটু ভেবে দেখলে কিন্তু এই চিট শিটের উপকারিতা আর প্রয়োজনীয়তা বোঝা যায়।  ভেবে দেখুন, একটা কোর্সের সব ফর্মুলা, সূত্র কিংবা ডেফিনিশন মুখস্ত করে মাথা ভরিয়ে তুলে তো আসলে লাভ নেই, ফর্মুলা বা সূত্র ব্যবহার করে সমস্যার সমাধান করতে পারাটাই আসল, তাই না? তাছাড়া, এই চিট শিট লিখতে গিয়ে ছাত্র-ছাত্রীরা যে পরিমান পড়াশুনা করবে, তাতে কোর্সের একটা খুব ভালো রিভিউ হয়ে যায় আর ভবিষ্যতেও এই চিট শিট একটা ভালো রেফারেন্স হিসাবে থাকতে পারে।


যাই হোক, আসল কথায় আসি। আমি এই সেমিস্টারে পাইথনের উপর যে দুটো কোর্স পড়িয়েছি (দুটোতেই ফাইনালে চিট শিটের ব্যবহারের অনুমতি ছিল) - মোটামুটি নিজে পড়ে তারপর পড়িয়েছি।  আমি এর আগে জাভাতে কাজ করলেও পাইথনে এই প্রথম কিছু করলাম। আমার দৃষ্টিতে জাভা আর পাইথনের যে তফাৎ গুলো চোখে পড়েছে তার উপর এর আগের এক লেখায় লিখেছি।  কিন্তু এখন কোর্স শেষ করার পর ভাবছিলাম নিজের জন্য পাইথনের উপর একটা চিট শিট লিখে রাখবো। কেননা যেকোনো প্রোগ্রামিং লাঙ্গুয়েজেই ছোট ছোট কিছু বিষয় আছে যেগুলো সবসময় কোডিং না করলে খুব সহজেই ভুলে যাওয়া যায়। নিচে পাইথনের তেমন কয়েকটা উদাহরণ দেই:
  • পাইথনে সেট ব্যবহার করা হয় এইভাবে: mySet = {1, 'Hello', 2, True}. কিন্তু তাই বলে একটা খালি বা Empty সেট কিন্তু mySet = {} এইভাবে লিখলে হবে না।  এটা একটা ডিকশনারি হয়ে যাবে। খালি বা এম্পটি সেট বানাতে লিখতে হবে mySet = set() [খেয়াল করুন Set() কিন্তু না]
  • সেট থেকে কোনো একটা আইটেম রিমুভ করার সময় খুব সাবধানে করতে হয়। সেট এ নেই এমন কোনো আইটেম রিমুভ করতে গেলে কিন্তু এরর হবে, নিরাপদ হচ্ছে discard ফাংশন ব্যবহার করা। যেমন :
                  mySet = {1, 2}
                  mySet.remove(2) # This is okay
                  mySet.remove(3) # This will get KeyError
                  mySet.discard(3) # This will be okay, no errors

  • পাইথন ডিকশনারিতে add বলে কোনো ফাংশন নেই। কোনো কী-ভ্যালু অ্যাড করতে চাইলে এভাবে লিখতে হবে: myDict[newKey] = newValue 
  • পাইথনে লিস্ট স্লাইসিং [List Slicing] ব্যাপারটা খুবই মজার। যেমন, নিচের লিস্ট থেকে প্রথম দুইটা আইটেম নেয়ার জন্য এভাবে লিখলেও চলবে: 
                aList = ['one', 'two', 'three', 'four', 'five']
                first_two = aList[:2]

  • লিস্ট স্লাইসিং-এর যে বিষয়টা প্রায়ই আমার ভুল হয়: alist[firstIndex, secondIndex] লিস্ট স্লাইসিং -এ secondIndex - আইটেমটা ইনক্লুডেড হবে না, এর আগেরটা পর্যন্ত হবে।  অর্থাৎ aList[:2], শুরু থেকে ইনডেক্স ১ পর্যন্ত আইটেম গুলো নিবে। অর্থাৎ 0, 1 পজিশনের ২ টা আইটেম নিবে। কিছু উল্লেখ না থাকলে শুরু/শেষ থেকে ধরে নিতে হবে। একই ভাবে range(5) ফাংশন 0, 1, 2, 3, 4 পর্যন্ত ভ্যালু দিবে, 5 দিবে না।  
  • স্ট্রিং তৈরি করার জন্য index ভিত্তিক format : full_name = "{0} {1}".format('Ishtiaque', 'Hussain')
  • পাইথন ক্লাস ডিক্লারেশনে সবগুলো ফাংশনে প্রথম আর্গুমেন্ট self হতে হবে, নাহলে কাজ করবে না। 
  • পাইথন ক্লাসের ভেতর কোনো এট্রিবিউট ভ্যারিয়েবল এক্সেস করতে হলে self. দিয়ে প্রিপেন্ড করতে হবে, অর্থাৎ self.attributeName - আকারে লিখতে হবে।  
  • পাইথন ক্লাস অন্য কোনো প্যারেন্ট ক্লাস থেকে ইনহেরিট করতে চাইলে প্যারেন্ট ক্লাস পারেনথেসিস-এর মধ্যে দিতে হবে। যেমন,  class ChildDog(ParentDog):
খুঁজলে এরকম আরো অনেক ছোট ছোট বিষয় পাওয়া যাবে যেইগুলো দরকারের সময় মনে করা খুবই ঝামেলার। তখন সাধারণত গুগলই ভরসা। কিন্তু একটা চিট শিট তৈরি করা থাকলে চট করে দেখে নেয়া যায় আর মাঝে মাঝে অবসরে চোখ বুলিয়ে নিলে অনেক কিছূই ঝালাই হয়ে যায়।

এরকম একটা শিট বানাতে বসার আগে ভাবলাম একটু গুগলে সার্চ করে দেখা যাক কেউ অলরেডি করে রেখেছে কীনা।  ভাগ্যিস করেছিলাম, আমি যেই বই ক্লাসে পড়াচ্ছি (Python Crash Course - By Eric Matthes), সেই বইয়ের লেখকই একটা পাইথন চিট শিট তৈরী করে রেখেছেন। ভদ্রলোককে মনে মনে আরেকবার বাহবা আর দোয়া দিয়ে পিডিএফ টা সেভ করা রাখলাম - কাজের জিনিস! আমার স্টুডেন্টদের সাথে লিংকটা শেয়ার করার পাশাপাশি একটা ব্লগ পোস্ট লেখার লোভটাও সামলাতে পারলাম না। আকারে ছোট আরেকটা ভালো চিট শিট এই লিংকে পাওয়া যাবে। আরো ভালো কোনো লিংক কারো জানা থাকলে বরাবরের মতোই অনুরোধ থাকলো কমেন্টে জানানোর । ধন্যবাদ।

আপডেট: নতুন কিছু শিখলে নিচে লিখে রাখবো:
  • Python Object-Oriented Programming (OOP)'র উপর খুব ভালো একটা YouTube প্লেলিস্ট: এই লিংকে 
  • কোনো String/list -এর প্রতিটা আইটেম for লুপ দিয়ে ইটারেট করার সময় তার index -ও জানার দরকার হলে পাইথনে enumarate ফাংশন ব্যবহার করা যায়। eunmarate ফাংশনে আবার স্টার্টিং কাউন্টার ভ্যালুও দিয়ে দেয়া যায়। নিচের উদাহরণ এই লিংক থেকে নেয়া।  আর Codewars -এ enumerate ব্যবহার করে সল্ভ করা একটা প্রবলেম এই লিংকে।  
my_list = ['apple', 'banana', 'grapes', 'pear']
for c, value in enumerate(my_list, 1):
    print(c, value)

# Output:
# 1 apple
# 2 banana
# 3 grapes
# 4 pear
আরেকটা সহজ উপায় হচ্ছে, range ফাংশন ব্যবহার করা।
for i in range(len(my_list)):
     print (i, my_list[i])
  • print('' or 'Ishti') কিংবা print(None, 'Ishti) দুইটাই 'Ishti' প্রিন্ট করবে! পাইথনে লজিকাল অপারেশন ছাড়াও লজিকাল 'ওর' (or) ব্যবহার করা যায়। উপরের print ফাংশন দুইক্ষেত্রেই প্রথম অংশে কোনো ভ্যালু না পেয়ে or -এর পরের অংশ প্রিন্ট করবে!!
  • পাইথন ৩ -এ ডিকশনারির ভ্যালু কিংবা কী গুলো myDict.values() বা myDict.keys() ব্যবহার করে পাওয়া গেলেও আসলে তা একটা লিস্ট নয়, বরঞ্চ একটা view আকারে আসে। এই view ইটারেট করা গেলেও index দিয়ে access করা যায় না। লিস্ট আকারে পেতে চাইলে এভাবে লিখতে হবে: list(myDict.values()) 
  • 'bla'.join(aList): এইখানে aList এম্পটি হলে join অপারেশন এম্পটি স্ট্রিং আর aList -এ একটা আইটেম থাকলে শুধু সেই আইটেমটা রিটার্ন করবে। 'bla' -র কোনো ভূমিকা থাকবে না। [CodeWars রেফারেন্স প্রবলেম এই লিংকে]।
  • rstip() ডিফল্ট হিসাবে ডান পাশ থেকে হোয়াইটস্পেস রিমুভ করে। কিন্তু বলে দিলে অন্য ক্যারেক্টারও রিমুভ করতে পারে। যেমন aStr = this_is_a_string12345 -এই স্ট্রিং এর জন্য নিচের কোড 'this_is_a_string' রিটার্ন করবে: . 
    • return aStr.rstrip('1234567890')
    • রেগুলার এক্সপ্রেশন দিয়েও একই কাজ করা যায় return re.search("(\d*)$", aStr)
  • str.zfill(width) - str -এর বাম পাশে ০ (জিরো) দিয়ে ফিলআপ করে দিবে। ফাইনাল লেংথ হবে width -এর সমান। যেমন: '513'.zfill(4) => '0513' দিবে। [ CodeWars রেফারেন্স প্রবলেম
  • লিস্ট কম্প্রিহেনশন-এ 'if ' - 'else' র ব্যবহার:
    • [f(x) if condition else g(x) for x in sequence]
      And, for list comprehensions with if conditions only,
      [f(x) for x in sequence if condition]
  • দুটি ভ্যালু (val1, val2) -র মধ্যে কোনটি বড় কিংবা সমান (=), তা বের করার ১ লাইনের কোড:
    • which = "1" if val1 > val2 else "2" if val2 > val1 else "="
  • পাইথনে মাল্টিপল এসাইনমেন্ট সম্ভব। যেমন: 
a, b, c = 1, 2, 3
my_list = [1, 2, 3]
a, b, c = my_list      # this will assign 1, 2 and 3 to a, b and c variables

a = 'AAA'
b = 'BBB'
a, b = b, a              # this will swap the values 
  • লিস্টে ইটারেট করার সময় তা মোডিফাই করা যায়।  যেমন নিচের কোড ১ থেকে শুরু করে সংখ্যা প্রিন্ট করতেই থাকবে, কেননা প্রতি লুপে লিস্টে পরের সংখ্যাটা যোগ হচ্ছে :
myList = [1]
for x in myList:
    print(x)
    myList.append(x+1)

  • লিস্টে কোনো ইনডেক্স -এ যেমন কোনো আইটেম এসাইন করা যায়, একই ভাবে লিস্টের স্লাইসেও নতুন লিস্ট (কয়েকটা আইটেম) দিয়ে আপডেট করা যায়!
animals = ['cat', 'dog', 'bat']
animals[1:3] = ['Horse', 'Cow', 'Sheep']
print(animals)
>> ['cat', 'Horse', 'Cow', 'Sheep']  
  • ডিকশনারিতে get মেথড যেমনি (e.g., my_dict.get(key, 'I did not find it')) কোনো কী থাকলে ডিফল্ট ভ্যালু রিটার্ন করতে পারে তেমনি setdefault মেথড কোনো মিসিং কী'র জন্য  ডিফল্ট কী-ভ্যালু পেয়ার অ্যাড করতে পারে। যেমন: my_dict.setdefault('a', 0). যদি 'a' কী অলরেডি ডিকশনারি না থাকে, তবে এই কোড 'a' -র জন্য ডিফল্ট  0 ভ্যালু অ্যাড করে দিবে।  
  • পাইথনে ডিকশনারি unordered ডাটা স্ট্রাকচার।  কী-ভ্যালু অর্ডার মেনে ডিকশেনারী তে ইন্সর্টেড হয় না। কাজেই নিচের দুইটি ডিকশনারি আসলে একই।  
>>> aDict = {'a' : 1, 'b' : 2, 'c' : 3} 
>>> bDict = {'b' : 2, 'c' : 3, 'a' : 1}
>>> aDict == bDict
>>> True
  • ধরা যাক, কোন বিরাট একটা টেক্সটকে String আকারে কোনো variable -এ রাখতে চাই।  সেই টেক্সটে (যেমন: It's Sunday and Izyan screamed "It's holiday today!".) যদি সিঙ্গেল বা ডাবল কোটেশন মার্ক থাকে, তাহলে কিভাবে সেভ করবো? উত্তর: মাল্টিলাইন স্ট্রিং বা ট্রিপল সিঙ্গেল/ডাবল কোটেশন মার্ক যেমন : '''It's Sunday and Izyan screamed "It's holiday today!".'''
  • ফাইল পাথ সেপারেটর Windows -এ '\' কিন্তু Linux  কিংবা MacOS -এ '/'. কোনো ফাইলের অ্যাবসলিউট পাথ তাহলে কিভাবে লিখবো যেন যেকোন OS -এই আমার কোড কাজ করে? নিচের কোডের মতো করে os ইম্পোর্ট করে তার join ফাঙ্কশন ব্যবহার করলে OS - ইন্ডিপেন্ডেন্ট (যে মেশিনে রান করা হচ্ছে, সেই মেশিনের ফাইল পাথ সেপারেটর ব্যবহার করে) ফাইল পাথ তৈরী হবে.
>>> import os
>>> os.path.join('folder1', 'folder2', 'folder3')
>>> 'folder1\\folder2\\folder3'  # for a Windows machine
>>> 'folder1/folder2/folder3'   # for a MacOS or Linux machine.
  • Python OOP  কন্সেপ্টস বোঝার জন্য খুব ভালো কিছু ভিডিও এই লিঙ্কে 
  • tuple immutable বলে dictionary তে key হিসাবে ব্যবহার করা যায়!
Many times, a tuple is used in combination with a dictionary, for example, a tuple might represent a key, because it's immutable.


  • sorted(list, key = Func): sorted ফাংশন মূল লিস্টকে পরিবর্তন না করেই sort করে, এবং key হিসাবে অপশনাল ফাংশন নিতে পারে। বিস্তারিত এই লিংকে পাওয়া যাবে। যেমন, আইটেমের লেংথ হিসাবে কোনো লিস্ট sort করতে চাইলে:
              strs = ['ccc', 'aaaa', 'd', 'bb']
       print sorted(strs, key=len)  ## ['d', 'bb', 'ccc', 'aaaa']
       strs = ['aa', 'CC', 'zz', 'BB']  
       print sorted(strs, key=str.lower)  ## ['aa', 'BB', 'CC', 'zz']
  • map(func, iterable) আর filter(func, iterable) দুটো ফাঙ্কশন যা কিনা iterable 'র প্রতিটা আইটেমকে প্যারামিটার হিসাবে পাস করিয়ে func কল করবে। map() শুধু এপলাই করে, আর filter এপলাই করে ম্যাচিং আইটেম রিটার্ন করে। যেমন: 
    def add_five(x):
    return x + 5

    nums = [11, 22, 33, 44, 55]
    result = list(map(add_five, nums))
    print(result)

    
    
    #আউটপুট 
    [16, 27, 38, 49, 60]

    nums = [11, 22, 33, 44, 55]
    res = list(filter(lambda x: x%2==0, nums))
    print(res)
  • #আউটপুট 
[11, 22, 44]


2 comments:

কাজের জায়গায় ভুল থেকে শেখা: regex 'র একটা খুব কমন বিষয় যেটা এতদিন ভুল জানতাম

কাজের জায়গায় ভুল থেকে শেখা: regex 'র একটা খুব কমন বিষয় যেটা এতদিন ভুল জানতাম  ৩ ফেব্রুয়ারি, শনিবার, ২০২৪ রেগুলার এক্সপ্রেশন (Regular Exp...