判断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的__builtin__模块中的一些要点知识
May 02 Python
Python实现读取邮箱中的邮件功能示例【含文本及附件】
Aug 05 Python
Python使用回溯法子集树模板获取最长公共子序列(LCS)的方法
Sep 08 Python
python微信好友数据分析详解
Nov 19 Python
对Python生成汉字字库文字,以及转换为文字图片的实例详解
Jan 29 Python
python使用递归的方式建立二叉树
Jul 03 Python
Python如何计算语句执行时间
Nov 22 Python
Python 识别12306图片验证码物品的实现示例
Jan 20 Python
Python的Django框架实现数据库查询(不返回QuerySet的方法)
May 19 Python
带你学习Python如何实现回归树模型
Jul 16 Python
Python+OpenCV检测灯光亮点的实现方法
Nov 02 Python
只用20行Python代码实现屏幕录制功能
Jun 02 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版(2)
2006/10/09 PHP
PHP编程一定要改掉的5个不良习惯
2020/09/18 PHP
利用JQuery的load函数动态加载其它页面的内容的实现代码
2010/12/14 Javascript
ASP.NET jQuery 实例6 (实现CheckBoxList成员全选或全取消)
2012/01/13 Javascript
js读写cookie实现一个底部广告浮层效果的两种方法
2013/12/29 Javascript
浅析js中的浮点型运算问题
2014/01/06 Javascript
JQuery性能优化的几点建议
2014/05/14 Javascript
一个字符串反转函数可实现字符串倒序
2014/09/15 Javascript
JQuery中层次选择器用法实例详解
2015/05/18 Javascript
Jquery基础教程之DOM操作
2015/08/19 Javascript
javascript中错误使用var造成undefined
2016/03/31 Javascript
使用vue.js开发时一些注意事项
2016/04/27 Javascript
jquery实现全选、全不选以及单选功能
2017/03/23 jQuery
jQuery实现jQuery-form.js实现异步上传文件
2017/04/28 jQuery
webpack配置打包后图片路径出错的解决
2018/04/26 Javascript
jQuery实现动态添加和删除input框代码实例
2019/03/29 jQuery
js通过canvas生成图片缩略图
2020/10/02 Javascript
nuxt 服务器渲染动态设置 title和seo关键字的操作
2020/11/05 Javascript
全面解析Vue中的$nextTick
2020/12/24 Vue.js
[19:54]夜魇凡尔赛茶话会 第一期02:看图识人
2021/03/11 DOTA
python抓取网页图片并放到指定文件夹
2014/04/24 Python
浅谈python迭代器
2017/11/08 Python
Python实现线程状态监测简单示例
2018/03/28 Python
python 画三维图像 曲面图和散点图的示例
2018/12/29 Python
python命令行参数用法实例分析
2019/06/25 Python
TensorFlow保存TensorBoard图像操作
2020/06/23 Python
如何利用python 读取配置文件
2021/01/06 Python
Linux系统下升级pip的完整步骤
2021/01/31 Python
一家专门做特卖的网站:唯品会
2016/10/09 全球购物
美国孕妇装购物网站:Motherhood Maternity
2019/09/22 全球购物
澳大利亚最受欢迎的超级商场每日优惠:Catch
2020/11/17 全球购物
EMPHASIS艾斐诗官网:周生生旗下原创精品珠宝品牌
2020/12/17 全球购物
品德评语大全
2014/05/05 职场文书
高中毕业典礼演讲稿
2014/09/09 职场文书
2014年医生工作总结
2014/11/21 职场文书
电力培训学习心得体会
2016/01/11 职场文书