查找资料,基本上判断python对象是否为可调用的函数,有三种方法
使用内置的callable函数
1
|
callable (func)
|
用于检查对象是否可调用,返回True也可能调用失败,但是返回False一定不可调用。
官方文档:https://docs.python.org/3/library/functions.html?highlight=callable#callable
判断对象类型是否是FunctionType
1
2
3
|
type (func) is FunctionType
# 或者
isinstance (func, FunctionType)
|
判断对象是否实现 __call__ 方法
1
|
hasattr (func, '__call__' )
|
写个小demo,测试下这三种验证方式的区别
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
from types import FunctionType
__author__ = 'blackmatrix'
class ClassA:
@staticmethod
def func_a():
pass
@classmethod
def func_b( cls , arg):
pass
def func_c( self , arg):
pass
def func_d():
pass
if __name__ = = '__main__' :
class_a = ClassA()
print ( '静态方法,实例调用验证' )
print ( "callable(class_a.func_a) result: {result}" . format (result = callable (class_a.func_a)))
print ( "type(class_a.func_a) is FunctionType result: {result}" . format (result = type (class_a.func_a) is FunctionType))
print ( "hasattr(class_a.func_a, '__call__') result: {result}" . format (result = hasattr (class_a.func_a, '__call__' )))
print ( '静态方法,类调用验证' )
print ( "callable(ClassA.func_a) result: {result}" . format (result = callable (ClassA.func_a)))
print ( "type(ClassA.func_a) is FunctionType result: {result}" . format (result = type (ClassA.func_a) is FunctionType))
print ( "hasattr(ClassA.func_a, '__call__') result: {result}" . format (result = hasattr (ClassA.func_a, '__call__' )))
print ( '类方法验证' )
print ( "callable(ClassA.func_b) result: {result}" . format (result = callable (ClassA.func_b)))
print ( "type(ClassA.func_b) is FunctionType result: {result}" . format (result = type (ClassA.func_b) is FunctionType))
print ( "hasattr(ClassA.func_b, '__call__') result: {result}" . format (result = hasattr (ClassA.func_b, '__call__' )))
print ( '实例方法验证' )
print ( "callable(class_a.func_c) result: {result}" . format (result = callable (class_a.func_c)))
print ( "type(class_a.func_c) is FunctionType result: {result}" . format (result = type (class_a.func_c) is FunctionType))
print ( "hasattr(class_a.func_c, '__call__') result: {result}" . format (result = hasattr (class_a.func_c, '__call__' )))
print ( '函数验证' )
print ( "callable(func_d) result: {result}" . format (result = callable (func_d)))
print ( "type(func_d) is FunctionType result: {result}" . format (result = type (func_d) is FunctionType))
print ( "hasattr(func_d, '__call__') result: {result}" . format (result = hasattr (func_d, '__call__' )))
|
通过运行结果,发现三种方法的验证结果并不相同。
主要是type(func) is FunctionType方法,在验证类方法和实例方法时,会返回False,
从调试的结果上看,实例方法,和类方法的类型都是<class 'method'>,不是FunctionType,所以会返回False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
静态方法,实例调用验证
callable (class_a.func_a) result: True
type (class_a.func_a) is FunctionType result: True
hasattr (class_a.func_a, '__call__' ) result: True
静态方法,类调用验证
callable (ClassA.func_a) result: True
type (ClassA.func_a) is FunctionType result: True
hasattr (ClassA.func_a, '__call__' ) result: True
类方法验证
callable (ClassA.func_b) result: True
type (ClassA.func_b) is FunctionType result: False
hasattr (ClassA.func_b, '__call__' ) result: True
实例方法验证
callable (class_a.func_c) result: True
type (class_a.func_c) is FunctionType result: False
hasattr (class_a.func_c, '__call__' ) result: True
函数验证
callable (func_d) result: True
type (func_d) is FunctionType result: True
hasattr (func_d, '__call__' ) result: True
|
因为Python中分为函数(function)和方法(method),函数是Python中一个可调用对象(用户定义的可调用对象,及lambda表达式创建的函数,都是函数,其类型都是FunctionType),方法是一种特殊的类函数。
官方文档中,对于method的定义:
Methods are always bound to an instance of a user-defined class
类方法和类进行绑定,实例方法与实例进行绑定,所以两者的类型都是method。
而静态方法,本身即不和类绑定,也不和实例绑定,不符合上述定义,所以其类型应该是function。
其中还有需要注意的是,如果一个类实现了__call__方法,那么其实例也会成为一个可调用对象,其类型为创建这个实例的类,而不是函数或方法。
1
2
3
4
5
6
7
8
9
|
class TheClass:
def __call__( self , * args, * * kwargs):
return self
if __name__ = = '__main__' :
the_class = TheClass()
# True
print ( 'class_instance callable {callable} ' . format ( callable = callable (the_class)))
|
所以通过类型去判断Python对象是否可调用,需要同时判断是函数(FunctionType)还是方法(MethodType),或者类是否实现__call__方法。
如果只是单纯判断python对象是否可调用,用callable()方法会更稳妥。
以上这篇判断python对象是否可调用的三种方式及其区别详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://www.cnblogs.com/blackmatrix/p/6831048.html