查找资料,基本上判断python对象是否为可调用的函数,有三种方法

使用内置的callable函数

callable(func)

用于检查对象是否可调用,返回True也可能调用失败,但是返回False一定不可调用。

官方文档:https://docs.python.org/3/library/functions.html?highlight=callable#callable

判断对象类型是否是FunctionType

type(func) is FunctionType
# 或者
isinstance(func, FunctionType)

判断对象是否实现 __call__ 方法

hasattr(func, '__call__')

写个小demo,测试下这三种验证方式的区别

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

静态方法,实例调用验证
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__方法,那么其实例也会成为一个可调用对象,其类型为创建这个实例的类,而不是函数或方法。

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()方法会更稳妥。

最新文章

  1. 现代3D图形编程学习-关于本书(译)
  2. Mac 系统环境变量配置
  3. R.java 文件内报错:Underscores can only be used with source level 1.7 or greater。
  4. JavaScript学习笔记之BOM
  5. js原生设计模式——13桥接模式(相同业务逻辑抽象化处理的职责链模式)
  6. 弹框在UC浏览器或者Android机器上会被顶上去
  7. Asp.Net Core基于JWT认证的数据接口网关Demo
  8. C# Note18: 使用wpf制作about dialog(关于对话框)
  9. Liferay7 BPM门户开发之12:acitiviti和liferay用户权限体系集成
  10. Skyline 二次实现单体化模型选择查询示例代码
  11. #js window.open() 父窗口与子窗口的互相调用【转】
  12. 部署Java项目到阿里云服务器主机
  13. hadoop flume 架构及监控的部署
  14. Alpha 冲刺六
  15. emoji表情存储到数据库的方法
  16. ckeditor4.4.6添加代码高亮
  17. 1java异常详解
  18. python 小技巧之获取固定下面包含的某种类型文件的个数
  19. open中的mode
  20. angular package.json中start build

热门文章

  1. Oracle的导入导出 DMP 文件
  2. 》》vue
  3. Sencha Cmd 6 和 Ext JS 6 指南文档(部分官方文档中文翻译)
  4. ThoughtWorks 2017技术雷达
  5. Node.js显示页面
  6. Java读取excel表格
  7. ms sql一些技巧
  8. mybatis插入实体到数据库后获取自增的主键
  9. 自学WPF之Binding(一)
  10. MVC+EF 入门教程(三)