判断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中使用百度音乐搜索的api下载指定歌曲的lrc歌词
Jul 18 Python
python使用socket连接远程服务器的方法
Apr 29 Python
Python使用urllib2模块实现断点续传下载的方法
Jun 17 Python
Python自动发邮件脚本
Mar 31 Python
简单实现python收发邮件功能
Jan 05 Python
对python中大文件的导入与导出方法详解
Dec 28 Python
Python基础教程之异常详解
Jan 10 Python
Python 通过打码平台实现验证码的实现
May 13 Python
快速解决vue.js 模板和jinja 模板冲突的问题
Jul 26 Python
python requests抓取one推送文字和图片代码实例
Nov 04 Python
opencv设置采集视频分辨率方式
Dec 10 Python
PyTorch 普通卷积和空洞卷积实例
Jan 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
mysql5详细安装教程
2007/01/15 PHP
dede3.1分页文字采集过滤规则详说(图文教程)续四
2007/04/03 PHP
php 随机排序广告的实现代码
2011/05/09 PHP
PHP 解决session死锁的方法
2013/06/20 PHP
php强制运行广告的方法
2014/12/01 PHP
19个Android常用工具类汇总
2014/12/30 PHP
php简单备份与还原MySql的方法
2016/05/09 PHP
smarty模板数学运算示例
2016/12/11 PHP
经常用到的JavasScript事件的翻译
2007/04/09 Javascript
ext 代码生成器
2009/08/07 Javascript
淘宝搜索框效果实现分析
2011/03/05 Javascript
一个不错的字符串转码解码函数(自写)
2014/07/31 Javascript
javascript实现英文首字母大写
2015/04/23 Javascript
JavaScript中switch语句的用法详解
2015/06/03 Javascript
实例详解JSON取值(key是中文或者数字)方式
2017/08/24 Javascript
JavaScript中的E-mail 地址格式验证
2018/03/28 Javascript
Vue中&quot;This dependency was not found&quot;问题的解决方法
2018/06/19 Javascript
[01:07:57]DOTA2-DPC中国联赛 正赛 Ehome vs Magma BO3 第二场 1月19日
2021/03/11 DOTA
python 读入多行数据的实例
2018/04/19 Python
python3.5基于TCP实现文件传输
2020/03/20 Python
Python读取csv文件分隔符设置方法
2019/01/14 Python
python 读取dicom文件,生成info.txt和raw文件的方法
2019/01/24 Python
Python之修改图片像素值的方法
2019/07/03 Python
Python scrapy爬取小说代码案例详解
2020/07/09 Python
解决pytorch 数据类型报错的问题
2021/03/03 Python
一款纯css3实现简单的checkbox复选框和radio单选框
2014/11/05 HTML / CSS
集团薪酬管理制度
2014/01/13 职场文书
部队党性分析材料
2014/02/16 职场文书
美德少年事迹材料500字
2014/08/19 职场文书
2014年群众路线党员自我评议
2014/09/24 职场文书
求职自我推荐信
2015/03/24 职场文书
质检员工作总结2015
2015/04/25 职场文书
2016年习主席讲话学习心得体会
2016/01/20 职场文书
2019年健身俱乐部的创业计划书
2019/08/26 职场文书
创业计划书之酒吧
2019/12/02 职场文书
springboot应用服务启动事件的监听实现
2022/04/06 Java/Android