寫這個的初衷主要是因為網上充斥的大量的假冒僞劣解釋說明
好歹自己試一試再寫文章啊! 真的是誤人子弟
例如: __ getattr__:擷取一個不存在的屬性時調用的方法 事實上擷取任何屬性的時候都會調用這個方法(包括存在和不存在的屬性)
1. __init __ 和 __new __
__init__(self)
這個方法是一個對象方法,它主要是用來建構對象屬性的
當對象建立的時候,就需要給這個對象賦予屬性 這個時候,這個對象就開始自動調用了
by tokiea (簡書)
class A:
def __init__(self):
print('開始給對象賦予屬性了')
a = A()
__________________________________
`開始給對象賦予屬性了`
def __new__(cls, *args, **kwargs):
這個方法是一個類方法,它用來建立對象的
也就是對象建立的時候最先調用的方法
通常會用來做單例模式和對象建立計數
*args, **kwargs是用來接收和傳遞建立對象時的參數
by tokiea (簡書)
class A:
def __init__(self, name, age=1): # 執行個體方法
print('開始給對象賦予屬性了')
self.name = name
self.age = age
def __new__(cls, *args, **kwargs): # 類方法
print('開始建立對象了')
print('我是參數args', args)
print('我是參數kwargs', kwargs)
return object.__new__(cls)
# 必須要有傳回值 傳回建立出來的執行個體
a = A('小明', age=2)
__________________________________
`開始建立對象了`
`我是參數args ('小明',)`
`我是參數kwargs {'age': 2}`
`開始給對象賦予屬性了`
2.__ getattr__ 和 __ setattr__
很好了解的字面意思
擷取屬性和設定屬性時調用的方法
__getattr__(self, item)
當擷取執行個體化後的對象屬性時,會自動調用的方法,好像除了阻止别人直接擷取屬性之外沒特别大的用處了
用了這個方法之後,所有的執行個體對象屬性都是需要在這裡傳回的,否則就是None值
by tokiea (簡書)

class A:
def __init__(self, name, age=1):
self.name = name # 我想多湊幾個字數
self.age = age
def __getattr__(self, item):
print('報告老大,有人在調用我的屬性', item)
if item =='name':
return '不告訴你'
a = A('小明', age=2)
print(a.name)
print(a.age)
__________________________________
`報告老大,有人在調用我的屬性 name`
`不告訴你`
`報告老大,有人在調用我的屬性 age`
`None`
__setattr__(self, key, value):
這個方法比__getattr __要好用一些
設定屬性的時候調用(當然初始化的時候也會調用一次)
可以用來判斷屬性設定的值(也可以改變即将設定的屬性值)
by tokiea (簡書)
class A:
def __init__(self, name):
self.name = name # 我想多湊幾個字數
self.age = 1
def __setattr__(self, key, value):
print('開始給執行個體對象指派了', key, value)
if key == 'age' and value:
# 這個可以做判斷或者改變指派的操作
if isinstance(value, int):
pass
else:
print('指派錯誤,請填整數類型')
a = A('小明')
a.age = 10
a.age = '十八'
__________________________________
`開始給執行個體對象指派了 name 小明`
`開始給執行個體對象指派了 age 1`
`開始給執行個體對象指派了 age 10`
`開始給執行個體對象指派了 age 十八`
`指派錯誤,請填整數類型`
3. __ enter __和 __ exit __
__enter__(self)
__exit__(self, exc_type, exc_val, exc_tb)
這兩個方法就是用with的時候使用的,上下文管理
而且是 都要有
否則就會報錯,差不多就像幹将和莫邪,楊過和大雕,缺一不可
三個參數:
exc_type 錯誤類型
exc_val 錯誤原因
exc_tb 錯誤發生的記憶體位址
by tokiea (簡書)
class A:
def __init__(self, name):
self.name = name # 我想多湊幾個字數
self.age = 1
def __enter__(self):
print('我要進去了,嘿嘿嘿')
def __exit__(self, exc_type, exc_val, exc_tb):
print(exc_type)
print(exc_val)
print(exc_tb)
print('我要出去了')
a = A('小明')
with a:
print('我進來了')
a.age = 1/0 # 0不能做被除數 會報錯
__________________________________
`Traceback (most recent call last):`
`我要進去了,嘿嘿嘿`
`我進來了`
`File ".....................py", line 18, in `
`a.age = 1/0`
`ZeroDivisionError: division by zero`
``
`division by zero`
``
`我要出去了`
4. __del __
__del__(self)
就是被删除的時候調用的方法
python自帶垃圾回收 當對象沒有引用的時候就會自動觸發垃圾回收 自動調用 __del __ 方法
by tokiea (簡書)
class A:
def __del__(self):
print('啊!我被删除了')
a = A()
del a # 這句 可有可無 因為程式運作結束會自動觸發
__________________________________
`啊!我被删除了`
PS 剛好看研究了一下描述符 也寫一點吧
__get __ , __set __ 和 __delete __
__get__(self, instance, owner)
看參數 instance 執行個體 owner 擁有者 就知道一個是擁有者 一個是被擁有 肯定需要兩個對象
class A:
def __get__(self, instance, owner):
print('A:我被(執行個體)%s調用了,它屬于 %s 類'%(instance,owner))
class B:
a = A()
b=B()
B.a
b.a
__________________________________
`A:我被(執行個體)None調用了,它屬于 類`
`A:我被(執行個體)<__main__.B object at 0x0000028F0BC00CC0>調用了,它屬于 類`
__set__(self, instance, value)
參數 一個是執行個體 一個是值
class A:
def __set__(self, instance, value):
print('我是A:我監聽到了:%s被執行個體:%s設定成了屬性' % (value, instance))
class B:
pass
a = A()
b = B()
B.a = a # 把執行個體對象a 先指派給 類對象B 的類屬性 a
b.a = 12345 # 再把 12345 指派給執行個體對象b 的a
print(B.a)
print(b.a)
__________________________________
`我是A:我監聽到了:12345被執行個體:<__main__.B object at 0x0000016923F90CC0>設定成了屬性`
`<__main__.A object at 0x0000016923F90C88>`
`<__main__.A object at 0x0000016923F90C88>`
最後發現不管是執行個體對象b 還是類對象B 它們的a屬性都是a執行個體 即使執行個體b進行了重新指派12345的操作,也沒能改變執行個體b的a屬性
我想知道為什麼 求教大佬
by tokiea (簡書)

__delete__(self, instance)
class A:
def __delete__(self, instance):
print('執行個體對象%s把我删除了'%instance)
class B:
pass
a = A()
b = B()
B.a = a # 把執行個體對象a 先指派給 類對象B 的類屬性 a
b.a = 12345 # 再把 12345 指派給執行個體對象b 的a
del b.a
print(b.a)
__________________________________
`執行個體對象<__main__.B object at 0x0000029510180CC0>把我删除了`
`<__main__.A object at 0x0000029510180C88>`
發現最後a執行個體沒有被b執行個體删除 而是隻調用了a的__delete __方法
by tokiea (簡書)
未完待續 -- tokiea