python高阶函数:__init__ , __call__ ,装饰器, hook 的应用和区别

一  :__init__()__call__()的区别如下: 

1. __init__()的作用是初始化某个类的一个实例。 
2. __call__()的作用是使实例能够像函数一样被调用,同时不影响实例本身的生命周期(__call__()不影响一个实例的构造和析构)。但是__call__()可以用来改变实例的内部成员的值。

class Mark(object):

def __init__(self, str):
print("__init__", str)

def __call__(self, func):
print("__call__", func)


mark=Mark("str") # 声明一个实例,调用__init__传参str
mark("func") # 引用该类实例,调用__call__传参func

-----------------------------
输出结果为:
__init__str
__call__func



二: 装饰器和语法糖

装饰器版本:
def func():
  print("被装饰的函数")
def add_way(func):  # 1
def wrapper(): # 3
print('这是新功能') # 6
func() # 7

return wrapper # 4

func = add_way(func) # 2
func()

语法糖版本:
def add_way(func):
def wrapper():
print('这是新功能')
func()

return wrapper

@add_way
def func():
print("语法糖版本:被装饰函数")

func()

Python提供了一个 语法糖 "@" 来帮我们完成func = add_way(func)这件事情! 所以“@”和__call__组合使用时,已经完成了__call__的逻辑并返回该函数,而不是在调用函数时
class Mark:

def __init__(self, module: str = ''):
print("__init__:", module)

def __call__(self, func):
print("__call__:", func.__name__)
return func


class Api:
mark = Mark


api = Api()


class Demo:

@staticmethod
@api.mark(module='demo1')
def demo1():
print("demo1()被调用")

@staticmethod
@api.mark(module='demo2')
def demo2():
print("demo2()被调用")


d = Demo()
d.demo1()
d.demo2()


-------------------
结果:

__init__: demo1
__call__: demo1
__init__: demo2
__call__: demo2
demo1()被调用
demo2()被调用

-------------------

 

带参数的装饰器

# 带参数的装饰器

def post(path=''):
def decorator(func):
def wrapper(*args, **kwargs):
print('path:', path)
func(*args, **kwargs)

return wrapper

return decorator


# () 就是调用了,会decorator返回实例,会初始化,这个decorator实例可以调用,生成wrapper实例
@post('/login')
def test_login(name, pwd):
print('name:', name)
print('pwd:', pwd)
print(test_login.__name__) # 最后是个wrapper实例


def test_login2(name, pwd):
print('name:', name)
print('pwd:', pwd)
print(test_login2.__name__)


test_login('wjz', '111')
test_login2('wjz', '111')

# 看到这个代码是不是又有些疑问,内层的decorator函数的参数func是怎么传进去的?和上面一般的装饰器不大一样啊。
# 其实道理是一样的,将其@语法去除,恢复函数调用的形式一看就明白了:
# 传入装饰器的参数,并接收返回的decorator函数
# decorator = post("/login")
# 传入test_login函数
# wrapper = decorator(test_login)
# 调用装饰器函数
# wrapper("'wjz', '111'")

三 : hook函数

 

原文地址:https://www.cnblogs.com/sylarwang/p/13502770.html