最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python利用魔法方法玩轉(zhuǎn)對(duì)象

 更新時(shí)間:2023年12月07日 11:23:39   作者:databook  
Python中魔法方法(magic method)其實(shí)就是那些被雙下劃線包圍的方法,這些魔法方法為類添加了**“魔力”,讓我們可以在面向?qū)ο缶幊讨杏酶雍?jiǎn)潔的代碼來操作對(duì)象,下面我們就來具體了解一下如何利用魔法方法玩轉(zhuǎn)對(duì)象吧

Python中魔法方法(magic method)其實(shí)就是那些被雙下劃線包圍的方法,比如__init____str__ 等等。

這些魔法方法添加了**“魔力”,讓我們可以在面向?qū)ο缶幊讨杏酶雍?jiǎn)潔的代碼來操作對(duì)象。

本篇根據(jù)面向?qū)ο缶幊痰囊恍﹫?chǎng)景來介紹常用的魔法方法**。

1. 對(duì)象構(gòu)建

為了初始化對(duì)象,我們常常在對(duì)象中定義一個(gè)__init__方法,比如:

class Student(object):
    """
    學(xué)生信息
    """
    def __init__(self, name):
        print("[__init__] Student 初始化...")
        self.name = name

# 創(chuàng)建對(duì)象
stu = Student("小明")

# 運(yùn)行結(jié)果
[__init__] Student 初始化...

當(dāng)我們創(chuàng)建對(duì)象時(shí),會(huì)自動(dòng)調(diào)用魔法方法__init__去初始化屬性。

__init__對(duì)應(yīng)的是__del__,它會(huì)在對(duì)象失效的調(diào)用,我們可以在__del__方法中清理對(duì)象Student占用的資源。

class Student(object):
    def __init__(self, name):
        print("[__init__] 初始化 Student...")
        self.name = name

    def __del__(self):
        print("[__del__] 清理 Student...")

def foo():
    print("進(jìn)入 foo 函數(shù)...")
    stu = Student("小明")
    print("離開 foo 函數(shù)...")

foo()

# 運(yùn)行結(jié)果
進(jìn)入 foo 函數(shù)...
[__init__] 初始化 Student...
離開 foo 函數(shù)...
[__del__] 清理 Student...

進(jìn)入 foo 函數(shù)后創(chuàng)建對(duì)象,離開后,自動(dòng)清理對(duì)象。

2. 對(duì)象屬性訪問

python的對(duì)象是可以直接訪問屬性的,但是訪問不存在的屬性時(shí),會(huì)拋出異常。

class Student(object):
    def __init__(self, name):
        print("[__init__] 初始化 Student...")
        self.name = name

stu = Student("小明")
print(stu.name)
print(stu.fullname)

# 運(yùn)行結(jié)果
[__init__] 初始化 Student...
小明

AttributeError: 'Student' object has no attribute 'fullname'

如果不想拋出異常,從而影響程序的其他部分的運(yùn)行,這里可以用魔法方法 __getattr__來控制訪問了不存在的屬性時(shí)的行為。

比如,下面的示例中,訪問不存在的屬性時(shí),返回False,不拋出異常。

class Student(object):
    def __init__(self, name):
        print("[__init__] 初始化 Student...")
        self.name = name

    def __getattr__(self, attr):
        print("[__getattr__] 訪問了 Student 不存在的屬性 {}".format(attr))
        return False

stu = Student("小明")
print(stu.name)
print(stu.fullname)

# 運(yùn)行結(jié)果
[__init__] 初始化 Student...
小明
[__getattr__] 訪問了 Student 不存在的屬性 fullname
False

__getattr__相對(duì)的另一個(gè)魔法方法__setattr__,與__getattr__不同的是,它既可以設(shè)置不存在的屬性,也可以設(shè)置已存在的屬性。

class Student(object):
    def __init__(self, name):
        print("[__init__] 初始化 Student...")
        self.name = name

    def __setattr__(self, attr, value):
        print("[__setattr__] 設(shè)置 Student 屬性 {}={}".format(attr, value))
        self.__dict__[attr] = value

stu = Student("小明")
print(stu.name)

# 已存在的屬性
stu.name = "小華"
print(stu.name)

# 不存在的屬性
stu.fullname = "小紅"
print(stu.fullname)

# 運(yùn)行結(jié)果
[__init__] 初始化 Student...
[__setattr__] 設(shè)置 Student 屬性 name=小明
小明
[__setattr__] 設(shè)置 Student 屬性 name=小華
小華
[__setattr__] 設(shè)置 Student 屬性 fullname=小紅
小紅

每次對(duì)屬性賦值,都會(huì)觸發(fā)__setattr__方法,即使在__init__中給self.name賦值,也觸發(fā)了__setattr__方法,所以一共被觸發(fā)了三次。

3. 對(duì)象比較

在使用基本類型(比如數(shù)值類型,字符串類型等)的時(shí)候,比較其大小非常簡(jiǎn)單。

print(1 < 2)
print(1 > 2)
print("abc" < "edf")

# 運(yùn)行結(jié)果
True
False
True

而對(duì)象直接互相比較大小則沒有這么簡(jiǎn)單了,還是用上面的Student類,這次我們加上各門功課的分?jǐn)?shù)。

class Student(object):
    def __init__(self, name, chinese, english, mathematics):
        self.name = name
        self.chinese = chinese
        self.english = english
        self.mathematics = mathematics

stu1 = Student("小明", 80, 90, 75)
stu2 = Student("小紅", 85, 70, 95)

# 比較兩個(gè)學(xué)生對(duì)象
print(stu1 > stu2)

# 運(yùn)行結(jié)果
TypeError: '>' not supported between instances of 'Student' and 'Student'

不出所料,拋出了異常。

其實(shí)我們比較兩個(gè)學(xué)生對(duì)象,是想要比較兩個(gè)學(xué)生的總分誰高誰低。

這時(shí),我們就可以實(shí)現(xiàn)用于比較的魔法方法,比如 __eq__,__lt____gt__等等。

class Student(object):
    def __init__(self, name, chinese, english, mathematics):
        self.name = name
        self.chinese = chinese
        self.english = english
        self.mathematics = mathematics

    def total(self):
        return self.chinese + self.english + self.mathematics

    def __eq__(self, other: Student):
        return self.total() == other.total()

    def __lt__(self, other: Student):
        return self.total() < other.total()

    def __gt__(self, other: Student):
        return self.total() > other.total()

stu1 = Student("小明", 80, 90, 75)
stu2 = Student("小紅", 85, 70, 95)

print(stu1 > stu2)
print(stu1 == stu2)
print(stu1 < stu2)

# 運(yùn)行結(jié)果
False
False
True

實(shí)現(xiàn)相應(yīng)的魔法方法,就能使用相應(yīng)的比較運(yùn)算符來直接比較對(duì)象了。

PS. 上面的例子中只實(shí)現(xiàn)了大于__gt__),等于__eq__),小于__lt__)的比較,還有其他魔法方法,比如:大于等于__ge__),不等于__ne__),小于等于__le__)等等。

實(shí)現(xiàn)的方式和上面例子中類似。

4. 對(duì)象輸出

對(duì)于一個(gè)基本類型的變量,顯示其內(nèi)容非常簡(jiǎn)單,而對(duì)于一個(gè)對(duì)象,顯示的內(nèi)容可能就不是我們所期望的了。

class Student(object):
    def __init__(self, name, chinese, english, mathematics):
        self.name = name
        self.chinese = chinese
        self.english = english
        self.mathematics = mathematics

s = "hello world"
print(s)

stu = Student("小明", 80, 90, 75)
print(stu)

# 運(yùn)行結(jié)果
hello world
<__main__.Student object at 0x00000164F72FD6D0>

字符串內(nèi)容可以直接顯示出來,而對(duì)象stu只是顯示了它的內(nèi)存地址,對(duì)我們了解其中的內(nèi)容毫無幫助。

此時(shí),就可以拿出我們的魔法方法__str__,來定制對(duì)象在print時(shí)顯示的內(nèi)容。

class Student(object):
    def __init__(self, name, chinese, english, mathematics):
        self.name = name
        self.chinese = chinese
        self.english = english
        self.mathematics = mathematics

    def __str__(self):
        return """姓名: {}
成績(jī):
1. 語文: {} 分
2. 數(shù)學(xué): {} 分
3. 英語: {} 分""".format(
            self.name,
            self.chinese,
            self.mathematics,
            self.english,
        )

stu = Student("小明", 80, 90, 75)
print(stu)

# 運(yùn)行結(jié)果
姓名: 小明
成績(jī):
1. 語文: 80 分
2. 數(shù)學(xué): 75 分
3. 英語: 90 分

通過魔法方法__str__,可以讓對(duì)象按照我們希望的形式顯示出來。

5. 對(duì)象運(yùn)算

對(duì)象除了可以像普通變量一樣比較,輸出,是不是也可以像變量一樣進(jìn)行算術(shù)運(yùn)算呢?
比如:

class Student(object):
    def __init__(self, name, scores):
        self.name = name
        self.scores = scores

    def __str__(self):
        return """姓名: {}, 各科成績(jī): {}""".format(
            self.name,
            self.scores,
        )

stu1 = Student("小明", [80, 90, 75])
stu2 = Student("小紅", [85, 70, 95])
print(stu1)
print(stu2)
print(stu1 + stu2)

# 運(yùn)行結(jié)果
姓名: 小明, 各科成績(jī): [80, 90, 75]
姓名: 小紅, 各科成績(jī): [85, 70, 95]

TypeError: unsupported operand type(s) for +: 'Student' and 'Student'

果然,直接進(jìn)行算術(shù)運(yùn)算是不行的。

還是得借助魔法方法,下面在類中實(shí)現(xiàn)加法減法魔法方法

class Student(object):
    def __init__(self, name, scores):
        self.name = name
        self.scores = scores

    def __str__(self):
        return """姓名: {}, 各科成績(jī): {}""".format(
            self.name,
            self.scores,
        )

    def __add__(self, other: Student):
        name = "{}, {} 成績(jī)合計(jì)".format(self.name, other.name)
        scores = [self.scores[i] + other.scores[i] for i in range(len(self.scores))]
        return Student(name, scores)

    def __sub__(self, other: Student):
        name = "{}, {} 成績(jī)之差".format(self.name, other.name)
        scores = [self.scores[i] - other.scores[i] for i in range(len(self.scores))]
        return Student(name, scores)


stu1 = Student("小明", [80, 90, 75])
stu2 = Student("小紅", [85, 70, 95])
print(stu1)
print(stu2)
print(stu1 + stu2)
print(stu1 - stu2)

# 運(yùn)行結(jié)果
姓名: 小明, 各科成績(jī): [80, 90, 75]
姓名: 小紅, 各科成績(jī): [85, 70, 95]
姓名: 小明, 小紅 成績(jī)合計(jì), 各科成績(jī): [165, 160, 170]
姓名: 小明, 小紅 成績(jī)之差, 各科成績(jī): [-5, 20, -20]

其他的算術(shù)運(yùn)算(比如,乘法,除法和求模等等)也有相應(yīng)的魔法方法,仿照上面的示例實(shí)現(xiàn)即可。

6. 總結(jié)

Python魔法方法很多,本文只是列舉了其中很少的一部分,github上有一個(gè)示例python文件,列舉了很多魔法方法,供參考:magicmethods.py

到此這篇關(guān)于Python利用魔法方法玩轉(zhuǎn)對(duì)象的文章就介紹到這了,更多相關(guān)Python魔法方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python+pyplot繪制帶文本標(biāo)注的柱狀圖方法

    Python+pyplot繪制帶文本標(biāo)注的柱狀圖方法

    今天小編就為大家分享一篇Python+pyplot繪制帶文本標(biāo)注的柱狀圖方法,具有很好的價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07
  • python實(shí)現(xiàn)自動(dòng)售貨機(jī)

    python實(shí)現(xiàn)自動(dòng)售貨機(jī)

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)自動(dòng)售貨機(jī),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 詳解pandas apply 并行處理的幾種方法

    詳解pandas apply 并行處理的幾種方法

    這篇文章主要介紹了詳解pandas apply 并行處理的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • 帶你學(xué)習(xí)Python如何實(shí)現(xiàn)回歸樹模型

    帶你學(xué)習(xí)Python如何實(shí)現(xiàn)回歸樹模型

    這篇文章主要介紹了Python如何實(shí)現(xiàn)回歸樹模型,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Django ORM多對(duì)多查詢方法(自定義第三張表&ManyToManyField)

    Django ORM多對(duì)多查詢方法(自定義第三張表&ManyToManyField)

    今天小編就為大家分享一篇Django ORM多對(duì)多查詢方法(自定義第三張表&ManyToManyField),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • Python中線程同步的實(shí)現(xiàn)

    Python中線程同步的實(shí)現(xiàn)

    本文主要介紹了Python中線程同步的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-06-06
  • python 利用opencv實(shí)現(xiàn)圖像網(wǎng)絡(luò)傳輸

    python 利用opencv實(shí)現(xiàn)圖像網(wǎng)絡(luò)傳輸

    這篇文章主要介紹了python 如何利用opencv實(shí)現(xiàn)圖像網(wǎng)絡(luò)傳輸,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-11-11
  • Python3顯示當(dāng)前時(shí)間、計(jì)算時(shí)間差及時(shí)間加減法示例代碼

    Python3顯示當(dāng)前時(shí)間、計(jì)算時(shí)間差及時(shí)間加減法示例代碼

    這篇文章主要給大家介紹了關(guān)于Python3顯示當(dāng)前時(shí)間、計(jì)算時(shí)間差及時(shí)間加減法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Python3具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 用Python生成藝術(shù)之分形與算法繪圖實(shí)踐

    用Python生成藝術(shù)之分形與算法繪圖實(shí)踐

    這篇文章主要介紹了用Python生成藝術(shù)之分形與算法繪圖實(shí)踐,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2026-03-03
  • 如何通過Python實(shí)現(xiàn)一個(gè)消息隊(duì)列

    如何通過Python實(shí)現(xiàn)一個(gè)消息隊(duì)列

    這篇文章主要為大家詳細(xì)介紹了如何通過Python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的消息隊(duì)列,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02

最新評(píng)論

西昌市| 沙湾县| 合水县| 沧州市| 湛江市| 长泰县| 博客| 迁安市| 广宁县| 平湖市| 临清市| 达拉特旗| 上蔡县| 郎溪县| 泸水县| 扶沟县| 班玛县| 金塔县| 来安县| 渑池县| 江门市| 太湖县| 吴堡县| 和政县| 金昌市| 长乐市| 崇礼县| 扎赉特旗| 广平县| 邢台县| 岑溪市| 西林县| 乾安县| 边坝县| 大宁县| 开封市| 弥渡县| 新宁县| 东台市| 吉木乃县| 江达县|