天天看點

python魔法方法詳解_Python魔術方法詳解

寫這個的初衷主要是因為網上充斥的大量的假冒僞劣解釋說明

好歹自己試一試再寫文章啊! 真的是誤人子弟

例如: __ 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 (簡書)

python魔法方法詳解_Python魔術方法詳解

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 (簡書)

python魔法方法詳解_Python魔術方法詳解

__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