python中為什麼要使用魔法函式__call__?怎麼用?

影片連結https://zhuanlan。zhihu。com/p/562586782

什麼是魔法函式?

是以雙下劃線開頭和雙下劃線結尾命名的特殊函式,不需要開發者呼叫,由Python直譯器呼叫。

可呼叫物件的概念:在python中,能夠使用名稱加()執行的物件都是可呼叫物件。

很顯然所有的函式都是可呼叫物件,那麼類例項物件是呼叫物件嗎?

實驗下:

python中為什麼要使用魔法函式__call__?怎麼用?

報錯了,錯誤資訊提示Student物件不是一個可呼叫物件。

檢測一個物件是否可呼叫還可以使用callable函式。

python中為什麼要使用魔法函式__call__?怎麼用?

返回False,也說明了Student物件不是一個可呼叫物件。

那麼這麼才能拿讓類例項物件變成可呼叫物件呢?

只要類實現了魔法函式__call__即可,我們試下。

python中為什麼要使用魔法函式__call__?怎麼用?

很明顯實現了__call__之後,Student物件變成了可呼叫物件;

其中__call__不需要要開發者來呼叫,它屬於特殊函式,直譯器會去呼叫的。

為什麼要將了轉化成可呼叫物件呢?哪些場景使用?

可呼叫物件,讓類例項物件能夠像函式一樣接收引數,好處是更加簡潔,不需要使用 物件。方法()。

使用場景:

1。在一些驗證器中使用,舉個例子:

import re

class PhoneValidator():

‘’‘DEC:手機號格式合法驗證器’‘’

def __call__(self, *args, **kwargs):

reg = ‘^1(3[0-9]|4[5,7]|5[0,1,2,3,5,6,7,8,9]|6[2,5,6,7]|7[0,1,7,8]|8[0-9]|9[1,8,9])\d{8}$’

phone = args[0]

if not re。match(reg, phone):

print(“phone is validate。”)

else:

print(“phone is invalidate。”)

phone_validator = PhoneValidator()

phone_validator(“13735468254”)

phone_validator(“10735468254”)

結果:

phone is invalidate。

phone is validate。

你可能會為那為什麼不使用函式呢?類有更好的擴充套件性,你可能還需要做其他的事情呢?

所以我們需要的是函式但是又不僅僅只是函式。

2。在類裝飾器中使用,在裝飾器章節詳細看下類裝飾器。

‘’‘

描述:雖然裝飾器是用類實現的,但是最終用來替換原函式的物件,仍然是一個處在__call__方法裡的閉包函式

’‘’

import time

import random

from functools import wraps

class Timer:

“”“裝飾器:列印函式的耗時

:param print_args:是否打印發發那個發名和引數,預設為False

”“”

def __init__(self,print_args):

self。print_args = print_args

def __call__(self, func):

@wraps(func)

def decorated(*args, **kwargs):

‘’‘

desc:jdhfksjdf

@param:args,

’‘’

st = time。perf_counter()

ret = func(*args, **kwargs)

if self。print_args:

print(f‘“{func。__name__}”,args:{args},kwargs:{kwargs}’)

print(“time cost:{} seconds”。format(time。perf_counter()-st))

return ret

return decorated

@Timer(print_args=True)

def random_sleep():

print(“random”)

if __name__ == ‘__main__’:

random_sleep()