判断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设计模式编程的代理模式与抽象工厂模式
Jan 16 Python
详谈Python2.6和Python3.0中对除法操作的异同
Apr 28 Python
Tensorflow 合并通道及加载子模型的方法
Jul 26 Python
python制作填词游戏步骤详解
May 05 Python
我就是这样学习Python中的列表
Jun 02 Python
简单了解python高阶函数map/reduce
Jun 28 Python
Django 自动生成api接口文档教程
Nov 19 Python
Python操作MySQL数据库实例详解【安装、连接、增删改查等】
Jan 17 Python
tensorflow 重置/清除计算图的实现
Jan 19 Python
浅谈Python线程的同步互斥与死锁
Mar 22 Python
python访问hdfs的操作
Jun 06 Python
python如何从键盘获取输入实例
Jun 18 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/10/09 PHP
某大型网络公司应聘时的笔试题目附答案
2008/03/27 PHP
CI框架出现mysql数据库连接资源无法释放的解决方法
2016/05/17 PHP
Mac版PhpStorm之XAMPP整合apache服务器配置的图文教程详解
2016/10/13 PHP
在Thinkphp中使用ajax实现无刷新分页的方法
2016/10/25 PHP
PHP终止脚本运行三种实现方法详解
2020/09/01 PHP
关于jQuery参考实例 1.0 jQuery的哲学
2013/04/07 Javascript
jQuery 获取浏览器所在的IP地址的小例子
2013/11/08 Javascript
javascript内存管理详细解析
2013/11/11 Javascript
jquery获取html元素的绝对位置和相对位置的方法
2014/06/20 Javascript
javascript实现window.print()去除页眉页脚
2014/12/30 Javascript
php+ajax+jquery实现点击加载更多内容
2015/05/03 Javascript
javascript为按钮注册回车事件(设置默认按钮)的方法
2015/05/09 Javascript
JavaScript实现选择框按比例拖拉缩放的方法
2015/08/04 Javascript
深入理解JavaScript函数参数(推荐)
2016/07/26 Javascript
jQuery选择器之表单元素选择器详解
2017/09/19 jQuery
浅谈es6中export和export default的作用及区别
2018/02/07 Javascript
jQuery实现颜色打字机的完整代码
2020/03/19 jQuery
在NodeJs中使用node-schedule增加定时器任务的方法
2020/06/08 NodeJs
python网络编程学习笔记(四):域名系统
2014/06/09 Python
VTK与Python实现机械臂三维模型可视化详解
2017/12/13 Python
python 使用正则表达式按照多个空格分割字符的实例
2018/12/20 Python
一款简洁的纯css3代码实现的动画导航
2014/10/31 HTML / CSS
使用HTML5进行SVG矢量图形绘制的入门教程
2016/02/19 HTML / CSS
浅谈html5增强的页面元素
2016/06/14 HTML / CSS
土耳其国际性时尚购物网站:Modanisa
2018/01/19 全球购物
中药专业大学生医药工作求职信
2013/10/25 职场文书
教师的实习自我鉴定
2013/12/17 职场文书
技术总监个人的自我评价范文
2013/12/18 职场文书
生物科学系大学生的自我评价
2013/12/20 职场文书
经济管理毕业生求职信
2014/03/15 职场文书
说明书范文
2014/05/07 职场文书
学生会副主席竞选稿
2015/11/19 职场文书
Nginx同一个域名配置多个项目的实现方法
2021/03/31 Servers
关于CSS自定义属性与前端页面的主题切换问题
2022/03/21 HTML / CSS
MySQL事务操作的四大特性以及并发事务问题
2022/04/12 MySQL