判断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使用urllib模块开发的多线程豆瓣小站mp3下载器
Jan 16 Python
Python中的choice()方法使用详解
May 15 Python
深入理解Python中命名空间的查找规则LEGB
Aug 06 Python
Python跨文件全局变量的实现方法示例
Dec 10 Python
Django contenttypes 框架详解(小结)
Aug 13 Python
python爱心表白 每天都是浪漫七夕!
Aug 18 Python
Django2.1.3 中间件使用详解
Nov 26 Python
使用python判断你是青少年还是老年人
Nov 29 Python
在Qt中正确的设置窗体的背景图片的几种方法总结
Jun 19 Python
python利用tkinter实现屏保
Jul 30 Python
Python 动态变量名定义与调用方法
Feb 09 Python
Python爬虫UA伪装爬取的实例讲解
Feb 19 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
如何选购合适的收音机
2021/03/01 无线电
ip签名探针
2006/10/09 PHP
无数据库的详细域名查询程序PHP版(3)
2006/10/09 PHP
mac下使用brew配置环境的步骤分享
2011/05/23 PHP
PHP中对数组的一些常用的增、删、插操作函数总结
2015/11/27 PHP
Symfony2框架学习笔记之HTTP Cache用法详解
2016/03/18 PHP
php中文语义分析实现方法示例
2019/09/28 PHP
地址栏上的一段语句,改变页面的风格。(教程)
2008/04/02 Javascript
jQuery :nth-child前有无空格的区别分析
2011/07/11 Javascript
asp.net网站开发中用jquery实现滚动浏览器滚动条加载数据(类似于腾讯微博)
2012/03/14 Javascript
Jquery 返回json数据在IE浏览器中提示下载的问题
2014/05/18 Javascript
BootStrap制作导航条实例代码
2016/05/06 Javascript
基于Layer+jQuery的自定义弹框
2020/05/26 Javascript
nodejs和C语言插入mysql数据库乱码问题的解决方法
2017/04/14 NodeJs
javascript 产生随机数的几种方法总结
2017/09/26 Javascript
详解vue项目中如何引入全局sass/less变量、function、mixin
2018/06/02 Javascript
JQuery Ajax动态加载Table数据的实例讲解
2018/08/09 jQuery
实例讲解vue源码架构
2019/01/24 Javascript
JavaScript遍历数组的方法代码实例
2020/01/14 Javascript
vue+koa2搭建mock数据环境的详细教程
2020/05/18 Javascript
[08:38]DOTA2-DPC中国联赛 正赛 VG vs Elephant 选手采访
2021/03/11 DOTA
解决PyCharm中光标变粗的问题
2017/08/05 Python
python中利用Future对象异步返回结果示例代码
2017/09/07 Python
Python入门之三角函数tan()函数实例详解
2017/11/08 Python
Python基于高斯消元法计算线性方程组示例
2018/01/17 Python
python3发送request请求及查看返回结果实例
2020/04/30 Python
Pytorch使用PIL和Numpy将单张图片转为Pytorch张量方式
2020/05/25 Python
python爬虫工具例举说明
2020/11/30 Python
Volcom法国官网:美国冲浪滑板品牌
2017/05/25 全球购物
巴西婴儿用品商店:Bebe Store
2017/11/23 全球购物
英国快时尚女装购物网站:PrettyLittleThing
2018/08/15 全球购物
给儿子的表扬信
2014/01/15 职场文书
优秀交警事迹材料
2014/01/26 职场文书
租房合同协议书
2014/04/09 职场文书
公务员爱岗敬业演讲稿
2014/08/26 职场文书
质检员工作总结2015
2015/04/25 职场文书