判断python对象是否可调用的三种方式及其区别详解


Posted in Python onJanuary 31, 2019

查找资料,基本上判断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()方法会更稳妥。

以上这篇判断python对象是否可调用的三种方式及其区别详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 中的Selenium异常处理实例代码
May 03 Python
把pandas转换int型为str型的方法
Jan 29 Python
使用python实现mqtt的发布和订阅
May 05 Python
详解Matplotlib绘图之属性设置
Aug 23 Python
python kafka 多线程消费者&amp;手动提交实例
Dec 21 Python
pytorch标签转onehot形式实例
Jan 02 Python
matplotlib绘制多子图共享鼠标光标的方法示例
Jan 08 Python
PyCharm 解决找不到新打开项目的窗口问题
Jan 15 Python
Python中正则表达式对单个字符,多个字符和匹配边界等使用
Jan 27 Python
从Pytorch模型pth文件中读取参数成numpy矩阵的操作
Mar 04 Python
详解Django的MVT设计模式
Apr 29 Python
Python超详细分步解析随机漫步
Mar 17 Python
python3使用QQ邮箱发送邮件
May 20 #Python
Python实现FTP弱口令扫描器的方法示例
Jan 31 #Python
对python条件表达式的四种实现方法小结
Jan 30 #Python
python从子线程中获得返回值的方法
Jan 30 #Python
学生信息管理系统Python面向对象版
Jan 30 #Python
python学生管理系统开发
Jan 30 #Python
Python修改文件往指定行插入内容的实例
Jan 30 #Python
You might like
PHP 循环列出目录内容的函数代码
2010/05/26 PHP
在smarty模板中使用PHP函数的方法
2011/04/23 PHP
编写安全 PHP应用程序的七个习惯深入分析
2013/06/08 PHP
PHP提示Warning:phpinfo() has been disabled函数禁用的解决方法
2014/12/17 PHP
PHP访问数据库集群的方法小结
2016/03/14 PHP
php断点续传之文件分割合并详解
2016/12/13 PHP
PHP框架Laravel中使用UUID实现数据分表操作示例
2018/05/30 PHP
jQuery 使用手册(三)
2009/09/23 Javascript
JS 文件本身编码转换 图文教程
2009/10/12 Javascript
写得不错的jquery table鼠标经过变色代码
2013/09/27 Javascript
js图片向右一张张滚动效果实例代码
2013/11/23 Javascript
让IE8浏览器支持function.bind()方法
2014/10/16 Javascript
基于javascript实现九九乘法表
2016/03/27 Javascript
AnjularJS中$scope和$rootScope的区别小结
2016/09/18 Javascript
实例浅析js的this
2016/12/11 Javascript
JS实现百度搜索接口及链接功能实例代码
2018/02/02 Javascript
使用webpack打包后的vue项目如何正确运行(express)
2018/10/26 Javascript
JS实现判断数组是否包含某个元素示例
2019/05/24 Javascript
js图片查看器插件用法示例
2019/06/22 Javascript
Vue 实现显示/隐藏层的思路(加全局点击事件)
2019/12/31 Javascript
Python基类函数的重载与调用实例分析
2015/01/12 Python
在Python中使用HTML模版的教程
2015/04/29 Python
python散点图实例之随机漫步
2018/08/27 Python
用Python画小女孩放风筝的示例
2019/11/23 Python
python中time包实例详解
2021/02/02 Python
轻松掌握CSS3中的字体大小单位rem的使用方法
2016/05/24 HTML / CSS
使用HTML5 IndexDB存储图像和文件的示例
2018/11/05 HTML / CSS
Perry Ellis官网:美国男士品味服装
2016/12/09 全球购物
使用索引有什么好处
2016/07/27 面试题
Windows和Linux动态库应用异同
2016/07/28 面试题
应聘教师自荐信
2013/10/12 职场文书
趣味体育活动方案
2014/02/08 职场文书
电子信息工程专业推荐信
2014/02/14 职场文书
农村党支部书记党群众路线四风问题整改措施
2014/09/26 职场文书
2015年学校工作总结范文
2015/04/20 职场文书
银行服务理念口号
2015/12/25 职场文书