مقایسه کردن آبجکت ها

قرار است یک سری قوانین برای کارت هایمان وضع کنیم و بگوییم که کدام کارت ارزش بیشتری دارد؟ در بعضی بازی ها این ارزش گذاری بستگی به رنگ آن ها دارد، در بعضی دیگر به خال و در بعضی فقط اعداد آن ها مهم هستند. چگونه این کار را انجام دهیم؟

در پایتون ۲ برای این کار از متد یا تابعی به نام __cmp__ استفاده میکردیم تا اعمال مقایسه ای را در آن پیاده سازی کنیم.

اما بدلیل اینکه ساخت کلاس های پیچیده تر امکان پذیر باشد، این متد از پایتون حذف شد و به جای آن ۶ متد دیگر به پایتون اضاف شد.

مقایسه آبجکت ها در پایتون

زمانی که قرار است یک کارت، خودش را با کارت دیگر مقایسه کند نیاز به دو آرگومان دارد، خودش و کارت دیگر. پس آرگومان های هر متد عبارت اند از self و other.

در نهایت هر متد باید True یا False را برگرداند.

میخواهیم مساوی بودن کارت ها را تعریف کنیم، دو کارت زمانی مساوی هستند که مقدار خال و ارزش یکسانی داشته باشند. از متد __eq__ استفاده میکنیم:

def __eq__(self, other):
    return (self.suit, self.rank) == (other.suit, other.rank)

حالا پایتون میداند که کارت ها در چه زمانی مساوی هستند، اگر در بازی ما خال ها ارزش یکسان داشتند آنوقت کافی بود که فقط rank ها را مقایسه میکردیم. اما در اینجا ارزش خال ها به این صورت است:

Clubs < Diamonds < Hearts < Spades

میتوانیم دو شی از این کلاس بسازیم و آن ها را با علامت == مقایسه کنیم. برای اینکه بتوانیم نا مساوی بودن آن ها را نیز بررسی کنیم ( != ) لازم نیست حتما متد __ne__ را بنویسیم. اگر بین دو کارت علامت != را به کار ببریم، پایتون به طور اتوماتیک متد __eq__ را اجرا کرده و نتیجه را معکوس میکند و برمیگرداند.

هنوز نمیتوانیم از علامت های <> و <= >= استفاده کنیم. برای پیاده سازی قوانین بزرگتر یا گوچکتر از یکی از متد های __lt__ یا __gt__ استفاده میکنیم. یکی را که بنویسیم پایتون دومی را نیز اجرا میکند.

اولویت بازی ما به این صورت است که در اولویت اول خال ها بررسی میشوند، اگر خال یک کارت ارزش بیشتری داشت آنوقت مهم نیست rank آن چقدر است پس آن کارت بزرگتر است. اما در حالتی که خال های برابری داشتند آنوقت سراغ rank رفته و آن کارت که ارزش بیشتری دارد، کارت غالب است. متد را به صورت زیر مینویسیم:

def __lt__(self, other):
    if self.suit == other.suit:
        return self.rank < other.rank
    return self.suit < other.suit

هنوز بزرگتر مساوی و کوچکتر مساوی روی اشیا این کلاس کار نمیکند. برای این کار کافیست متد __le__ را صدا بزنیم و دقیقا کد های قسمت قبل را در آن کپی کنیم فقط به جای علامت < از <= استفاده میکنیم:

def __le__(self, other):
    if self.suit == other.suit:
        return self.rank <= other.rank
    return self.suit <= other.suit

تمام حالات ممکن پیاده سازی شدند. بعنوان تمرین سعی کنید کاری کنید که در این بازی ارزش Ace از King بیشتر باشد. این کار بر عهده خودتان است. با کمی تمرین و تمرکز حتما میتوانید آن را بنویسید.

کلاس کارت به اتمام رسید و در مجموع کد های آن به صورت زیر است، یک بار دیگر مرور کنید و دلیل هر کد را بررسی کنید.

class Card:
    def __init__(self, suit=0, rank=0):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        suit_list = ["Clubs", "Diamonds", "Hearts", "Spades"]
        rank_list = [0, "Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"]
        return rank_list[self.rank] + " of " + suit_list[self.suit]

    def __eq__(self, other):
        return (self.suit, self.rank) == (other.suit, other.rank)

    def __lt__(self, other):
        if self.suit == other.suit:
            return self.rank < other.rank
        return self.suit < other.suit

    def __le__(self, other):
        if self.suit == other.suit:
            return self.rank <= other.rank
        return self.suit <= other.suit
ارسال دیدگاه

نشانی ایمیل شما منتشر نخواهد شد.