判断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的Django框架下搭建的BLOG添加RSS功能的教程
Apr 08 Python
python递归计算N!的方法
May 05 Python
Python中的random()方法的使用介绍
May 15 Python
python实现简单爬虫功能的示例
Oct 24 Python
在 Python 应用中使用 MongoDB的方法
Jan 05 Python
python3 拼接字符串的7种方法
Sep 12 Python
使用 Python 实现微信群友统计器的思路详解
Sep 26 Python
python networkx 根据图的权重画图实现
Jul 10 Python
python自动化测试之DDT数据驱动的实现代码
Jul 23 Python
Pandas缺失值2种处理方式代码实例
Jun 13 Python
python 提高开发效率的5个小技巧
Oct 19 Python
两行代码解决Jupyter Notebook中文不能显示的问题
Apr 24 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初学者头疼问题总结
2006/07/08 PHP
phpmyadmin出现Cannot start session without errors问题解决方法
2014/08/14 PHP
日常整理PHP中简单的图形处理(经典)
2015/10/26 PHP
PHP多进程编程之僵尸进程问题的理解
2017/10/15 PHP
详解关于php的xdebug配置(编辑器vscode)
2019/01/29 PHP
ext 列表页面关于多行查询的办法
2010/03/25 Javascript
Javascript基础教程之函数对象和属性
2015/01/18 Javascript
JS上传图片前实现图片预览效果的方法
2015/03/02 Javascript
详解JavaScript中setSeconds()方法的使用
2015/06/11 Javascript
JavaScript获得url查询参数的方法
2015/07/02 Javascript
jquery实现表格隔行换色效果
2015/11/19 Javascript
jQuery实现扑克正反面翻牌效果
2017/03/10 Javascript
原生JavaScript实现todolist功能
2018/03/02 Javascript
9102了,你还不会移动端真机调试吗
2019/03/25 Javascript
在微信小程序中使用图表的方法示例
2019/04/25 Javascript
javascript面向对象三大特征之多态实例详解
2019/07/24 Javascript
Vue3 实现双盒子定位Overlay的示例
2020/12/22 Vue.js
[48:53]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS VG第一场
2014/05/26 DOTA
[48:11]完美世界DOTA2联赛 Magma vs GXR 第二场 11.07
2020/11/10 DOTA
python thread 并发且顺序运行示例
2009/04/09 Python
Python 实现随机数详解及实例代码
2017/04/15 Python
Python实现合并同一个文件夹下所有PDF文件的方法示例
2018/04/28 Python
django创建超级用户过程解析
2019/09/18 Python
django序列化serializers过程解析
2019/12/14 Python
python爬虫开发之使用Python爬虫库requests多线程抓取猫眼电影TOP100实例
2020/03/10 Python
Python字符串格式化f-string多种功能实现
2020/05/07 Python
Python操作Excel把数据分给sheet
2020/05/20 Python
Python参数传递机制传值和传引用原理详解
2020/05/22 Python
Html5定位终极解决方案
2020/02/05 HTML / CSS
美国销售第一的智能手机和平板电脑保护壳:OtterBox
2017/12/21 全球购物
工业设计专业推荐信
2013/10/29 职场文书
应届大学生求职信
2013/12/01 职场文书
2014感恩节演讲稿大全
2014/10/11 职场文书
2016廉洁从政心得体会
2016/01/19 职场文书
导游词之湖州-太湖
2019/10/11 职场文书
SpringBoot深入分析讲解监听器模式下
2022/07/15 Java/Android