یک عملگر مقایسه در Python (که به آن عملگر رابطهای پایتون هم میگویند) به مقدارهای دو عملوند نگاه میکند و اگر شرط comparison برقرار باشد یا نباشد، یک مقدار «منطقی» True یا False را برمیگرداند.
جدول زیر رایجترین عملگرهای مقایسه در 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 را سفارشی میکنند.
برای جزئیات (بسیار) بیشتر، به مقایسهی مقدارها در مستندات Python مراجعه کنید.
انواع عددی (بیشتر) استثنای این قاعدهی تطبیق نوعاند.
یک integer میتواند با یک float برابر شمرده شود (یا یک octal با یک hexadecimal)، تا زمانی که این انواع بتوانند برای مقایسه بهصورت ضمنی تبدیل شوند.
برای دیگر انواع عددی (مختلط، اعشاری، کسرها)، عملگرهای مقایسه در جایی تعریف شدهاند که «معنا دارند» (جایی که تبدیل ضمنی نتیجه را تغییر نمیدهد)، اما اگر شیءهای زیرین نتوانند برای مقایسه بهطور دقیق تبدیل شوند، یک 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 (نه یک عدد) برابر False است.
یک اثر جانبی گیجکننده در تعریف NaN در Python این است که NaN هرگز با NaN برابر شمرده نمیشود.
اگر کنجکاوید بدانید چرا NaN در Python اینگونه تعریف شده است، این پست Stack Overflow دربارهی 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)
انواع دادهی نگهدارنده (lists، tuples، sets، dicts و غیره) هم واژهنامهای مقایسه میشوند: اگر هر دو نگهدارنده دادههای یکسان و انواع دادهی یکسان داشته باشند برابرند (در مورد lists و tuples، ترتیب هم باید یکسان باشد) و در غیر این صورت نابرابرند.
>>> [1, 2] == [1, 2]
True
# But if the data is not in the same order, they are not equal.
>>> [2, 1] == [1, 2]
False
# The same holds true for tuples
>>> (3,4,5) == (5,4,3)
False
# Length is also compared
>>> [1, 2] < [1, 2, 3]
True
# Comparing dicts
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 18}
False
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 19}
True
عملگرهای مقایسه را میتوان به هر شکلی زنجیره کرد.
توجه کنید که ارزیابی یک عبارت از left به right انجام میشود.
برای نمونه، x < y <= z همارز x < y and y <= z است، با این تفاوت که y فقط یک بار ارزیابی میشود.
در هر دو حالت، وقتی x < y برابر False باشد، z اصلاً ارزیابی نمیشود.
به این کار اغلب short-circuit evaluation میگویند: اگر ارزش درستی عبارت پیشاپیش مشخص شده باشد، ارزیابی متوقف میشود.
Short circuiting را عملگرهای منطقی و توابع گوناگون پشتیبانی میکنند و در Python زنجیرهسازی مقایسه هم از آن پشتیبانی میکند.
برخلاف بسیاری از زبانهای برنامهنویسی دیگر، از جمله C، C++، C# و Java، عبارتهای زنجیرهای مانند a < b < c در Python یک تفسیر ریاضی و اولویت متعارف دارند.
>>> 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 مقایسه کرد.
برای جزئیات بیشتر دربارهی این قرارداد، به مستندات مرجع Python دربارهی مقایسهی مقدارها و PEP8 مراجعه کنید.
# A list of favorite numbers.
>>> 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> باشد (یعنی زیرمجموعهای از <soup> یا درون آن باشد) و در غیر این صورت False ارزیابی میشود.
<fish> not in <soup> نقیض، یا عکس <fish> in <soup> را برمیگرداند.
برای انواع رشته و بایت، <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
رفتار مقایسهی شیءها را میتوان از طریق پیادهسازی rich comparison methods سفارشی کرد.
برای اطلاعات بیشتر، آموزش Python: کلاسها، کلاسها و متدهای جادویی Python (Dan Bader) و نامهای متدهای ویژه را ببینید.