Python নিচের মৌলিক তুলনা অপারেটরগুলো সাপোর্ট করে:
| অপারেটর | অপারেশন | বিবরণ |
|---|---|---|
> |
"এর চেয়ে বড়" |
a > b হলো True যদি মানের দিক থেকে a, b-এর চেয়ে কঠোরভাবে বড় হয় |
< |
"এর চেয়ে ছোট" |
a < b হলো True যদি মানের দিক থেকে a, b-এর চেয়ে কঠোরভাবে ছোট হয় |
== |
"সমান" |
a == b হলো True যদি মানের দিক থেকে a, b-এর কঠোরভাবে সমান হয় |
>= |
"এর চেয়ে বড় বা সমান" |
a >= b হলো True যদি মানের দিক থেকে a > b অথবা a == b হয় |
<= |
"এর চেয়ে ছোট বা সমান" |
a <= b হলো True যদি মানের দিক থেকে a < b অথবা a == b হয় |
!= |
"সমান নয়" |
a != b হলো True যদি a == b হয় False
|
is |
"আইডেন্টিটি" |
a is b হলো True যদি এবং কেবল যদি a আর b একই অবজেক্ট হয় |
is not |
"নেগেটেড আইডেন্টিটি" |
a is not b হলো True যদি a আর b একই অবজেক্ট না হয় |
in |
"কন্টেইনমেন্ট টেস্ট" |
a in b হলো True যদি a, b-এর মেম্বার, সাবসেট বা এলিমেন্ট হয় |
not in |
"নেগেটেড কন্টেইনমেন্ট টেস্ট" |
a not in b হলো True যদি a, b-এর মেম্বার, সাবসেট বা এলিমেন্ট না হয় |
এদের সবার প্রায়োরিটি একই (যা বুলিয়ান অপারেশন-এর চেয়ে বেশি, কিন্তু অ্যারিথমেটিক বা বিটওয়াইজ অপারেশনের চেয়ে কম)।
ভিন্ন টাইপের অবজেক্ট (সংখ্যাসূচক টাইপগুলো ছাড়া) ডিফল্টভাবে কখনোই সমান হিসেবে গণ্য হয় না।
একটি class-এর অভিন্ন নয় এমন ইনস্ট্যান্সও সমান হিসেবে না-ই গণ্য হয়, যদি না class-টি এমন বিশেষ রিচ কম্প্যারিজন মেথড ডিফাইন করে যা ডিফল্ট object তুলনার আচরণ কাস্টমাইজ করে।
rich comparisons দিয়ে কাস্টমাইজ করার বিষয়টি পরের একটি অনুশীলনীতে আলোচনা করা হবে।
এই বিষয়ে (অনেক) বেশি বিস্তারিত জানতে Python ডকুমেন্টেশনের মানের তুলনা দেখুন।
সংখ্যাসূচক টাইপগুলো এই টাইপ মেলানোর নিয়মের (বেশিরভাগ ক্ষেত্রেই) একটি ব্যতিক্রম।
একটি integer-কে একটি float-এর সমান ধরা যেতে পারে (বা একটি octal-কে একটি hexadecimal-এর সমান), যতক্ষণ টাইপগুলোকে তুলনার জন্য ইমপ্লিসিটভাবে কনভার্ট করা যায়।
Python স্ট্যান্ডার্ড লাইব্রেরির বাকি সংখ্যাসূচক টাইপগুলোর (complex, decimal, fractions) জন্য তুলনা অপারেটরগুলো সেখানে ডিফাইন করা, যেখানে তারা "অর্থবহ" (যেখানে ইমপ্লিসিট কনভার্সন ফলাফল বদলায় না), কিন্তু তুলনার জন্য অন্তর্নিহিত অবজেক্টগুলোকে নির্ভুলভাবে কনভার্ট করা না গেলে একটি TypeError থ্রো করে।
Python সংখ্যাসূচক কনভার্সনে যে নিয়মগুলো ব্যবহার করে সে সম্পর্কে আরও জানতে Python ডকুমেন্টেশনের অ্যারিথমেটিক কনভার্সন দেখুন।
>>> import fractions
# A string cannot be converted to an int.
>>> 17 == '17'
False
# An int can be converted to float for comparison.
>>> 17 == 17.0
True
# The fraction 6/3 can be converted to the int 2
# The int 2 can be converted to 0b10 in binary.
>>> 6/3 == 0b10
True
# An int can be converted to a complex number with a 0 imaginary part.
>>> 17 == complex(17)
True
# The fraction 2/5 can be converted to the float 0.4
>>> 0.4 == 2/5
True
>>> complex(2/5, 1/2) == complex(0.4, 0.5)
True
কোনো সংখ্যাকে NaN (not a number) টাইপের সাথে ক্রমভিত্তিক তুলনা করলে ফল সবসময় False।
Python-এর NaN-এর সংজ্ঞার একটি বিভ্রান্তিকর পার্শ্বপ্রতিক্রিয়া হলো, NaN কখনোই NaN-এর সমান হিসেবে তুলিত হয় না।
>>> x = float('NaN')
>>> 3 < x
False
>>> x < 3
False
# NaN never compares equal to NaN
>>> x == x
False
সংখ্যার বিপরীতে, স্ট্রিং (str) তুলনা করা হয় লেক্সিকোগ্রাফিকভাবে, তাদের প্রতিটি ইউনিকোড কোড পয়েন্ট ব্যবহার করে (str-এর প্রতিটি কোড পয়েন্ট বিল্ট-ইন ফাংশন ord()-এ পাস করার ফল, যা একটি int রিটার্ন করে)।
দুই স্ট্রিংয়ের সব কোড পয়েন্ট মিলে গেলে এবং সেগুলো একই ক্রমে থাকলে, দুই স্ট্রিংকেই সমান ধরা হয়।
এই তুলনাটি 'জোড়ায় জোড়ায়' করা হয়, প্রথমটির সাথে প্রথমটি, দ্বিতীয়টির সাথে দ্বিতীয়টি, এভাবে।
Python 3.x-এ str আর bytes-কে সরাসরি রূপান্তর করে তুলনা করা যায় না।
>>> 'Python' > 'Rust'
False
>>> 'Python' > 'JavaScript'
True
# Examples with Mandarin.
# hello < goodbye
>>> '你好' < '再见'
True
# ord() of first characters
>>> ord('你'), ord('再')
(20320, 20877)
# ord() of second characters
>>> ord('好'), ord('见')
(22909, 35265)
# And with Korean words.
# Pretty < beautiful.
>>> '예쁜' < '아름다운'
False
>>> ord('예'), ord('아')
(50696, 50500)
তুলনা অপারেটরগুলো ইচ্ছেমতো চেইন করা যায়, অর্থাৎ যেকোনো দৈর্ঘ্যের যেকোনো সমন্বয়ে সেগুলো ব্যবহার করা যায়।
মনে রাখবেন, একটি এক্সপ্রেশনের মূল্যায়ন left থেকে right-এ হয়।
উদাহরণস্বরূপ, x < y <= z আসলে x < y and y <= z-এর সমতুল্য, শুধু পার্থক্য হলো y মাত্র একবার মূল্যায়িত হয়।
দুই ক্ষেত্রেই, x < y-কে False হিসেবে পাওয়া গেলে z-কে একেবারেই মূল্যায়ন করা হয় না।
একে প্রায়ই short-circuit evaluation বলা হয়, অর্থাৎ এক্সপ্রেশনের সত্য মান আগেই নির্ধারিত হয়ে গেলে মূল্যায়ন থেমে যায়।
Short circuiting verschieden বুলিয়ান অপারেটর, ফাংশন এবং Python-এ তুলনার চেইনিংও সাপোর্ট করে।
C, C++, C# আর Java-সহ আরও অনেক প্রোগ্রামিং ভাষার বিপরীতে, Python-এ a < b < c-এর মতো চেইন করা এক্সপ্রেশনের একটি প্রচলিত গাণিতিক ব্যাখ্যা ও প্রিসিডেন্স থাকে।
>>> x = 2
>>> y = 5
>>> z = 10
>>> x < y < z
True
>>> x < y > z
False
>>> x > y < z
False
is আর is not অপারেটর অবজেক্টের মান-এর বিপরীতে অবজেক্টের আইডেন্টিটি পরীক্ষা করে।
একবার তৈরি হওয়ার পর অবজেক্টের আইডেন্টিটি কখনো বদলায় না, আর এটি id() ফাংশন দিয়ে পাওয়া যায়।
<apple> is <orange> মূল্যায়িত হয় True-তে যদি এবং কেবল যদি id(<apple>) == id(<orange>) হয়।
<apple> is not <orange> এর বিপরীত ফল দেয়।
সিঙ্গেলটন হওয়ার কারণে, None আর NotImplemented-কে সবসময় is আর is not দিয়ে আইটেমের সাথে তুলনা করা উচিত।
এই রীতির আরও বিস্তারিত জানতে মানের তুলনা ও PEP8 নিয়ে Python-এর রেফারেন্স ডকুমেন্টেশন দেখুন।
>>> my_fav_numbers = [1, 2, 3]
>>> your_fav_numbers = my_fav_numbers
>>> my_fav_numbers is your_fav_numbers
True
# The returned id will differ by system and python version.
>>> id(my_fav_numbers)
4517478208
# your_fav_numbers is only an alias pointing to the original my_fav_numbers object.
# Assigning a new name does not create a new object.
>>> id(your_fav_numbers)
4517478208
>>> my_fav_numbers is not your_fav_numbers
False
>>> my_fav_numbers is not None
True
>>> my_fav_numbers is NotImplemented
False
in আর not in অপারেটর মেম্বারশিপ পরীক্ষা করে।
<fish> in <soup> মূল্যায়িত হয় True-তে যদি <fish>, <soup>-এর একটি মেম্বার হয় (যদি <fish>, <soup>-এর একটি সাবসেট হয় বা <soup>-এর ভেতরে থাকে), অন্যথায় False-তে মূল্যায়িত হয়।
<fish> not in <soup> নেগেশনটি রিটার্ন করে, অর্থাৎ <fish> in <soup>-এর বিপরীত ফল।
স্ট্রিং আর bytes টাইপের ক্ষেত্রে, <name> in <fullname> হলো True যদি এবং কেবল যদি <name>, <fullname>-এর একটি সাবস্ট্রিং হয়।
# A set of lucky numbers.
>>> lucky_numbers = {11, 22, 33}
>>> 22 in lucky_numbers
True
>>> 44 in lucky_numbers
False
# A dictionary of employee information.
>>> employee = {'name': 'John Doe',
'id': 67826, 'age': 33,
'title': 'ceo'}
# Checking for the membership of certain keys.
>>> 'age' in employee
True
>>> 33 in employee
False
>>> 'lastname' not in employee
True
# Checking for substring membership
>>> name = 'Super Batman'
>>> 'Bat' in name
True
>>> 'Batwoman' in name
False
এই অনুশীলনীতে আপনি ব্ল্যাকজ্যাক-এর কিছু নিয়ম বাস্তবায়ন করবেন, যেমন গেমটি কীভাবে খেলা হয় এবং কীভাবে স্কোর করা হয়।
দ্রষ্টব্য: এই অনুশীলনীতে, A মানে টেকা, J মানে জ্যাক, Q মানে রানি এবং K মানে রাজা।
জোকার বাদ দেওয়া হয়।
একটি আদর্শ ফরাসি স্যুটের ৫২-কার্ডের ডেক ধরে নেওয়া হয়, তবে বেশিরভাগ সংস্করণে খেলার জন্য একাধিক ডেক একসাথে শাফল করা হয়।
ব্ল্যাকজ্যাকে, একটি টেকার মূল্য ১ পয়েন্ট হবে নাকি ১১ পয়েন্ট, তা নির্ভর করে প্রতিটি খেলোয়াড়ের নিজের উপর (সে বিষয়ে পরে আরও)।
ফেস কার্ড (J, Q, K) ১০ পয়েন্টে গণনা করা হয় এবং অন্য যেকোনো কার্ডের মান তার "পিপ" (সাংখ্যিক) মান।
প্যারামিটার card সহ value_of_card(<card>) ফাংশনটি ডিফাইন করুন।
ফাংশনটি পাস করা কার্ড স্ট্রিংয়ের সাংখ্যিক মান রিটার্ন করবে।
যেহেতু একটি টেকা একাধিক মান নিতে পারে (১ বা ১১), তাই আপাতত এই ফাংশনটি টেকা কার্ডের মান ১ হিসেবেই ধরে নেবে।
পরে, হাতে থাকা কার্ডের ভিত্তিতে টেকা কার্ডের মান নির্ণয় করার জন্য একটি ফাংশন বাস্তবায়ন করবেন।
>>> value_of_card('K')
10
>>> value_of_card('4')
4
>>> value_of_card('A')
1
card_one ও card_two প্যারামিটার সহ higher_card(<card_one>, <card_two>) ফাংশনটি ডিফাইন করুন।
স্কোরিংয়ের জন্য, J, Q বা K-এর মান ১০।
স্কোরিংয়ের জন্য কোন কার্ডের মান বেশি, তা ফাংশনটি রিটার্ন করবে।
দুই কার্ডের মান সমান হলে, দুটোই রিটার্ন করুন।
return স্টেটমেন্টে কমা ব্যবহার করে দুটি কার্ডই রিটার্ন করা যায়:
# Using a comma in a return creates a Tuple. Tuples will be covered in a later exercise.
>>> def returning_two_values(value_one, value_two):
return value_one, value_two
>>> returning_two_values('K', '3')
('K', '3')
একটি টেকা একাধিক মান নিতে পারে, তাই এই কাজের জন্য আমরা A কার্ডের মান ১ ধরে নেব।
>>> higher_card('K', '10')
('K', '10')
>>> higher_card('4', '6')
'6'
>>> higher_card('K', 'A')
'K'
আগেই বলা হয়েছে, একটি টেকার মূল্য হয় ১, নয়তো ১১ পয়েন্ট। খেলোয়াড়রা ২১-এর স্কোরের যতটা সম্ভব কাছাকাছি পৌঁছানোর চেষ্টা করে, ২১-এর উপরে না গিয়ে ("বাস্ট" হয়ে যাওয়া)।
টেকা কার্ড পাওয়ার আগে হাতে থাকা একজোড়া কার্ড card_one ও card_two দিয়ে, অর্থাৎ এই প্যারামিটার দুটি সহ value_of_ace(<card_one>, <card_two>) ফাংশনটি ডিফাইন করুন।
আসন্ন টেকাটি ১ মান পাবে নাকি ১১ মান পাবে, তা আপনার ফাংশনকে সিদ্ধান্ত নিতে হবে এবং সেই মান রিটার্ন করতে হবে।
মনে রাখবেন: টেকাসহ হাতের মান যতটা সম্ভব বেশি হওয়া দরকার, তবে ২১-এর উপরে না গিয়ে।
ইঙ্গিত: হাতে যদি ইতিমধ্যেই একটি টেকা থাকে, তাহলে আসন্ন টেকার মান হবে ১।
>>> value_of_ace('6', 'K')
1
>>> value_of_ace('7', '3')
11
কোনো খেলোয়াড়ের প্রথম দুই কার্ড হিসেবে একটি টেকা (A) আর একটি দশ-কার্ড (১০, K, Q বা J) পড়লে, তার স্কোর হয় ২১।
এটাকে ব্ল্যাকজ্যাক হাত বলা হয়।
card_one ও card_two প্যারামিটার সহ is_blackjack(<card_one>, <card_two>) ফাংশনটি ডিফাইন করুন, যেখানে এগুলো একজোড়া কার্ড।
দুই কার্ডের হাতটি ব্ল্যাকজ্যাক কি না তা নির্ণয় করুন, এবং সেটি হলে বুলিয়ান True, অন্যথায় False রিটার্ন করুন।
দ্রষ্টব্য: স্কোরের হিসাব নানা ভাবে করা যায়। তবে সম্ভব হলে, আমরা চাই আপনি হাতের মানগুলো যোগ করার বদলে হাতে (বা নির্দিষ্ট কোনো অবস্থানে) একটি টেকা আর একটি দশ-কার্ড আছে কি না তা যাচাই করুন।
>>> is_blackjack('A', 'K')
True
>>> is_blackjack('10', '9')
False
হাতের প্রথম দুই কার্ডের মান একই হলে (যেমন দুটি ছক্কা, বা একটি Q ও K), খেলোয়াড় সেগুলোকে দুটি আলাদা হাত হিসেবে গণ্য করতে বেছে নিতে পারেন।
এটাকে "জোড়া ভাগ করা" বলা হয়।
card_one ও card_two প্যারামিটার সহ can_split_pairs(<card_one>, <card_two>) ফাংশনটি ডিফাইন করুন, যেখানে এগুলো একজোড়া কার্ড।
এই দুই কার্ডের হাতটি দুটি জোড়ায় ভাগ করা যায় কি না তা নির্ণয় করুন।
হাতটি ভাগ করা গেলে বুলিয়ান True রিটার্ন করুন, অন্যথায় False রিটার্ন করুন
>>> can_split_pairs('Q', 'K')
True
>>> can_split_pairs('10', 'A')
False
প্রথমে দেওয়া দুই কার্ডের মোট মান ৯, ১০ বা ১১ পয়েন্ট হলে, খেলোয়াড় নিজের মূল বাজির সমান একটি অতিরিক্ত বাজি রাখতে পারেন। এটাকে "ডাবল ডাউন" বলা হয়।
card_one ও card_two প্যারামিটার সহ can_double_down(<card_one>, <card_two>) ফাংশনটি ডিফাইন করুন, যেখানে এগুলো একজোড়া কার্ড।
দুই কার্ডের হাতটি "ডাবল ডাউন" করা যায় কি না তা নির্ণয় করুন, এবং গেলে বুলিয়ান True, অন্যথায় False রিটার্ন করুন।
>>> can_double_down('A', '9')
True
>>> can_double_down('10', '2')
False
Exercism-এ সাইন আপ করুন, Python ট্র্যাকের 17টি কনসেপ্ট146টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।