判断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实现发送email的几种常用方法
Aug 18 Python
Pyhthon中使用compileall模块编译源文件为pyc文件
Apr 28 Python
用C++封装MySQL的API的教程
May 06 Python
python中base64加密解密方法实例分析
May 16 Python
Python基于select实现的socket服务器
Apr 13 Python
Python时间戳使用和相互转换详解
Dec 11 Python
NetworkX之Prim算法(实例讲解)
Dec 22 Python
python实现画出e指数函数的图像
Nov 21 Python
Python将二维列表list的数据输出(TXT,Excel)
Apr 23 Python
基于python实现删除指定文件类型
Jul 21 Python
pandas 数据类型转换的实现
Dec 29 Python
Python趣味实战之手把手教你实现举牌小人生成器
Jun 07 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
第1次亲密接触PHP5(2)
2006/10/09 PHP
Ext.data.PagingMemoryProxy分页一次性读取数据的实现代码
2010/04/07 PHP
php带抄送和密件抄送的邮件发送方法
2015/03/20 PHP
php自定义错误处理用法实例
2015/03/20 PHP
PHP设计模式之 策略模式Strategy详解【对象行为型】
2020/05/01 PHP
jQuery EasyUI 的EasyLoader功能介绍
2010/09/12 Javascript
js通过googleAIP翻译PHP系统的语言配置的实现代码
2011/10/17 Javascript
jquery选择器原理介绍($()使用方法)
2014/03/25 Javascript
js操作iframe父子窗体示例
2014/05/22 Javascript
Bootstrap实现input控件失去焦点时验证
2016/08/04 Javascript
PHP+jquery+ajax实现分页
2016/12/09 Javascript
用file标签实现多图文件上传预览
2017/02/14 Javascript
xmlplus组件设计系列之图标(ICON)(1)
2017/05/05 Javascript
在JS中如何把毫秒转换成规定的日期时间格式实例
2017/05/11 Javascript
React Form组件的实现封装杂谈
2018/05/07 Javascript
javascript中如何判断类型汇总
2019/05/14 Javascript
vue实现标签云效果的方法详解
2019/08/28 Javascript
小程序实现上下切换位置
2020/11/16 Javascript
[01:23]一分钟告诉你 DOTA2为什么叫信仰2
2014/06/20 DOTA
使用python 获取进程pid号的方法
2014/03/10 Python
在Python中使用__slots__方法的详细教程
2015/04/28 Python
实例探究Python以并发方式编写高性能端口扫描器的方法
2016/06/14 Python
Golang与python线程详解及简单实例
2017/04/27 Python
Python实现定时精度可调节的定时器
2018/04/15 Python
Python 循环语句之 while,for语句详解
2018/04/23 Python
Python pycharm 同时加载多个项目的方法
2019/01/17 Python
python匿名函数的使用方法解析
2019/10/10 Python
Pytorch对Himmelblau函数的优化详解
2020/02/29 Python
全球知名巧克力品牌:Godiva
2016/07/22 全球购物
如何在发生故障的节点上重新安装 SQL Server
2013/03/14 面试题
信号量和自旋锁的区别?如何选择使用?
2015/09/08 面试题
党支部四风整改方案
2014/10/25 职场文书
2016教师节问候语
2015/11/10 职场文书
送给小学生的暑假礼物!小学生必背99首古诗
2019/07/02 职场文书
Java面试题冲刺第十五天--设计模式
2021/08/07 面试题
Anaconda安装pytorch和paddle的方法步骤
2022/04/03 Python