久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Python魔法方法漫游指南:類的表示

 常有理 2021-07-14

使用字符串等信息來表示類是一個相當(dāng)實(shí)用的特性。比方說你在調(diào)試代碼時,,會頻繁使用 print() 等函數(shù)來獲取對象信息,其背后就是隱式調(diào)用了將類轉(zhuǎn)化為字符串的魔法方法,。相對應(yīng)的,,還有另一部分魔法方法用于自定義在使用內(nèi)建函數(shù)時類的行為。

基礎(chǔ)方法

Python 中將對象轉(zhuǎn)換為字符串有兩個類似的魔法方法,,即 __str__ 和 __repr__ ,。

它兩有什么區(qū)別呢?讓我們先看結(jié)論:

  • __str__ 注重可讀性,,比如展示給用戶,。

  • __repr__ 注重明確性,比如展示給開發(fā)中的程序員,。

舉個栗子,。假設(shè)有一個表示當(dāng)前時間的類:

from datetime import datetimeclass MyDate:    def __init__(self):        self.date = datetime.now()f = MyDate()print(f)print(f.__repr__())print(f.__str__())# 輸出:# <__main__.MyDate object at 0x000002510231AFA0># <__main__.MyDate object at 0x000002510231AFA0># <__main__.MyDate object at 0x000002510231AFA0>

打印的結(jié)果不明確,得不到我想要的跟時間有關(guān)的信息,。

增加 __str__ 方法后:

from datetime import datetimeclass MyDate:    def __init__(self):        self.date = datetime.now()            def __str__(self):        return self.date.__str__()f = MyDate()print(f)print(f.__repr__())print(f.__str__())# 輸出:# 2021-06-30 19:49:56.620427# <__main__.MyDate object at 0x00000251026C3CA0># 2021-06-30 19:49:56.620427

打印 f 或者 f.__str__() 均能夠顯示格式化后的時間信息,,但是無法得知具體的類型。

如果只實(shí)現(xiàn) __repr__ ,,則有:

from datetime import datetimeclass MyDate:    def __init__(self):        self.date = datetime.now()        def __repr__(self):        return self.date.__repr__()f = MyDate()print(f)print(f.__repr__())print(f.__str__())# 輸出:# datetime.datetime(2021, 6, 30, 19, 53, 14, 797960)# datetime.datetime(2021, 6, 30, 19, 53, 14, 797960)# datetime.datetime(2021, 6, 30, 19, 53, 14, 797960)

三種打印方式均被 __repr__ 覆蓋,,不僅顯示了時間信息,也可得知具體的類型。

如果兩種魔法方法同時實(shí)現(xiàn):

from datetime import datetimeclass MyDate:    def __init__(self):        self.date = datetime.now()            def __str__(self):        return self.date.__str__()        def __repr__(self):        return self.date.__repr__()f = MyDate()print(f)print(f.__repr__())print(f.__str__())# 輸出:# 2021-06-30 19:54:57.350076# datetime.datetime(2021, 6, 30, 19, 54, 57, 350076)# 2021-06-30 19:54:57.350076

總的來說兩者中可優(yōu)先實(shí)現(xiàn) __repr__ ,,有需要再實(shí)現(xiàn) __str__,。

此外,還有兩個常用的方法 __dir__ 和 __dict__ ,。

__dir__ 定義了調(diào)用 dir() 時的行為,,返回對象的屬性、方法的列表:

>>> a = 1>>> a.__dir__()['__repr__', '__hash__', '__getattribute__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__add__', '...']

而 __dict__ 則會輸出所有實(shí)例屬性組成的字典:

class Bar:    def __init__(self, a, b):        self.a = a        self.b = bb = Bar(1, 2)print(b.__dict__)# 輸出:# {'a': 1, 'b': 2}

bytes 和 format 和 bool

理解了前面的內(nèi)容,,再來說類似的方法就簡單了,。

__bytes__ 方法實(shí)現(xiàn)了通過 bytes() 獲取對象字節(jié)序列的表示形式。而 __format__ 方法被內(nèi)置的 format() 或 str.format() 調(diào)用,,獲取對象的格式化后的字符串表示形式,。

看例子:

from datetime import datetimeclass MyDate:    def __init__(self):        self.date = datetime.now()            def __bytes__(self):        return b'This is a bytes result'        def __format__(self, format_spec):        return 'The time is: ' + format(self.date, format_spec)f = MyDate()print(bytes(f))print(format(f, '%H:%M:%S'))# 輸出:# b'This is a bytes result'# The time is: 10:15:36

而 __bool__ 就更簡單了,它負(fù)責(zé)實(shí)現(xiàn)內(nèi)置的 bool() 方法:

class Foo:    def __bool__(self):        return False    f = Foo()print(bool(f))# 輸出:# False

如果類沒有實(shí)現(xiàn) __bool__ ,,那么調(diào)用 bool() 會檢查類的 __len__ ,,非零則返回 True 。

如果連 __len__ 也沒實(shí)現(xiàn),,則會直接返回 True ,。

hash可哈希

__hash__ 這個稍微復(fù)雜點(diǎn),放到最后來說,。

Hash ,,一般稱作散列哈希

哈希算法是用來解決數(shù)據(jù)與數(shù)據(jù)之間對應(yīng)關(guān)系的一種算法,。它可以將任意長度的輸入變換為固定長度的輸出,,該輸出被稱為哈希值。簡單來說,,就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù),。而實(shí)現(xiàn)了哈希算法的對象,就被稱為可哈希的或者可散列的,。

Python 中的不可變類型通常都是可哈希的,,比如數(shù)字、字母,、字符串,、元組等。

可變類型通常是不可哈希的,,比如列表,、字典、集合等,。

Python 的三種數(shù)據(jù)結(jié)構(gòu):set ,、 frozenset 和 dict 都是要求其鍵值是可哈希的,,因?yàn)橐WC鍵的唯一性。

如果自定義對象需要實(shí)現(xiàn)可哈希,,那么就必須實(shí)現(xiàn) __hash__ 方法,。

我們自定義一個矢量類作為例子:

class Vector:    # 用于哈希算法的屬性就像一個id    # 改變id會導(dǎo)致對象的身份混亂    # 因此將其標(biāo)識為只能讀取的私有變量    def __init__(self, x, y):        self.__x = x        self.__y = y            @property    def x(self):        return self.__x        @property    def y(self):        return self.__y        # 根據(jù)官方文檔建議    # 哈希算法最好作用于輸入值的元組上    # 以使得哈希值更加隨機(jī)    def __hash__(self):        return hash((self.__x, self.__y))        # 實(shí)現(xiàn)__hash__ 必須同時實(shí)現(xiàn) __eq__    def __eq__(self, other):        return self.__x == other.__x and self.__y == other.__y        # 格式化打印輸出    def __repr__(self):        return f'(x: {self.__x}, y: {self.__y})'# 注意 v1 和 v2 的矢量值相同# 因此哈希函數(shù)計(jì)算結(jié)果也相同# 那么在集合中則會被歸為同一個元素v1 = Vector(1,2)v2 = Vector(1,2)v3 = Vector(2,3)s = set([v1, v2, v3])print(s)# 輸出:# {(x: 2, y: 3), (x: 1, y: 2)}

可以看到這個自定義的類實(shí)現(xiàn)了可哈?;?,并且順利的放到了集合 set 中。

需要注意的是,,如果類實(shí)現(xiàn)了 __hash__ ,,那么它也必須同時實(shí)現(xiàn) __eq__ ,因?yàn)殒I的唯一性是由它兩一起參與驗(yàn)證的,。并且你還需要保證 x==y 和 hash(x) == hash(y) 是等效的,。


本系列文章開源發(fā)布于 Github,傳送門:Python魔法方法漫游指南

看完文章想吐槽,?歡迎留言告訴我,!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多