class A(object):def __init__(self):passdef __call__(self):print 'I am a Class'
MyClass = A()
def foo():pass
print hasattr(foo.__class__, 'func_name') # Returns Trueprint hasattr(A.__class__, 'func_name') # Returns False as expected
print hasattr(foo, '__call__') # Returns Trueprint hasattr(A, '__call__') # (!) Returns True while it is not a function
class A():def __call__(self, a,b):print(a,b)def func1(self, a, b):print("[classfunction]:", a, b)@classmethoddef func2(cls, a,b):print("[classmethod]:", a, b)@staticmethoddef func3(a,b):print("[staticmethod]:", a, b)
def func(a,b):print("[function]", a,b)
定义函子:
#(1.1) built-in functionbuiltins_func = open#(1.2) ordinary functionordinary_func = func#(1.3) lambda expressionlambda_func = lambda a : func(a,4)#(1.4) functools.partialpartial_func = functools.partial(func, b=4)
#(2.1) callable class instanceclass_callable_instance = A()#(2.2) ordinary class functionclass_ordinary_func = A.func1#(2.3) bound class methodclass_bound_method = A.func2#(2.4) static class methodclass_static_func = A.func3
定义函数列表和类型列表:
## list of functorsxfuncs = [builtins_func, ordinary_func, lambda_func, partial_func, class_callable_instance, class_ordinary_func, class_bound_method, class_static_func]## list of typextypes = [types.BuiltinFunctionType, types.FunctionType, types.MethodType, types.LambdaType, functools.partial]
判断仿羊函数是可调用的。如您所见,它们都是可调用的。
res = [callable(xfunc) for xfunc in xfuncs]print("functors callable:")print(res)
"""functors callable:[True, True, True, True, True, True, True, True]"""
判断仿函数的类型(types.XXX)。然后,函数的类型并不完全相同。
res = [[isinstance(xfunc, xtype) for xtype in xtypes] for xfunc in xfuncs]
## output the resultprint("functors' types")for (row, xfunc) in zip(res, xfuncs):print(row, xfunc)
"""functors' types[True, False, False, False, False] <built-in function open>[False, True, False, True, False] <function func at 0x7f1b5203e048>[False, True, False, True, False] <function <lambda> at 0x7f1b5081fd08>[False, False, False, False, True] functools.partial(<function func at 0x7f1b5203e048>, b=4)[False, False, False, False, False] <__main__.A object at 0x7f1b50870cc0>[False, True, False, True, False] <function A.func1 at 0x7f1b5081fb70>[False, False, True, False, False] <bound method A.func2 of <class '__main__.A'>>[False, True, False, True, False] <function A.func3 at 0x7f1b5081fc80>"""
def detect_function(obj):return hasattr(obj,"__call__")
In [26]: detect_function(detect_function)Out[26]: TrueIn [27]: callable(detect_function)Out[27]: True
至于内置功能
In [43]: callable(hasattr)Out[43]: True
当再走一步检查是否内置函数或用户定义的函数时
#check inspect.isfunction and type.FunctionTypeIn [46]: inspect.isfunction(detect_function)Out[46]: TrueIn [47]: inspect.isfunction(hasattr)Out[47]: FalseIn [48]: isinstance(detect_function, types.FunctionType)Out[48]: TrueIn [49]: isinstance(getattr, types.FunctionType)Out[49]: False#so they both just applied to judge the user-definded
确定是否builtin function
In [50]: isinstance(getattr, types.BuiltinFunctionType)Out[50]: TrueIn [51]: isinstance(detect_function, types.BuiltinFunctionType)Out[51]: False
# -*- coding: utf-8 -*-import hashlibimport inspect
# calc everything to md5!!def count_md5(content):if isinstance(content, dict):return count_md5([(str(k), count_md5(content[k])) for k in sorted(content.keys())],)elif isinstance(content, (list, tuple)):content = [count_md5(k) for k in content]elif callable(content):return make_callable_hash(content)return calc_md5(str(content))
def calc_md5(content):m2 = hashlib.md5()if isinstance(content, str):m2.update(content.encode("utf8"))else:m2.update(content)return m2.hexdigest()
def make_callable_hash(content):if inspect.isclass(content):h = []for attr in [i for i in sorted(dir(content)) if not i.startswith("__")]:v = getattr(content, attr)h.append(count_md5(v))
return calc_md5("".join(h))
return calc_md5(content.__name__)