Python學習筆記(十四):類特殊成員
類的特殊屬性和特殊方法
- Python學習筆記(十四):類特殊成員
- 一.類特殊成員
- 二.__new__()
- 三.__repr__()
- 四.__del__()
- Python的垃圾回識訓制
- 五.__dir__()
- 六.__dict__屬性
一.類特殊成員
以雙下劃線 "__" 開頭和結尾命名的成員(屬性和方法),都被稱為類的特殊成員(特殊屬性和特殊方法)
Python類中的特殊成員,不能在類的外部直接呼叫,可以用類中的普通方法呼叫和修改,可以對類的特殊方法進行重寫,實作特殊的功能
二.new()
__new__() 是負責創建類實體的靜態方法
無需使用 staticmethod 裝飾器修飾,優先 __init__() 初始化方法被呼叫
覆寫__new__()將會使用合適的引數呼叫其父類的super().__new__(),并在回傳之前修改實體
__new__(*args, **kwargs)
Create and return a new object. See help(type) for accurate signature.
class demoClass:
instances_created = 0
def __new__(cls,*args,**kwargs):
print("__new__():",cls,args,kwargs)
instance = super().__new__(cls)
instance.number = cls.instances_created
cls.instances_created += 1
return instance
def __init__(self,attribute):
print("__init__():",self,attribute)
self.attribute = attribute
test1 = demoClass("abc")
test2 = demoClass("xyz")
print(test1.number,test1.instances_created)
print(test2.number,test2.instances_created)
__new__(): <class '__main__.demoClass'> ('abc',) {}
__init__(): <__main__.demoClass object at 0x02519690> abc
__new__(): <class '__main__.demoClass'> ('xyz',) {}
__init__(): <__main__.demoClass object at 0x025196F0> xyz
0 2
1 2
__new__()通常會回傳該類的一個實體,有時也可能會回傳其他類的實體,如果發生了這種情況,會跳過對__init__()方法的呼叫
class nonZero(int):
def __new__(cls,value):
return super().__new__(cls,value) if value != 0 else None
def __init__(self,skipped_value):
print("__init__()") #__new__方法回傳None會跳過此方法
super().__init__()
print(type(nonZero(-10)))
print(type(nonZero(0)))
__init__()
<class '__main__.nonZero'>
<class 'NoneType'>
如果__new__方法回傳None,則__init__方法不會被執行,并且回傳值只能呼叫父類中的__new__方法
__new__方法的第一個引數是這個類,其余的引數在呼叫成功后全部傳遞給__init__方法初始化
class A:
pass
class B(A):
def __new__(cls):
print("__new__方法被執行")
return super().__new__(cls)
def __init__(self):
print("__init__方法被執行")
b = B()
__new__方法是傳入類(cls),__init__方法傳入類的實體化物件(self)
__new__方法回傳的值是一個實體化物件,如果__new__方法回傳None,則__init__方法不會被執行,并且回傳值只能呼叫父類中的__new__方法,而不能呼叫毫無關系的類的__new__方法
在__init__() 不夠用的時候使用 __new__()
__new__()不限于回傳同一個類的實體,很容易被濫用,需謹慎使用
Python中大量使用 __new__() 方法且合理的,是 MetaClass 元類
關于MetaClass 元類見之前筆記
Python學習筆記(十二):類和物件
三.repr()
直接輸出類的實體化物件
class test:
pass
TEST = test()
print(TEST)
<__main__.test object at 0x02919670>
默認情況下,得到的資訊只有“類名+object at+記憶體地址”,對了解該實體化物件幫助不大
當輸出某個實體化物件時,呼叫的就是該物件的__repr__()方法,輸出的是該方法的回傳值
所以print(TEST) 等同于print(TEST.__repr__()),輸出的記憶體地址可能不同
Python中的每個類都包含__repr__() 方法
因為object 類包含 __reper__() 方法,而Python中所有的類都直接或間接繼承自 object 類
默認情況下,__repr__() 會回傳和呼叫者有關的 “類名+object at+記憶體地址”資訊,可以通過在類中重寫這個方法,實作輸出想要的資訊
class test:
def __init__(self):
self.name = "youchanwill"
self.add = "you.com"
def __repr__(self):
return "test[name="+ self.name +",add=" + self.add +"]"
TEST = test()
print(TEST)
test[name=youchanwill,add=you.com]
__repr__() 方法默認情況下會回傳當前物件的“類名+object at+記憶體地址”,如果對該方法進行重寫,可以為其制作自定義的描述資訊
四.del()
__del__() 方法用來銷毀實體化物件
之前創建的類實體化物件后續不再使用,最好在適當位置手動將其銷毀,釋放其占用的記憶體空間(垃圾回收,簡稱GC)
大多數情況下,不需要手動進行垃圾回收,Python有自動的垃圾回識訓制,能自動將不需要使用的實體物件進行銷毀
手動和自動都會呼叫 __del__() 方法
class test:
def __init__(self):
print("呼叫__init__() 方法構造物件")
def __del__(self):
print("呼叫__del__() 銷毀物件,釋放其空間")
TEST = test()
del TEST
呼叫__init__() 方法構造物件
呼叫__del__() 銷毀物件,釋放其空間
Python的垃圾回識訓制
Python采用自動參考計數(ARC)的方式實作垃圾回識訓制
1.每個Python物件都會配置一個計數器,初始實體物件的計數器值都為 0,如果有變數參考該實體物件,其計數器的值會加 1,依次類推
2.每當一個變數取消對該實體物件的參考,計數器會減 1
3.如果一個物件的的計數器值為 0,表明沒有變數參考該物件,說明程式不再需要,自動呼叫 __del__() 方法將其回收
class test:
def __init__(self):
print("呼叫__init__() 方法構造物件")
def __del__(self):
print("呼叫__del__() 銷毀物件,釋放其空間")
TEST = test()
test1 = TEST #添加一個參考TEST物件的實體物件
del TEST
print("****")
呼叫__init__() 方法構造物件
****
1.構建TEST實體物件時先用test()呼叫該類中的 __init__()方法構造出一個該類的物件(計數器為 0)
2.用TEST這個變數作為所建實體物件的參考(計數器值+1)
3.又有一個test1變數參考TEST(相當于參考 CLanguage()),此時計數器再+1
4.呼叫del TEST陳述句,只會導致計數器減 1 ,因為計數器值不為 0,因此 不會執行 __del__() 方法
class test:
def __init__(self):
print("呼叫__init__() 方法構造物件")
def __del__(self):
print("呼叫__del__() 銷毀物件,釋放其空間")
TEST = test()
test1 = TEST #添加一個參考TEST物件的實體物件
del TEST
print("****")
del test1
print("----")
呼叫__init__() 方法構造物件
****
呼叫__del__() 銷毀物件,釋放其空間
----
執行 del test1 陳述句時,計數器變為 0,對于計數器為 0 的實體物件,自動將其視為垃圾進行回收
如果重寫子類的 __del__() 方法(父類為非 object 的類),必須顯式呼叫父類的 __del__() 方法,這樣才能保證回收子類物件時,其占用的資源能被徹底釋放
class test:
def __del__(self):
print("呼叫父類__del__() 方法")
class test1(test):
def __del__(self):
print("呼叫子類__del__() 方法")
test2 = test1()
del test2
呼叫子類__del__() 方法
呼叫父類的 __del__()方法,保證回收子類物件時,其占用的資源能被徹底釋放
test3 = test()
del test3
呼叫子類__del__() 方法
呼叫父類__del__() 方法
五.dir()
dir() 函式,回傳一個包含有所有屬性名和方法名的有序串列
通過 dir() 函式,不僅僅輸出本類中新添加的屬性名和方法,還會輸出從父類繼承得到的屬性名和方法名
dir() 函式的內部實作,是在呼叫引數物件 __dir__() 方法的基礎上,對該方法回傳的屬性名和方法名做了排序
class test:
def __init__ (self,):
self.name = "youchanwill"
self.add = "you.com"
def say():
pass
TEST = test()
print(dir(TEST))
class test:
def __init__ (self,):
self.name = "youchanwill"
self.add = "you.com"
def say():
pass
TEST = test()
print(TEST.__dir__())
使用 __dir__() 方法和 dir() 函式輸出的資料相同,順序不同
六.__dict__屬性
在Python類的內部,類屬性還是實體屬性,都以字典的形式進行存盤,其中屬性名作為key,值作為該key對應的value
__dict__ 屬性可以用類名或者類的實體物件來呼叫
用類名直接呼叫 __dict__,會輸出該由類中所有類屬性組成的字典
用類的實體物件呼叫 __dict__,會輸出由類中所有實體屬性組成的字典
class test:
a = 10
b = 16
def __init__ (self,):
self.name = "youchanwill"
self.add = "you.com"
print(test.__dict__) #通過類名呼叫__dict__
{'a': 10, '__dict__': <attribute '__dict__' of 'test' objects>, '__module__': '__main__', '__init__': <function test.__init__ at 0x02A97270>, '__weakref__': <attribute '__weakref__' of 'test' objects>, 'b': 16, '__doc__': None}
TEST = test() #通過類的實體物件呼叫 __dict__
print(TEST.__dict__)
{'name': 'youchanwill', 'add': 'you.com'}
具有繼承關系的父類和子類,父類有自己的 __dict__,子類也有自己的 __dict__,不會包含父類的 __dict__
由類的實體物件呼叫 __dict__ 屬性獲取的字典,可以使用字典的方式對其中實體屬性的值進行修改
class test:
a = 10
b = 16
def __init__ (self):
self.name = "youchanwill"
self.add = "you.com"
TEST = test()
print(TEST.__dict__) #通過類實體物件呼叫 __dict__
TEST.__dict__['name'] = "chanwill"
print(TEST.name)
print(TEST.__dict__)
{'name': 'youchanwill', 'add': 'you.com'}
chanwill
{'name': 'chanwill', 'add': 'you.com'}
無法通過類似的方式修改類變數的值
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/260055.html
標籤:python
上一篇:PAT 1034 Head of a Gang (30 分)————Python
下一篇:python之星河戰爭游戲
