判断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 元组(Tuple)操作详解
Mar 11 Python
python中__call__方法示例分析
Oct 11 Python
Python中使用copy模块实现列表(list)拷贝
Apr 14 Python
Python模拟百度登录实例详解
Jan 20 Python
Python 实现两个列表里元素对应相乘的方法
Nov 14 Python
Python数据可视化之画图
Jan 15 Python
Django使用redis缓存服务器的实现代码示例
Apr 28 Python
如何使用Python发送HTML格式的邮件
Feb 11 Python
python GUI库图形界面开发之PyQt5动态加载QSS样式文件
Feb 25 Python
python剪切视频与合并视频的实现
Mar 03 Python
keras实现VGG16方式(预测一张图片)
Jul 07 Python
Python必须了解的35个关键词
Jul 16 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中的访问修饰符简单比较
2019/02/02 PHP
javascript小数计算出现近似值的解决办法
2010/02/06 Javascript
ScrollDown的基本操作示例
2013/06/09 Javascript
jquery和javascript中如何将一元素的内容赋给另一元素
2014/01/09 Javascript
js限制文本框只能输入整数或者带小数点的数字
2015/04/27 Javascript
JavaScript中三个等号和两个等号的区别(== 和 ===)浅析
2016/09/22 Javascript
vue mintui-Loadmore结合实现下拉刷新和上拉加载示例
2017/10/12 Javascript
关于vue的语法规则检测报错问题的解决
2018/05/21 Javascript
详解在create-react-app使用less与antd按需加载
2018/12/06 Javascript
[10:24]郎朗助力完美“圣”典,天籁交织奏响序曲
2016/12/18 DOTA
[10:21]2018DOTA2国际邀请赛寻真——Winstrike
2018/08/11 DOTA
跟老齐学Python之深入变量和引用对象
2014/09/24 Python
以Python的Pyspider为例剖析搜索引擎的网络爬虫实现方法
2015/03/30 Python
python读写二进制文件的方法
2015/05/09 Python
利用Python读取文件的四种不同方法比对
2017/05/18 Python
python中利用zfill方法自动给数字前面补0
2018/04/10 Python
分享一下Python数据分析常用的8款工具
2018/04/29 Python
对dataframe进行列相加,行相加的实例
2018/06/08 Python
对Python中的条件判断、循环以及循环的终止方法详解
2019/02/08 Python
Python实现的爬取百度文库功能示例
2019/02/16 Python
selenium python 实现基本自动化测试的示例代码
2019/02/25 Python
使用Python求解带约束的最优化问题详解
2020/02/11 Python
jupyter修改文件名方式(TensorFlow)
2020/04/21 Python
HTML5 progress和meter控件_动力节点Java学院整理
2017/07/06 HTML / CSS
html5简单示例_动力节点Java学院整理
2017/07/07 HTML / CSS
雅萌 (YA-MAN) :日本美容家电领域的龙头企业
2017/05/12 全球购物
Lookfantastic法国官网:英国知名美妆购物网站
2017/10/28 全球购物
松本清官方海外旗舰店:日本最大的药妆连锁店
2017/11/21 全球购物
I.T集团香港官方商城:ITeSHOP.com Hong Kong
2019/02/15 全球购物
表演方阵解说词
2014/02/08 职场文书
幼儿园家长评语大全
2014/04/16 职场文书
优秀大学生求职自荐信范文
2014/04/19 职场文书
欢迎领导标语
2014/06/27 职场文书
挂职个人工作总结
2015/03/05 职场文书
学籍证明模板
2015/06/18 职场文书
教你一步步实现一个简易promise
2021/11/02 Javascript