魔法方法總是被雙下劃線包圍 魔法方法的“魔力”體現在它們總能夠在適當的時候被自動調用。 魔法方法的第一個參數應爲
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)
再返回該值作爲實例化的最終對a
,b
的賦值,並且不會進入__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