判断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的Flask框架下使用sqlalchemy库的简单教程
Apr 09 Python
Python实用日期时间处理方法汇总
May 09 Python
Python Queue模块详细介绍及实例
Dec 27 Python
基于Python函数的作用域规则和闭包(详解)
Nov 29 Python
python实现excel读写数据
Mar 02 Python
Python PyQt4实现QQ抽屉效果
Apr 20 Python
对python 数据处理中的LabelEncoder 和 OneHotEncoder详解
Jul 11 Python
Python抽象和自定义类定义与用法示例
Aug 23 Python
python 猴子补丁(monkey patch)
Jun 26 Python
基于python的Paxos算法实现
Jul 03 Python
Django密码存储策略分析
Jan 09 Python
pycharm 代码自动补全的实现方法(图文)
Sep 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中文转拼音的实现代码
2014/02/11 PHP
Laravel5.1数据库连接、创建数据库、创建model及创建控制器的方法
2016/03/29 PHP
PHP命名空间和自动加载类
2016/04/03 PHP
[原创]php使用curl判断网页404(不存在)的方法
2016/06/23 PHP
PHP常用的三种设计模式汇总
2016/08/28 PHP
PHP小偷程序的设计与实现方法详解
2016/10/15 PHP
利用laravel+ajax实现文件上传功能方法示例
2017/08/13 PHP
javascript 基础篇2 数据类型,语句,函数
2012/03/14 Javascript
JQuery实现倒计时按钮的实现代码
2012/03/23 Javascript
不使用jquery实现js打字效果示例分享
2014/01/19 Javascript
jQuery树形下拉菜单特效代码分享
2015/08/15 Javascript
解决js图片加载时出现404的问题
2020/11/30 Javascript
基于jQuery实现放大镜特效
2020/10/19 Javascript
纯js实现手风琴效果代码
2020/04/17 Javascript
JS实现列表页面隔行变色效果
2017/03/25 Javascript
React实践之Tree组件的使用方法
2017/09/30 Javascript
实例详解ztree在vue项目中使用并且带有搜索功能
2018/08/24 Javascript
javascript实现简易聊天室
2019/07/12 Javascript
Vue实现剪贴板复制功能
2019/12/31 Javascript
[03:03]2014DOTA2国际邀请赛 EG战队专访
2014/07/12 DOTA
python list格式数据excel导出方法
2018/10/31 Python
python 实现二维字典的键值合并等函数
2019/12/06 Python
Python搭建Keras CNN模型破解网站验证码的实现
2020/04/07 Python
python matplotlib实现将图例放在图外
2020/04/17 Python
Python变量格式化输出实现原理解析
2020/08/06 Python
Python测试框架:pytest学习笔记
2020/10/20 Python
使用CSS3滤镜的filter:blur属性制作毛玻璃模糊效果的方法
2016/07/08 HTML / CSS
德国箱包网上商店:koffer24.de
2016/07/27 全球购物
super关键字的用法
2012/04/10 面试题
在C中是否有模拟继承等面向对象程序设计特性的好方法
2012/05/22 面试题
校庆团日活动总结
2014/08/28 职场文书
2014年幼儿园老师工作总结
2014/12/05 职场文书
mysql自增长id用完了该怎么办
2022/02/12 MySQL
微信小程序中wxs文件的一些妙用分享
2022/02/18 Javascript
nginx中封禁ip和允许内网ip访问的实现示例
2022/03/17 Servers
PO模式在selenium自动化测试框架的优势
2022/03/20 Python