Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何检测Python变量是否为函数?_Python - Fatal编程技术网

如何检测Python变量是否为函数?

如何检测Python变量是否为函数?,python,Python,我有一个变量,x,我想知道它是否指向函数 我曾希望我能做一些类似的事情: >>> isinstance(x, function) 但这给了我: 回溯(最近一次呼叫最后一次): 文件“”,第1行,是否在中? NameError:未定义名称“函数” 我之所以选择它是因为 >>> type(x) <type 'function'> >类型(x) 以下内容应返回布尔值: callable(x) 尝试使用callable(x)如果这是针对Python

我有一个变量,
x
,我想知道它是否指向函数

我曾希望我能做一些类似的事情:

>>> isinstance(x, function)
但这给了我:

回溯(最近一次呼叫最后一次):
文件“”,第1行,是否在中?
NameError:未定义名称“函数”
我之所以选择它是因为

>>> type(x)
<type 'function'>
>类型(x)

以下内容应返回布尔值:

callable(x)

尝试使用
callable(x)

如果这是针对Python2.x或Python3.2+,您可以使用。它曾经被弃用,但现在还没有被预先确定,所以您可以再次使用它。您可以在此处阅读讨论:。您可以通过以下方式执行此操作:

callable(obj)
hasattr(obj, '__call__')
如果这是针对Python3.x但在3.2之前的版本,请检查对象是否具有
\uuuu call\uuu
属性。您可以通过以下方式执行此操作:

callable(obj)
hasattr(obj, '__call__')
经常建议的or方法(两者都有)附带了一些警告。对于非Python函数,它返回
False
。例如,大多数是用C语言实现的,而不是用Python实现的,因此它们返回
False

>>> isinstance(open, types.FunctionType)
False
>>> callable(open)
True

因此
types.FunctionType
可能会给您带来令人惊讶的结果。检查duck类型对象属性的正确方法是询问它们是否会嘎嘎作响,而不是查看它们是否适合duck大小的容器。

内置命名空间中没有构造函数的内置类型(例如函数、生成器、方法)位于
类型模块中。您可以在
isinstance
调用中使用
types.FunctionType

>>> import types
>>> types.FunctionType
<class 'function'>

>>> def f(): pass

>>> isinstance(f, types.FunctionType)
True
>>> isinstance(lambda x : None, types.FunctionType)
True
打开
(内置函数有不同的类型):

如果您正在执行一些特定于
类型.FunctionType
实例的操作,如反编译字节码或检查闭包变量,请使用
类型.FunctionType
,但如果您只需要一个对象像函数一样可调用,请使用
可调用

可调用(x)如果传递的对象可以在Python中调用,则
将返回true,但该函数在Python 3.0中不存在,正确地说,不会区分:

class A(object):
    def __call__(self):
        return 'Foo'

def B():
    return 'Bar'

a = A()
b = B

print type(a), callable(a)
print type(b), callable(b)
您将得到
True
True
作为输出

isinstance
可以很好地确定某个东西是否是函数(试试
isinstance(b,types.FunctionType)
);如果你真的想知道是否可以调用某个东西,你可以使用hasattr(b,“\uu call”
,或者试试

test_as_func = True
try:
    b()
except TypeError:
    test_as_func = False
except:
    pass

当然,这不会告诉您它是否可调用,而是在执行时抛出一个
TypeError
,或者一开始就不可调用。这对您可能无关紧要。

函数只是一个带有
\uuu调用\uuu
方法的类,所以您可以这样做

hasattr(obj, '__call__')
例如:

>>> hasattr(x, '__call__')
True

>>> x = 2
>>> hasattr(x, '__call__')
False
>>> def x():
...     raise TypeError
... 
>>> hasattr(x, '__call__')
True # Correct
>>> try:
...     x()
... except TypeError:
...     print "x was not callable"
... 
x was not callable # Wrong!
这是“最好”的方法,但根据您需要知道它是可调用的还是note的原因,您可以将它放在try/execpt块中:

try:
    x()
except TypeError:
    print "was not callable"
如果try/except比hasattr(x,“\uuu call\uuuu”):x()
更像Python'y,这是有争议的。。我想说
hasattr
更准确,因为您不会意外发现错误的类型错误,例如:

>>> hasattr(x, '__call__')
True

>>> x = 2
>>> hasattr(x, '__call__')
False
>>> def x():
...     raise TypeError
... 
>>> hasattr(x, '__call__')
True # Correct
>>> try:
...     x()
... except TypeError:
...     print "x was not callable"
... 
x was not callable # Wrong!
Python的2to3工具()建议:

import collections
isinstance(obj, collections.Callable)

似乎选择了这个方法而不是hasattr(x,“\uu调用”方法是因为。

在Python3中,我提出了
type(f)==type(lambda x:x)
,如果
f
是一个函数,则产生
True
,如果不是,则产生
False
。但是我想我更喜欢
isinstance(f,types.FunctionType)
,它感觉不那么特别。我想做
类型(f)是函数
,但那不起作用

您可以从模块导入
isfunction


如果您想检测语法上看起来像函数的所有东西:函数、方法、内置的fun/meth、lambda。。。但是排除可调用对象(定义了
\uuuu调用\uuu
方法的对象),然后尝试以下方法:

import types
isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType))

我将其与
is*()
checks in
inspect
模块的代码进行了比较,上面的表达式更加完整,尤其是当您的目标是过滤掉任何函数或检测对象的常规属性时。

在前面的回答之后,我得出了以下结论:

from pprint import pprint

def print_callables_of(obj):
    li = []
    for name in dir(obj):
        attr = getattr(obj, name)
        if hasattr(attr, '__call__'):
            li.append(name)
    pprint(li)

任何函数都是一个类,因此您可以使用实例x的类的名称并比较:


if(x.__class__.__name__ == 'function'):
     print "it's a function"

您可以检查用户定义的函数是否具有属性
函数名
函数文档
等,而不是检查
调用
(这不是函数独有的)。这对方法不起作用

>>> def x(): pass
... 
>>> hasattr(x, 'func_name')
True
另一种检查方法是使用
inspect
模块中的
isfunction()
方法

>>> import inspect
>>> inspect.isfunction(x)
True

要检查对象是否是方法,请使用
inspect.ismethod()

接受的答案在提供时被认为是正确的。因为它 事实证明,Python中的
callable()
是无法替代的 3.2:具体地说,
callable()
检查被调用对象的
tp\u call
字段 测试。没有简单的Python等价物。大多数建议的测试都是 大多数情况下,请更正:

>>> class Spam(object):
...     def __call__(self):
...         return 'OK'
>>> can_o_spam = Spam()


>>> can_o_spam()
'OK'
>>> callable(can_o_spam)
True
>>> hasattr(can_o_spam, '__call__')
True
>>> import collections
>>> isinstance(can_o_spam, collections.Callable)
True
我们可以通过从 班级。为了让事情更加精彩,在实例中添加一个假的调用

>>> del Spam.__call__
>>> can_o_spam.__call__ = lambda *args: 'OK?'
注意,这实际上是不可调用的:

>>> can_o_spam()
Traceback (most recent call last):
  ...
TypeError: 'Spam' object is not callable
callable()
返回正确的结果:

>>> callable(can_o_spam)
False
但是
hasattr
是错误的:

can\u o\u spam
毕竟有这个属性;只是打电话的时候没用 实例

更微妙的是,
isinstance()
也会出错:

>>> isinstance(can_o_spam, collections.Callable)
True
因为我们之前使用了此检查,后来删除了该方法,
abc.ABCMeta
缓存结果。可以说这是abc.ABCMeta中的一个bug。也就是说, 真的没有比这更精确的方法了 由于
typeobject->tp\u调用
插槽方法在任何其他w中都不可访问
>>> isinstance(can_o_spam, collections.Callable)
True
def myfunc(x):
  try:
    x()
  except TypeError:
    raise Exception("Not callable")
>>> import collections
>>> Test = collections.namedtuple('Test', [])
>>> callable(Test)
True
>>> hasattr(Test, '__call__')
True
>>> import inspect
>>> inspect.isfunction(Test)
False
>>> def t(): pass
>>> inspect.isfunction(t)
True
def isFunction1(f) :
    return type(f) == type(lambda x: x);

def isFunction2(f) :
    return 'function' in str(type(f));
>>> type(lambda x: x);
<type 'function'>
>>> str(type(lambda x: x));
"<type 'function'>"
# Look Maa, function! ... I ACTUALLY told my mom about this!
class A(object):
    def __init__(self):
        pass
    def __call__(self):
        print 'I am a Class'

MyClass = A()

def foo():
    pass

print hasattr(foo.__class__, 'func_name') # Returns True
print hasattr(A.__class__, 'func_name')   # Returns False as expected

print hasattr(foo, '__call__') # Returns True
print hasattr(A, '__call__')   # (!) Returns True while it is not a function
import types

def is_func(obj):
    return isinstance(obj, (types.FunctionType, types.LambdaType))


def f(x):
    return x


assert is_func(f)
assert is_func(lambda x: x)
#!/usr/bin/python3
# 2017.12.10 14:25:01 CST
# 2017.12.10 15:54:19 CST

import functools
import types
import pprint
class A():
    def __call__(self, a,b):
        print(a,b)
    def func1(self, a, b):
        print("[classfunction]:", a, b)
    @classmethod
    def func2(cls, a,b):
        print("[classmethod]:", a, b)
    @staticmethod
    def func3(a,b):
        print("[staticmethod]:", a, b)

def func(a,b):
    print("[function]", a,b)
#(1.1) built-in function
builtins_func = open
#(1.2) ordinary function
ordinary_func = func
#(1.3) lambda expression
lambda_func  = lambda a : func(a,4)
#(1.4) functools.partial
partial_func = functools.partial(func, b=4)

#(2.1) callable class instance
class_callable_instance = A()
#(2.2) ordinary class function
class_ordinary_func = A.func1
#(2.3) bound class method
class_bound_method = A.func2
#(2.4) static class method
class_static_func = A.func3
## list of functors
xfuncs = [builtins_func, ordinary_func, lambda_func, partial_func, class_callable_instance, class_ordinary_func, class_bound_method, class_static_func]
## list of type
xtypes = [types.BuiltinFunctionType, types.FunctionType, types.MethodType, types.LambdaType, functools.partial]
res = [callable(xfunc)  for xfunc in xfuncs]
print("functors callable:")
print(res)

"""
functors callable:
[True, True, True, True, True, True, True, True]
"""
res = [[isinstance(xfunc, xtype) for xtype in xtypes] for xfunc in xfuncs]

## output the result
print("functors' types")
for (row, xfunc) in zip(res, xfuncs):
    print(row, xfunc)

"""
functors' types
[True, False, False, False, False] <built-in function open>
[False, True, False, True, False] <function func at 0x7f1b5203e048>
[False, True, False, True, False] <function <lambda> at 0x7f1b5081fd08>
[False, False, False, False, True] functools.partial(<function func at 0x7f1b5203e048>, b=4)
[False, False, False, False, False] <__main__.A object at 0x7f1b50870cc0>
[False, True, False, True, False] <function A.func1 at 0x7f1b5081fb70>
[False, False, True, False, False] <bound method A.func2 of <class '__main__.A'>>
[False, True, False, True, False] <function A.func3 at 0x7f1b5081fc80>
"""
def func(a,b):
    print("[function]", a,b)

>>> callable(func)
True
>>> isinstance(func,  types.FunctionType)
True
>>> isinstance(func, (types.BuiltinFunctionType, types.FunctionType, functools.partial))
True
>>> 
>>> isinstance(func, (types.MethodType, functools.partial))
False
def a():pass
type(a) #<class 'function'>
str(type(a))=="<class 'function'>" #True

b = lambda x:x*2
str(type(b))=="<class 'function'>" #True
#import inspect             #import types
['isabstract',
 'isasyncgen',              'AsyncGeneratorType',
 'isasyncgenfunction', 
 'isawaitable',
 'isbuiltin',               'BuiltinFunctionType',
                            'BuiltinMethodType',
 'isclass',
 'iscode',                  'CodeType',
 'iscoroutine',             'CoroutineType',
 'iscoroutinefunction',
 'isdatadescriptor',
 'isframe',                 'FrameType',
 'isfunction',              'FunctionType',
                            'LambdaType',
                            'MethodType',
 'isgenerator',             'GeneratorType',
 'isgeneratorfunction',
 'ismethod',
 'ismethoddescriptor',
 'ismodule',                'ModuleType',        
 'isroutine',            
 'istraceback',             'TracebackType'
                            'MappingProxyType',
]
def detect_function(obj):
    return hasattr(obj,"__call__")

In [26]: detect_function(detect_function)
Out[26]: True
In [27]: callable(detect_function)
Out[27]: True
In [43]: callable(hasattr)
Out[43]: True
#check inspect.isfunction and type.FunctionType
In [46]: inspect.isfunction(detect_function)
Out[46]: True
In [47]: inspect.isfunction(hasattr)
Out[47]: False
In [48]: isinstance(detect_function, types.FunctionType)
Out[48]: True
In [49]: isinstance(getattr, types.FunctionType)
Out[49]: False
#so they both just applied to judge the user-definded
In [50]: isinstance(getattr, types.BuiltinFunctionType)
Out[50]: True
In [51]: isinstance(detect_function, types.BuiltinFunctionType)
Out[51]: False
str(type(a))=="<class 'function'>"
from types import BuiltinFunctionType, BuiltinMethodType,  FunctionType, MethodType, LambdaType
from functools import partial

def is_function(obj):
  return isinstance(obj, (BuiltinFunctionType, BuiltinMethodType,  FunctionType, MethodType, LambdaType, partial))

#-------------------------------------------------

def my_func():
  pass

def add_both(x, y):
  return x + y

class a:
  def b(self):
    pass

check = [

is_function(lambda x: x + x),
is_function(my_func),
is_function(a.b),
is_function(partial),
is_function(partial(add_both, 2))

]

print(check)
>>> [True, True, True, False, True]
if obj.__class__.__name__ in ['function', 'builtin_function_or_method']:
    print('probably a function')
if "function" in lower(obj.__class__.__name__):
    print('probably a function')