python 将有参函数转化为无参函数

一、说明
这个过程类似“打包”,在一些游戏开发场景中,常常有将函数延后执行或者需要将函数作为回调入参,这时函数需要带参就不好处理了。例如:

 1 import Functor
 2 
 3 sUser = '用户名'
 4 iAcct = 123
 5 sPass = '******'
 6  
 7 def notify(sUser, bSuc):
 8     if bSuc:
 9         print sUser + '成功登录'
10 
11 '''login(iAcct, sPass, pfunCB)负责执行登录过程,
12 在结束时调用pfunCB(bSuc)通知登录结果
13 '''
14 pfunCB = Functor(notify, sUser)
15 login(iAcct, sPass, pfunCB)

上面是一个登录过程Functor就是要实现的打包器,将notify(sUser, bSuc)打包为只需一个入参的pfunCB(bSuc)

二、python的方法相关知识

1.python的方法是对象

方法的调用实质上是调用方法实例的__call__(),
因此,把对象变为可调用项,只需添加__call__()。例:

1 class Fun():
2     def __init__(self):
3         pass
4         
5     def __call__(self, obj):
6         print obj
7 
8 a = Fun()
9 a(67890)  # 等同a.__call__(67890)


2.实例方法的关键属性


对于实例方法的函数对象,我们可以通过__func__或im_func属性获取原始的函数对象。
下面的例子中,Functor还引用了实例方法的实例对象,因为当实例被回收时,我们不希望再调用该实例的方法,需要兼容这种情况。当然,更合理的做法是在代码中规避这种用法,不合理的使用常常导致bug的产生。

可以通过__self__或im_self获取实例方法的实例对象,类方法也可以这样获取到类实例(注意类方法的类实例不是im_class属性)。

三、Functor的实现
=======================Functor.py=======================

 1 # -*- coding:utf-8 -*-
 2 
 3 import types
 4 import weakref
 5 
 6 class Functor():
 7     def __init__(self, _fn, *args, **kwargs):
 8         if not callable(_fn):
 9             raise Exception('object is unable to call')
10             
11         if isinstance(_fn, types.MethodType):
12             # 实例方法,类方法
13             # 弱引用实例对象,使Functor不影响对象的生命周期
14             self.m_wrObj = weakref.ref(_fn.__self__)
15             self.m_Func = _fn.im_func
16             self.m_bIsMethodType = True
17         else:
18             # 非实例方法
19             self.m_wrObj = None
20             self.m_Func = _fn
21             self.m_bIsMethodType = False
22             
23         self.m_args = args
24         self.m_kwargs = kwargs
25         
26     def __call__(self, *args, **kwargs):
27         curkwargs = dict(self.m_kwargs)
28         curkwargs.update(kwargs)
29         if not self.m_bIsMethodType:
30             return self.m_Func(*(self.m_args + args), **kwargs)
31         else:
32             obj = self.m_wrObj()
33             if obj is None:
34                 return None
35             return self.m_Func(*((obj,) + self.m_args + args), **kwargs)
36 
37 #test len('abc')
38 len_no_arg = Functor(len, 'abc')
39 print len_no_arg()

猜你喜欢

转载自www.cnblogs.com/fu-feng/p/13193355.html