第二章 與Python的無縫集成----基本特殊方法.

第二章 與Python的悟性陳繼承----基本特殊方法.

python中有有一些特殊的方法,它們允許我們的類和python更好的集成

  • __repr__():
  • __str__()
  • __format__()
  • __hash__()
  • __bool__()
  • __bytes__()
  • __lt__()
  • __le__()
  • __eq__()
  • __ne__()
  • __gt__()
  • __ge__()
  • __new__()
  • __del__()

2.1 __repr__()__str__()方法

  • 通常str()方法表示的對象對用戶更加友好.這個方法是有對象的__str__()方法實現的.

什么時候重寫 __str__()__repr__()

  • 非集合對象: 一個不包括其他集合對象的'簡單'對象,這類對象格式通常不會特別復雜
  • 集合對象:一個包括集合的對象,這類對象的格式化會非常復雜.
非集合對象的__repr__()__str__()

問題1: 什么是集合?

class Card(object):
    def __init__(self, rank, suit):
        self.suit = suit
        self.rank = rank
        self.hard, self.soft = self._points()

    def __repr__(self):
        return '{__class__.__name__}(suit = {suit!r} , rank = {rank!r})'.format(
            __class__=self.__class__, **self.__dict__
        )

    def __str__(self):
        return '{rank}{suit}'.format(**self.__dict__)


class NumberCard(Card):
    def _points(self):
        return int(self.rank), int(self.rank)


x = NumberCard('2', '?')
# 注意下面是重寫后的
print(str(x))  # 2? 
print(x)       # 2?
print(repr(x)) # NumberCard(suit = '?' , rank = '2')
__format__()方法

注意:‘{0!r}'.format()'{0!s}'.format()并不會調用__format__()方法,它們會調用__repr__()或者__str__().

__hash__()方法

內置hash()函數調用了__hash__()方法.哈希是一種將復雜的值簡化為小整數的計算方式.

python有兩個哈希庫:

  • hashlib
  • zip 有兩個搞笑的哈希函數adler32()crc32()
    hasd()函數主要被用來創建set,forzenset,dict這些集合類的鍵.這些集合利用了不可變對象的哈希值來高效的查找集合中的對象
決定hash的對象

并非每個對象都需要提供一個哈希值,尤其是,當我們創建一個包含有狀態,可改變對象的類時.這類不應該返回哈希值,__hash__的定義 應該是None

等價比較有三個層次:

  • 哈希值相等:意味著兩個結果可能相等.哈希值是判斷兩個對象有可能相等的快捷方式,如果哈希值不同,兩個對象不可能相等,也不可能是同一個對象.
  • 比較結果相等:意味著兩個對象的哈希值已經是相等的,這個比較用的是==運算符.如果結果相等,那么兩個對象的有可能是同一個.
  • IDD 相等:這意味著兩個對象是同一個對象,它們的哈希值仙童,并且使用==的比較結果相等,這個比較是用的是is運算符.

**基本哈希法(Fundametal Law of Hash):比較相等的對象的哈希值一定相等.

有關不可變對象和繼承的默認行為
class Card(object):
    def __init__(self, rank, suit, hard, soft):
        self.suit = suit
        self.rank = rank
        self.hard = hard
        self.soft = soft

    def __repr__(self):
        return '{__class__.__name__}(suit = {suit!r} , rank = {rank!r})'.format(
            __class__=self.__class__, **self.__dict__
        )

    def __str__(self):
        return '{rank}{suit}'.format(**self.__dict__)


class NumberCard(Card):
    def __init__(self, rank, suit):
        super().__init__(str(rank), suit, rank, rank)


class AceCard(Card):
    def __init__(self, rank, suit):
        super(AceCard, self).__init__("A", suit, 1, 11)


class FaceCard(Card):
    def __init__(self, rank, suit):
        super(FaceCard, self).__init__({11: 'J',
                                        12: 'Q',
                                        13: 'K'}[rank], suit, 10, 10)



c1 = AceCard(1,'?')
c2 = AceCard(1,'?')
print(id(c1),id(c2)) # 52067024 52067120 

id()值不同意味著是不同的對象.
**is測試基于id()的值,哈希值根據id()值來計算的`

重載不可變對象

下面是一個重載了__hash__()__eq__()定義的簡單類.

class Card2(object):
    def __init__(self, rank, suit, hard, soft):
        self.suit = suit
        self.rank = rank
        self.hard = hard
        self.soft = soft

    def __repr__(self):
        return '{__class__.__name__}(suit = {suit!r} , rank = {rank!r})'.format(
            __class__=self.__class__, **self.__dict__
        )

    def __str__(self):
        return '{rank}{suit}'.format(**self.__dict__)

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

    def __hash__(self):
        return hash(self.suit) ^ hash(self.rank)


class AceCard2(Card2):
    insure = True

    def __init__(self, rank, suit):
        super().__init__("A", suit, 1, 11)


c1 = AceCard2(1, '?')
c2 = AceCard2(1, '?')

print(id(c1), id(c2))     # id 是不相同的
print(c1 is c2)           # False
print(hash(c1), hash(c2)) # hash是相同的
print(c1 == c2)           # True
print(set([c1,c2]))       # {AceCard2(suit = '?' , rank = 'A')}
重載可變對象

下面的類層級結構中,我們沖在了可變對象的 __hash__()__eq__()

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容

  • Python內置函數詳解——總結篇 ** 引 言** ** 數學運算** abs:求數值的絕對值>>> abs...
    yutiansut閱讀 771評論 0 1
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,737評論 18 399
  • 黑暗孕育了光明,而光明卻背棄了黑暗,黑暗只有孤身一人,而光明卻擁有眾多朋友,這就是你們向往的光明,崇尚的光明,你們...
    鞠安ojbk閱讀 388評論 5 2
  • 其實我也不知道叫這個題目對不對,符合不符合我想說的事 下午去爬山,天氣突然晴轉陰,伴隨打雷閃電,到半山腰就開始往回...
    丸子_34c8閱讀 398評論 0 3
  • 女性,到了大學會有很多的改變,大多數是驚嘆于容貌的徹頭徹尾的“革命”,在這個靠顏值的社會,似乎誰再不注重自己的外在...
    子晨恩閱讀 279評論 4 3