Python基礎刻意練習:魔法方法

參考鏈接

魔法方法總是被雙下劃線包圍 魔法方法的“魔力”體現在它們總能夠在適當的時候被自動調用。 魔法方法的第一個參數應爲cls(類方法)
或者self(實例方法)。

  • cls:代表一個類的名稱
  • self:代表一個實例對象的名稱

__init__(self[, ...])__new__(cls[, ...])

  • __new__是在一個對象實例化的時候所調用的第一個方法,在調用__init__初始化前,先調用__new__

  • __new__至少要有一個參數cls,代表要實例化的類,此參數在實例化時由 Python 解釋器自動提供,後面的參數直接傳遞給__init__

  • __new__對當前類進行了實例化,並將實例返回,傳給__init__的self。但是,執行了__new__,並不一定會進入__init__,只有__new__返回了,當前類cls的實例,當前類的__init__纔會進入

  • __new__沒有正確返回當前類cls的實例,那__init__是不會被調用的,即使是父類的實例也不行,將沒有__init__被調用。

__init__(self[, ...])__new__(cls[, ...])的傳遞關係:

__new__(cls[, ...])需要設置有返回值,而__init__(self[, ...])可以不設置返回值。

該返回值決定了

  • 實例化對象的初始化(賦值)
  • 之後是否進入__new__(cls[, ...])方法
class A(object):
    def __init__(self, value):
        print("into A __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into A __new__")
        print(cls)
        return object.__new__(cls)


class B(A):
    def __init__(self, value):
        print("into B __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into B __new__")
        print(cls)
        return super().__new__(cls, *args, **kwargs)


b = B(10)

# 結果:
# into B __new__
# <class '__main__.B'>
# into A __new__
# <class '__main__.B'>
# into B __init__

class A(object):
    def __init__(self, value):
        print("into A __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into A __new__")
        print(cls)
        return object.__new__(cls)


class B(A):
    def __init__(self, value):
        print("into B __init__")
        self.value = value

    def __new__(cls, *args, **kwargs):
        print("into B __new__")
        print(cls)
        return super().__new__(A, *args, **kwargs)  # 改動了cls變爲A


b = B(10)

# 結果:
# into B __new__
# <class '__main__.B'>
# into A __new__
# <class '__main__.A'>
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102887712

單例模式:
此處將類的私有屬性賦值cls實例object.__new__(cls)
再返回該值作爲實例化的最終對ab的賦值,並且不會進入__init__(self[, ...])

class Earth:
    pass


a = Earth()
print(id(a))  # 260728291456
b = Earth()
print(id(b))  # 260728291624

class Earth:
    __instance = None  # 定義一個類屬性做判斷

    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = object.__new__(cls)
            return cls.__instance
        else:
            return cls.__instance


a = Earth()
print(id(a))  # 512320401648
b = Earth()
print(id(b))  # 512320401648
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102887712

__new__方法主要是當你繼承一些不可變的 class 時(比如int, str, tuple),提供給你一個自定義這些類的實例化過程的途徑。

此處將str類進行改寫

class CapStr(str):
    def __new__(cls, string):
        string = string.upper()
        return str.__new__(cls, string)


a = CapStr("i love lsgogroup")
print(a)  # I LOVE LSGOGROUP
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102887712

__del__(self)

析構器,當一個對象將要被系統回收之時調用的方法。
即對象用del關鍵字消除時自動調用的方法

__str__(self)

  • 當你打印一個對象的時候,觸發__str__
  • 當你使用%s格式化的時候,觸發__str__
  • str強轉數據類型的時候,觸發__str__

__repr__(self)

  • repr是str的備胎
  • 有__str__的時候執行__str__,沒有實現__str__的時候,執行__repr__
  • repr(obj)內置函數對應的結果是__repr__的返回值
  • 當你使用%r格式化的時候 觸發__repr__

__str__(self) 的返回結果可讀性強。也就是說,__str__ 的意義是得到便於人們閱讀的信息,就像下面的
‘2019-10-11’ 一樣。
__repr__(self) 的返回結果應更準確。怎麼說,__repr__ 存在的目的在於調試,便於開發者使用。

import datetime

today = datetime.date.today()
print(str(today))  # 2019-10-11
print(repr(today))  # datetime.date(2019, 10, 11)
print('%s' %today)  # 2019-10-11
print('%r' %today)  # datetime.date(2019, 10, 11)
————————————————
版權聲明:本文爲CSDN博主「老馬的程序人生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/LSGO_MYP/article/details/102887712

算術運算符與反算術運算符

區別:
a + b
這裏加數是a,被加數是b,因此是a主動,反運算就是如果a對象的__add__()方法沒有實現或者不支持相應的操作,那麼 Python 就會調用b__radd__()方法。

class Nint(int):
    def __radd__(self, other):
        return int.__sub__(other, self) # 注意 self 在後面


a = Nint(5)
b = Nint(3)
print(a + b)  # 8
print(1 + b)  # -2

在這裏插入圖片描述

魔法方法速查

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章