判断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程序中进行文件读取和写入操作的教程
Apr 28 Python
Python机器学习之SVM支持向量机
Dec 27 Python
代码讲解Python对Windows服务进行监控
Feb 11 Python
Python openpyxl读取单元格字体颜色过程解析
Sep 03 Python
Python计算两个矩形重合面积代码实例
Sep 16 Python
pytorch中torch.max和Tensor.view函数用法详解
Jan 03 Python
pytorch 实现在预训练模型的 input上增减通道
Jan 06 Python
django有外键关系的两张表如何相互查找
Feb 10 Python
python读取csv文件指定行的2种方法详解
Feb 13 Python
python+OpenCV实现图像拼接
Mar 05 Python
Python并发concurrent.futures和asyncio实例
May 04 Python
VSCode配合pipenv搞定虚拟环境的实现方法
May 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 面向对象的一个例子
2011/04/12 PHP
php实现递归与无限分类的方法
2015/02/16 PHP
PHP生成静态HTML文档实现代码
2016/06/23 PHP
laravel框架中路由设置,路由参数和路由命名实例分析
2019/11/23 PHP
屏蔽Flash右键信息的js代码
2010/01/17 Javascript
TBCompressor js代码压缩
2011/01/05 Javascript
javaScript中Math()函数注意事项
2015/06/18 Javascript
JavaScript验证Email(3种方法)
2015/09/21 Javascript
每天一篇javascript学习小结(Date对象)
2015/11/13 Javascript
jQuery实现的倒计时效果实例小结
2016/04/16 Javascript
D3.js实现柱状图的方法详解
2016/09/21 Javascript
浅谈javascript中遇到的字符串对象处理
2016/11/18 Javascript
JQuery查找子元素find()和遍历集合each的方法总结
2017/03/07 Javascript
用户管理的设计_jquery的ajax实现二级联动效果
2017/07/13 jQuery
微信小程序 配置顶部导航条标题颜色的实现方法
2017/09/20 Javascript
Angular实现的内置过滤器orderBy排序与模糊查询功能示例
2017/12/29 Javascript
jQuery NProgress.js加载进度插件的简单使用方法
2018/01/31 jQuery
详解vue数组遍历方法forEach和map的原理解析和实际应用
2018/11/15 Javascript
VUE单页面切换动画代码(全网最好的切换效果)
2019/10/31 Javascript
[51:32]Optic vs Serenity 2018国际邀请赛淘汰赛BO3 第一场 8.22
2018/08/23 DOTA
python判断输入日期为第几天的实例
2018/11/13 Python
Python+OpenCV感兴趣区域ROI提取方法
2019/01/10 Python
Python split() 函数拆分字符串将字符串转化为列的方法
2019/07/16 Python
python+openCV调用摄像头拍摄和处理图片的实现
2019/08/06 Python
基于python2.7实现图形密码生成器的实例代码
2019/11/05 Python
Python如何把Spark数据写入ElasticSearch
2020/04/18 Python
matplotlib之pyplot模块之标题(title()和suptitle())
2021/02/22 Python
HTML5 Canvas绘制文本及图片的基础教程
2016/03/14 HTML / CSS
Canvas制作的下雨动画的示例
2018/03/06 HTML / CSS
韩国美国时尚服装和美容在线全球市场:KOODING
2018/11/07 全球购物
房地产项目建议书
2014/03/12 职场文书
借款协议书范本
2014/04/22 职场文书
优质服务活动实施方案
2014/05/02 职场文书
如何通过简单的代码描述Angular父组件、子组件传值
2022/04/07 Javascript
CentOS MySql8 远程连接实战
2022/04/19 MySQL
 python中的元类metaclass详情
2022/05/30 Python