判断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中使用sys模板和logging模块获取行号和函数名的方法
Apr 15 Python
使用Python编写vim插件的简单示例
Apr 17 Python
Python实现对excel文件列表值进行统计的方法
Jul 25 Python
Python之os操作方法(详解)
Jun 15 Python
对python requests发送json格式数据的实例详解
Dec 19 Python
linux查找当前python解释器的位置方法
Feb 20 Python
python2使用bs4爬取腾讯社招过程解析
Aug 14 Python
Python collections中的双向队列deque简单介绍详解
Nov 04 Python
Python实现常见的几种加密算法(MD5,SHA-1,HMAC,DES/AES,RSA和ECC)
May 09 Python
浅析Python 责任链设计模式
Sep 11 Python
Python的scikit-image模块实例讲解
Dec 30 Python
Python爬虫制作翻译程序的示例代码
Feb 22 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
几种显示数据的方法的比较
2006/10/09 PHP
php判断当前用户已在别处登录的方法
2015/01/06 PHP
PHP图片添加水印功能示例小结
2016/10/03 PHP
Laravel框架实现redis集群的方法分析
2017/09/14 PHP
php常用字符串查找函数strstr()与strpos()实例分析
2019/06/21 PHP
Javascript入门学习资料收集整理篇
2008/07/06 Javascript
range 标准化之获取
2011/08/28 Javascript
jquery选择器之属性过滤选择器详解
2014/01/27 Javascript
jquery+html5制作超酷的圆盘时钟表
2015/04/14 Javascript
简单谈谈Javascript中类型的判断
2015/10/19 Javascript
JS实现图片平面旋转的方法
2016/03/01 Javascript
JQuery EasyUI学习教程之datagrid 添加、修改、删除操作
2016/07/09 Javascript
jQuery插件Validation快速完成表单验证的方式
2016/07/28 Javascript
JS之获取样式的简单实现方法(推荐)
2016/09/13 Javascript
详解js中call与apply关键字的作用
2016/11/21 Javascript
Jquery Easyui选项卡组件Tab使用详解(10)
2016/12/18 Javascript
JS操作input标签属性checkbox全选的实现代码
2017/03/02 Javascript
D3.js实现拓扑图的示例代码
2018/06/30 Javascript
JS实现图片拖拽交换效果
2018/11/30 Javascript
实现vuex与组件data之间的数据同步更新方式
2019/11/12 Javascript
Vertx基于EventBus发送接受自定义对象
2020/11/16 Javascript
[01:19:46]EG vs Secret 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.21.mp4
2020/07/19 DOTA
Python决策树之基于信息增益的特征选择示例
2018/06/25 Python
python+pandas+时间、日期以及时间序列处理方法
2018/07/10 Python
CentOS7下python3.7.0安装教程
2018/07/30 Python
在Django model中设置多个字段联合唯一约束的实例
2019/07/17 Python
解决pycharm编辑区显示yaml文件层级结构遇中文乱码问题
2020/04/27 Python
香港化妆品经销商:我的公主
2016/08/05 全球购物
瑞典轮胎在线:Tirendo.se
2018/06/21 全球购物
英国婴儿产品专家:Samuel Johnston
2020/04/20 全球购物
什么是静态路由?什么是动态路由?各自的特点是什么?
2015/09/16 面试题
幼儿园庆六一活动方案
2014/03/06 职场文书
小学教师师德整改措施
2014/09/29 职场文书
银行会计主管岗位职责
2014/10/01 职场文书
高中生社会实践心得体会
2016/01/14 职场文书
小米11和iphone12哪个值得买?小米11对比iphone12评测
2021/04/21 数码科技