ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python判断一个对象是否为函数或方法

2021-11-03 19:01:16  阅读:223  来源: 互联网

标签:__ False 函数 Python inspect 对象 isinstance True types


文章目录

问题描述

Python判断一个对象是否为函数




解决方案

import types
import inspect
import functools
import typing


def judge(x):
    name = x.__name__ if hasattr(x, '__name__') else 'functools.partial'
    print(name)
    print('\ttype({})={}'.format(name, type(x)))
    print('\tcallable({})={}'.format(name, callable(x)))
    print('\thasattr({}, \'__call__\')={}'.format(name, hasattr(x, '__call__')))
    print()
    print('\tinspect.isfunction({})={}'.format(name, inspect.isfunction(x)))
    print('\tinspect.ismethod({})={}'.format(name, inspect.ismethod(x)))
    print('\tinspect.isgeneratorfunction({})={}'.format(name, inspect.isgeneratorfunction(x)))
    print('\tinspect.iscoroutinefunction({})={}'.format(name, inspect.iscoroutinefunction(x)))
    print('\tinspect.isasyncgenfunction({})={}'.format(name, inspect.isasyncgenfunction(x)))
    print()
    print('\tisinstance({}, typing.Callable)={}'.format(name, isinstance(x, typing.Callable)))
    print('\tisinstance({}, types.BuiltinFunctionType)={}'.format(name, isinstance(x, types.BuiltinFunctionType)))
    print('\tisinstance({}, types.BuiltinMethodType)={}'.format(name, isinstance(x, types.BuiltinMethodType)))
    print('\tisinstance({}, types.FunctionType)={}'.format(name, isinstance(x, types.FunctionType)))
    print('\tisinstance({}, types.MethodType)={}'.format(name, isinstance(x, types.MethodType)))
    print('\tisinstance({}, types.LambdaType)={}'.format(name, isinstance(x, types.LambdaType)))
    print('\tisinstance({}, functools.partial)={}'.format(name, isinstance(x, functools.partial)))


def func(a, b):
    pass


partial = functools.partial(func, a=1)

_lambda = lambda _: _


def generator():
    yield 1
    yield 2


async def async_func():
    pass


async def async_generator():
    yield 1


class A:
    def __call__(self, a, b):
        pass

    def func1(self, a, b):
        pass

    @classmethod
    def func2(cls, a, b):
        pass

    @staticmethod
    def func3(a, b):
        pass


for func in [print,
             func,
             partial,
             _lambda,
             generator,
             async_func,
             async_generator,
             A,
             A.func1,
             A.func2,
             A.func3]:
    judge(func)

结果

print
	type(print)=<class 'builtin_function_or_method'>
	callable(print)=True
	hasattr(print, '__call__')=True

	inspect.isfunction(print)=False
	inspect.ismethod(print)=False
	inspect.isgeneratorfunction(print)=False
	inspect.iscoroutinefunction(print)=False
	inspect.isasyncgenfunction(print)=False

	isinstance(print, typing.Callable)=True
	isinstance(print, types.BuiltinFunctionType)=True
	isinstance(print, types.BuiltinMethodType)=True
	isinstance(print, types.FunctionType)=False
	isinstance(print, types.MethodType)=False
	isinstance(print, types.LambdaType)=False
	isinstance(print, functools.partial)=False
func
	type(func)=<class 'function'>
	callable(func)=True
	hasattr(func, '__call__')=True

	inspect.isfunction(func)=True
	inspect.ismethod(func)=False
	inspect.isgeneratorfunction(func)=False
	inspect.iscoroutinefunction(func)=False
	inspect.isasyncgenfunction(func)=False

	isinstance(func, typing.Callable)=True
	isinstance(func, types.BuiltinFunctionType)=False
	isinstance(func, types.BuiltinMethodType)=False
	isinstance(func, types.FunctionType)=True
	isinstance(func, types.MethodType)=False
	isinstance(func, types.LambdaType)=True
	isinstance(func, functools.partial)=False
functools.partial
	type(functools.partial)=<class 'functools.partial'>
	callable(functools.partial)=True
	hasattr(functools.partial, '__call__')=True

	inspect.isfunction(functools.partial)=False
	inspect.ismethod(functools.partial)=False
	inspect.isgeneratorfunction(functools.partial)=False
	inspect.iscoroutinefunction(functools.partial)=False
	inspect.isasyncgenfunction(functools.partial)=False

	isinstance(functools.partial, typing.Callable)=True
	isinstance(functools.partial, types.BuiltinFunctionType)=False
	isinstance(functools.partial, types.BuiltinMethodType)=False
	isinstance(functools.partial, types.FunctionType)=False
	isinstance(functools.partial, types.MethodType)=False
	isinstance(functools.partial, types.LambdaType)=False
	isinstance(functools.partial, functools.partial)=True
<lambda>
	type(<lambda>)=<class 'function'>
	callable(<lambda>)=True
	hasattr(<lambda>, '__call__')=True

	inspect.isfunction(<lambda>)=True
	inspect.ismethod(<lambda>)=False
	inspect.isgeneratorfunction(<lambda>)=False
	inspect.iscoroutinefunction(<lambda>)=False
	inspect.isasyncgenfunction(<lambda>)=False

	isinstance(<lambda>, typing.Callable)=True
	isinstance(<lambda>, types.BuiltinFunctionType)=False
	isinstance(<lambda>, types.BuiltinMethodType)=False
	isinstance(<lambda>, types.FunctionType)=True
	isinstance(<lambda>, types.MethodType)=False
	isinstance(<lambda>, types.LambdaType)=True
	isinstance(<lambda>, functools.partial)=False
generator
	type(generator)=<class 'function'>
	callable(generator)=True
	hasattr(generator, '__call__')=True

	inspect.isfunction(generator)=True
	inspect.ismethod(generator)=False
	inspect.isgeneratorfunction(generator)=True
	inspect.iscoroutinefunction(generator)=False
	inspect.isasyncgenfunction(generator)=False

	isinstance(generator, typing.Callable)=True
	isinstance(generator, types.BuiltinFunctionType)=False
	isinstance(generator, types.BuiltinMethodType)=False
	isinstance(generator, types.FunctionType)=True
	isinstance(generator, types.MethodType)=False
	isinstance(generator, types.LambdaType)=True
	isinstance(generator, functools.partial)=False
async_func
	type(async_func)=<class 'function'>
	callable(async_func)=True
	hasattr(async_func, '__call__')=True

	inspect.isfunction(async_func)=True
	inspect.ismethod(async_func)=False
	inspect.isgeneratorfunction(async_func)=False
	inspect.iscoroutinefunction(async_func)=True
	inspect.isasyncgenfunction(async_func)=False

	isinstance(async_func, typing.Callable)=True
	isinstance(async_func, types.BuiltinFunctionType)=False
	isinstance(async_func, types.BuiltinMethodType)=False
	isinstance(async_func, types.FunctionType)=True
	isinstance(async_func, types.MethodType)=False
	isinstance(async_func, types.LambdaType)=True
	isinstance(async_func, functools.partial)=False
async_generator
	type(async_generator)=<class 'function'>
	callable(async_generator)=True
	hasattr(async_generator, '__call__')=True

	inspect.isfunction(async_generator)=True
	inspect.ismethod(async_generator)=False
	inspect.isgeneratorfunction(async_generator)=False
	inspect.iscoroutinefunction(async_generator)=False
	inspect.isasyncgenfunction(async_generator)=True

	isinstance(async_generator, typing.Callable)=True
	isinstance(async_generator, types.BuiltinFunctionType)=False
	isinstance(async_generator, types.BuiltinMethodType)=False
	isinstance(async_generator, types.FunctionType)=True
	isinstance(async_generator, types.MethodType)=False
	isinstance(async_generator, types.LambdaType)=True
	isinstance(async_generator, functools.partial)=False
A
	type(A)=<class 'type'>
	callable(A)=True
	hasattr(A, '__call__')=True

	inspect.isfunction(A)=False
	inspect.ismethod(A)=False
	inspect.isgeneratorfunction(A)=False
	inspect.iscoroutinefunction(A)=False
	inspect.isasyncgenfunction(A)=False

	isinstance(A, typing.Callable)=True
	isinstance(A, types.BuiltinFunctionType)=False
	isinstance(A, types.BuiltinMethodType)=False
	isinstance(A, types.FunctionType)=False
	isinstance(A, types.MethodType)=False
	isinstance(A, types.LambdaType)=False
	isinstance(A, functools.partial)=False
func1
	type(func1)=<class 'function'>
	callable(func1)=True
	hasattr(func1, '__call__')=True

	inspect.isfunction(func1)=True
	inspect.ismethod(func1)=False
	inspect.isgeneratorfunction(func1)=False
	inspect.iscoroutinefunction(func1)=False
	inspect.isasyncgenfunction(func1)=False

	isinstance(func1, typing.Callable)=True
	isinstance(func1, types.BuiltinFunctionType)=False
	isinstance(func1, types.BuiltinMethodType)=False
	isinstance(func1, types.FunctionType)=True
	isinstance(func1, types.MethodType)=False
	isinstance(func1, types.LambdaType)=True
	isinstance(func1, functools.partial)=False
func2
	type(func2)=<class 'method'>
	callable(func2)=True
	hasattr(func2, '__call__')=True

	inspect.isfunction(func2)=False
	inspect.ismethod(func2)=True
	inspect.isgeneratorfunction(func2)=False
	inspect.iscoroutinefunction(func2)=False
	inspect.isasyncgenfunction(func2)=False

	isinstance(func2, typing.Callable)=True
	isinstance(func2, types.BuiltinFunctionType)=False
	isinstance(func2, types.BuiltinMethodType)=False
	isinstance(func2, types.FunctionType)=False
	isinstance(func2, types.MethodType)=True
	isinstance(func2, types.LambdaType)=False
	isinstance(func2, functools.partial)=False
func3
	type(func3)=<class 'function'>
	callable(func3)=True
	hasattr(func3, '__call__')=True

	inspect.isfunction(func3)=True
	inspect.ismethod(func3)=False
	inspect.isgeneratorfunction(func3)=False
	inspect.iscoroutinefunction(func3)=False
	inspect.isasyncgenfunction(func3)=False

	isinstance(func3, typing.Callable)=True
	isinstance(func3, types.BuiltinFunctionType)=False
	isinstance(func3, types.BuiltinMethodType)=False
	isinstance(func3, types.FunctionType)=True
	isinstance(func3, types.MethodType)=False
	isinstance(func3, types.LambdaType)=True
	isinstance(func3, functools.partial)=False




对比

判断方法callable(x)hasattr(x, ‘__call__’)inspect.isfunction(x)inspect.ismethod(x)inspect.isgeneratorfunction(x)inspect.iscoroutinefunction(x)inspect.isasyncgenfunction(x)isinstance(x, typing.Callable)isinstance(x, types.BuiltinFunctionType)isinstance(x, types.BuiltinMethodType)isinstance(x, types.FunctionType)isinstance(x, types.MethodType)isinstance(x, types.LambdaType)isinstance(x, functools.partial)
print×××××××××
func××××××××
functools.partial××××××××××
<lambda>××××××××
generator×××××××
async_func×××××××
async_generator×××××××
A×××××××××××
func1××××××××
func2×××××××××
func3××××××××
import types
import inspect
import functools
import typing


def func(a, b):
    pass


partial = functools.partial(func, a=1)

_lambda = lambda _: _


def generator():
    yield 1
    yield 2


async def async_func():
    pass


async def async_generator():
    yield 1


class A:
    def __call__(self, a, b):
        pass

    def func1(self, a, b):
        pass

    @classmethod
    def func2(cls, a, b):
        pass

    @staticmethod
    def func3(a, b):
        pass


def judge(x):
    results = [
        callable(x),
        hasattr(x, '__call__'),
        inspect.isfunction(x),
        inspect.ismethod(x),
        inspect.isgeneratorfunction(x),
        inspect.iscoroutinefunction(x),
        inspect.isasyncgenfunction(x),
        isinstance(x, typing.Callable),
        isinstance(x, types.BuiltinFunctionType),
        isinstance(x, types.BuiltinMethodType),
        isinstance(x, types.FunctionType),
        isinstance(x, types.MethodType),
        isinstance(x, types.LambdaType),
        isinstance(x, functools.partial)
    ]
    return results


funcs = [
    print,
    func,
    partial,
    _lambda,
    generator,
    async_func,
    async_generator,
    A,
    A.func1,
    A.func2,
    A.func3
]
judge_names = [
    'callable(x)',
    'hasattr(x, \'__call__\')',
    'inspect.isfunction(x)',
    'inspect.ismethod(x)',
    'inspect.isgeneratorfunction(x)',
    'inspect.iscoroutinefunction(x)',
    'inspect.isasyncgenfunction(x)',
    'isinstance(x, typing.Callable)',
    'isinstance(x, types.BuiltinFunctionType)',
    'isinstance(x, types.BuiltinMethodType)',
    'isinstance(x, types.FunctionType)',
    'isinstance(x, types.MethodType)',
    'isinstance(x, types.LambdaType)',
    'isinstance(x, functools.partial)'
]
print('|判断方法|{}|'.format('|'.join(judge_names)))
print('|--' * (1 + len(judge_names)) + '|')
for x in funcs:
    func_name = x.__name__ if hasattr(x, '__name__') else 'functools.partial'
    results = judge(x)
    results = ['√' if i else '×' for i in results]
    print('|{}|{}|'.format(func_name, '|'.join(results)))




耗时

挑选最通用的三种方法:

函数耗时/s
callable(x)0.86
hasattr(x, ‘__call__’)1.36
isinstance(x, typing.Callable)12.19
import typing
from timeit import timeit


def x():
    pass


def f1():
    return callable(x)


def f2():
    return hasattr(x, '__call__')


def f3():
    return isinstance(x, typing.Callable)


print(timeit(f1, number=10000000))
print(timeit(f2, number=10000000))
print(timeit(f3, number=10000000))
# 0.8643081
# 1.3563508
# 12.193492500000001




参考文献

  1. How do I detect whether a Python variable is a function?
  2. Python快速计算函数耗时timeit

标签:__,False,函数,Python,inspect,对象,isinstance,True,types
来源: https://blog.csdn.net/lly1122334/article/details/121125178

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有