파이썬 변수가 함수인지 어떻게 감지합니까?
나는 변수가 있고 x
그것이 함수를 가리키는 지 아닌지 알고 싶습니다.
다음과 같이 할 수 있기를 바랐습니다.
>>> isinstance(x, function)
그러나 그것은 나에게 준다.
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
내가 고른 이유는
>>> type(x)
<type 'function'>
Python 2.x 또는 Python 3.2+ 용인 경우 callable()
. 이전에는 더 이상 사용되지 않았지만 이제는 더 이상 사용되지 않으므로 다시 사용할 수 있습니다. 여기에서 토론을 읽을 수 있습니다 : http://bugs.python.org/issue10518 . 다음과 같이 할 수 있습니다.
callable(obj)
이것이 Python 3.x이지만 3.2 이전 인 경우 객체에 __call__
속성 이 있는지 확인하십시오 . 다음과 같이 할 수 있습니다.
hasattr(obj, '__call__')
자주 제안되는 types.FunctionTypes
접근 방식은 내장 기능과 같이 통과하기를 원하는 많은 경우를 다루지 못하기 때문에 올바르지 않습니다.
>>> isinstance(open, types.FunctionType)
False
>>> callable(open)
True
오리 유형 개체의 속성을 확인하는 적절한 방법은 오리 크기의 컨테이너에 맞는지 확인하는 것이 아니라 돌팔이인지 묻는 것입니다. types.FunctionType
함수가 무엇인지에 대해 매우 구체적인 아이디어가 없으면 사용 하지 마십시오 .
내장 네임 스페이스에 생성자가없는 내장 유형 (예 : 함수, 생성기, 메서드)은 types
모듈에 있습니다. types.FunctionType
isinstance 호출에서 사용할 수 있습니다 .
In [1]: import types
In [2]: types.FunctionType
Out[2]: <type 'function'>
In [3]: def f(): pass
...:
In [4]: isinstance(f, types.FunctionType)
Out[4]: True
In [5]: isinstance(lambda x : None, types.FunctionType)
Out[5]: True
Python 2.1부터 모듈 isfunction
에서 가져올 수 있습니다 inspect
.
>>> from inspect import isfunction
>>> def f(): pass
>>> isfunction(f)
True
>>> isfunction(lambda x: x)
True
받아 들여진 대답은 그것이 옳다고 생각되는 제안 당시였습니다. 결과적 으로 Python 3.2로 돌아온을 대체 할 수 없습니다callable()
. 특히 테스트중인 객체 callable()
의 tp_call
필드를 확인합니다 . 평범한 파이썬은 없습니다. 대부분의 제안 테스트는 대부분 정확합니다.
>>> 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
__call__
클래스 에서을 제거하여 몽키 렌치를 던져 넣을 수 있습니다 . 그리고 더 흥미 진진하게 유지 __call__
하기 위해 인스턴스에 가짜 를 추가하십시오 !
>>> 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
입니다 잘못된 :
>>> hasattr(can_o_spam, '__call__')
True
can_o_spam
결국 그 속성이 있습니다. 인스턴스를 호출 할 때 사용되지 않습니다.
더 미묘한 것도이 isinstance()
문제를 해결합니다.
>>> isinstance(can_o_spam, collections.Callable)
True
이 검사를 이전에 사용하고 나중에 메서드를 삭제했기 때문에 abc.ABCMeta
결과를 캐시합니다. 틀림없이 이것은 abc.ABCMeta
. 즉, 슬롯 방법은 다른 방법으로 액세스 할 수 없기 때문에 자체 를 사용하는 것보다 결과보다 더 정확한 결과를 생성 할 수있는 방법은 없습니다.callable()
typeobject->tp_call
그냥 사용 callable()
다음은 부울을 반환해야합니다.
callable(x)
Python의 2to3 도구 ( http://docs.python.org/dev/library/2to3.html )는 다음을 제안합니다.
import collections
isinstance(obj, collections.Callable)
http://bugs.python.org/issue7006hasattr(x, '__call__')
때문에 메서드 대신 선택된 것 같습니다 .
callable(x)
전달 된 객체가 Python에서 호출 될 수 있지만 함수가 Python 3.0에 존재하지 않는 경우 true 를 반환하고 올바르게 말하면 다음을 구분하지 않습니다.
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)
<class 'A'> True
그리고 <type function> True
출력으로 얻을 수 있습니다.
isinstance
무언가가 함수인지 판단하기에 완벽하게 잘 작동합니다 (try isinstance(b, types.FunctionType)
). 무언가를 호출 할 수 있는지 알고 싶다면 사용 hasattr(b, '__call__')
하거나 시도해 볼 수 있습니다.
test_as_func = True
try:
b()
except TypeError:
test_as_func = False
except:
pass
물론 이것은 호출 가능 여부를 알려주지 않지만 TypeError
실행될 때 a를 던지 거나 처음에는 호출 할 수 없습니다. 그것은 당신에게 중요하지 않을 수 있습니다.
함수, 메서드, 내장 fun / meth, 람다 등 구문 적으로 함수처럼 보이는 모든 것을 감지하고 싶지만 호출 가능한 객체 ( 메서드가 정의 된 객체)를 제외하려면__call__
다음을 시도하십시오.
import types
isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType))
나는 이것을 모듈 의 is*()
검사 코드와 비교 했으며 inspect
위의 표현식은 특히 목표가 함수를 필터링하거나 객체의 일반 속성을 감지하는 경우 훨씬 더 완전합니다.
몇 가지 다른 방법이 있습니다.
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!
을 사용해보십시오 callable(x)
.
함수는 __call__
메서드가 있는 클래스 일 뿐이 므로 할 수 있습니다.
hasattr(obj, '__call__')
예를 들면 :
>>> hasattr(x, '__call__')
True
>>> x = 2
>>> hasattr(x, '__call__')
False
이것이 "가장 좋은"방법이지만 호출 가능 여부를 알아야하는 이유에 따라 try / execpt 블록에 넣을 수 있습니다.
try:
x()
except TypeError:
print "was not callable"
try / except가 if hasattr(x, '__call__'): x()
.. hasattr
실수로 잘못된 TypeError를 잡을 수 없기 때문에 더 정확 하다고 말할 수 있습니다. 예를 들어 :
>>> def x():
... raise TypeError
...
>>> hasattr(x, '__call__')
True # Correct
>>> try:
... x()
... except TypeError:
... print "x was not callable"
...
x was not callable # Wrong!
당신이 배운 경우 C++
, 당신은 잘 알고 있어야합니다 function object
또는 functor
, 그 수있는 모든 개체를 의미합니다 be called as if it is a function
.
C ++에서는 an ordinary function
함수 객체이고 함수 포인터도 마찬가지입니다. 보다 일반적으로을 정의하는 클래스의 객체도 마찬가지입니다 operator()
. C ++ 11과 큰에서 the lambda expression
는 IS functor
너무합니다.
유사성, Python에서는 functors
모두 callable
. An ordinary function
호출 가능, a lambda expression
호출 가능, a functional.partial
호출 가능,의 인스턴스 class with a __call__() method
호출 가능.
좋습니다. 질문으로 돌아갑니다. I have a variable, x, and I want to know whether it is pointing to a function or not.
날씨를 판단하고 싶다면 객체가 함수처럼 작동한다면에서
callable
제안한 방법@John Feminella
은 괜찮습니다.원하는 경우
judge whether a object is just an ordinary function or not
(호출 가능한 클래스 인스턴스 또는 람다식이 아님)xtypes.XXX
제안하는@Ryan
것이 더 나은 선택입니다.
그런 다음 해당 코드를 사용하여 실험을 수행합니다.
#!/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]
functor가 호출 가능한지 판단하십시오. 보시다시피, 그들은 모두 호출 가능합니다.
res = [callable(xfunc) for xfunc in xfuncs]
print("functors callable:")
print(res)
"""
functors callable:
[True, True, True, True, True, True, True, True]
"""
펑터의 유형 (types.XXX)을 판단합니다. 그렇다면 펑터의 유형은 모두 동일하지 않습니다.
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
받아 들여진 대답으로 John Feminella는 다음과 같이 말했습니다.
오리 유형 개체의 속성을 확인하는 적절한 방법은 오리 크기의 컨테이너에 맞는지 확인하는 것이 아니라 돌팔이인지 묻는 것입니다. "직접 비교"접근 방식은 내장과 같은 많은 함수에 대해 잘못된 답을 제공합니다.
함수를 엄격하게 구분하는 두 개의 라이브러리가 있지만 필자는 완전한 비교 테이블을 그립니다.
8.9. types — 동적 유형 생성 및 내장 유형의 이름 — Python 3.7.0 문서
30.13. inspect — 라이브 객체 검사 — Python 3.7.0 문서
#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
확인 builtin function
In [50]: isinstance(getattr, types.BuiltinFunctionType)
Out[50]: True
In [51]: isinstance(detect_function, types.BuiltinFunctionType)
Out[51]: False
요약
고용 callable
기능을 확인 오리 유형,
사용 types.BuiltinFunctionType
이 더 지정한 경우 수요.
클래스에도 __call__
메서드 가 있으므로 다른 솔루션을 권장합니다.
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
Python 클래스도 호출 가능합니다.
함수를 얻으려면 (그리고 함수로 표준 함수와 람다를 의미합니다) 다음을 사용하십시오.
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)
대신 검사의 '__call__'
(기능에 배타적이지 인), 당신은 사용자 정의 함수는 속성이 있는지 여부를 확인할 수 있습니다 func_name
, func_doc
등이이 방법에 대한 작업을하지 않습니다.
>>> def x(): pass
...
>>> hasattr(x, 'func_name')
True
확인하는 또 다른 방법은 모듈 의 isfunction()
방법을 사용하는 것입니다 inspect
.
>>> import inspect
>>> inspect.isfunction(x)
True
객체가 메소드인지 확인하려면 inspect.ismethod()
어떤 함수가 클래스이므로 인스턴스 x의 클래스 이름을 가져와 비교할 수 있습니다.
if(x.__class__.__name__ == 'function'):
print "it's a function"
사용하는 솔루션 hasattr(obj, '__call__')
과 callable(.)
몇 가지 답변에서 언급이 주요 단점이있다 : 두도 반환 True
A를 클래스와 클래스의 인스턴스에 대한 __call__()
방법. 예 :
>>> import collections
>>> Test = collections.namedtuple('Test', [])
>>> callable(Test)
True
>>> hasattr(Test, '__call__')
True
객체가 사용자 정의 함수인지 확인하는 적절한 방법 중 하나는 다음을 사용하는 것입니다 isfunction(.)
.
>>> import inspect
>>> inspect.isfunction(Test)
False
>>> def t(): pass
>>> inspect.isfunction(t)
True
다른 유형을 확인해야하는 경우 inspect — Inspect live objects를 참조하십시오 .
정확한 기능 검사기
callable 은 아주 좋은 솔루션입니다. 그러나 나는 이것을 John Feminella와 반대되는 방식으로 다루고 싶었습니다. 다음과 같이 처리하는 대신 :
오리 유형 개체의 속성을 확인하는 적절한 방법은 오리 크기의 컨테이너에 맞는지 확인하는 것이 아니라 돌팔이인지 묻는 것입니다. "직접 비교"접근 방식은 내장과 같은 많은 함수에 대해 잘못된 답을 제공합니다.
다음과 같이 처리합니다.
어떤 것이 오리인지 확인하는 적절한 방법은 꽥꽥 거리는 것이 아니라 표면에서 오리처럼 보이는지 확인하는 대신 여러 필터를 통해 실제로 오리인지 확인하는 것입니다.
어떻게 구현할 것인가
'types'모듈에는 함수를 감지하기위한 많은 클래스가 있으며, 가장 유용한 것은 types.FunctionType입니다 . 그러나 메서드 유형, 내장 유형 및 람다 유형과 같은 다른 많은 클래스 도 있습니다. 또한 'functools.partial'객체를 함수로 간주합니다.
함수인지 확인하는 간단한 방법은 이러한 모든 유형에 대해 isinstance 조건을 사용하는 것입니다. 이전에는 위의 모든 클래스를 상속하는 기본 클래스를 만들고 싶었지만 Python이 위 클래스 중 일부에서 상속하는 것을 허용하지 않기 때문에 그렇게 할 수 없습니다.
다음은 어떤 클래스가 어떤 함수를 분류 할 수 있는지에 대한 표입니다.
그것을하는 코드
자, 이것은 위에서 설명한 모든 작업을 수행하는 코드입니다.
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]
하나의 거짓은 is_function (partial)입니다. 왜냐하면 그것은 함수가 아니라 클래스이기 때문입니다. 그리고 이것은 클래스가 아니라 정확히 함수입니다. 다음은 코드를 사용해 볼 수 있는 미리보기 입니다.
결론
호출 (OBJ)는 당신이로 가고 싶은 경우 객체가 함수가 있는지 확인하기 위해 사용되는 방법입니다 오리 타이핑 을 통해 절대 .
사용자 정의 is_function (obj) , 아마도 일부 편집을 통해 호출 가능한 클래스 인스턴스를 함수로 계산하지 않고 내장 함수 만 정의 하거나 lambda , def로 정의한 경우 객체가 함수인지 확인하는 데 선호되는 방법입니다. , 또는 부분 .
그리고 나는 그것이 모든 것을 마무리한다고 생각합니다. 좋은 하루 되세요!
Python3에서는 if 가 함수이고 그렇지 않은 경우 type (f) == type (lambda x:x)
를 산출 True
합니다 . 그러나 나는 덜 임시적인 느낌을 선호한다고 생각합니다 . 하고 싶었지만 작동하지 않습니다.f
False
isinstance (f, types.FunctionType)
type (f) is function
이전 답변에 따라 다음과 같이 생각했습니다.
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)
값이 호출 가능하면 코드가 계속해서 호출을 수행하면 호출을 수행하고 catch TypeError
합니다.
def myfunc(x):
try:
x()
except TypeError:
raise Exception("Not callable")
다음은 그것을 확인하는 "반복 방법"입니다. 또한 람다와 함께 작동합니다.
def a():pass
type(a) #<class 'function'>
str(type(a))=="<class 'function'>" #True
b = lambda x:x*2
str(type(b))=="<class 'function'>" #True
이것은 나를 위해 작동합니다.
str(type(a))=="<class 'function'>"
참고 URL : https://stackoverflow.com/questions/624926/how-do-i-detect-whether-a-python-variable-is-a-function
'Program Tip' 카테고리의 다른 글
스택 추적이란 무엇이며 애플리케이션 오류를 디버그하는 데 어떻게 사용할 수 있습니까? (0) | 2020.10.02 |
---|---|
파이썬에서 __future__는 무엇에 사용되며 어떻게 / 언제 사용되며 어떻게 작동하는지 (0) | 2020.10.02 |
PHP로 POST 요청을 보내려면 어떻게합니까? (0) | 2020.10.02 |
Linux의 특정 포트에서 실행되는 프로세스를 종료하는 방법은 무엇입니까? (0) | 2020.10.02 |
현재 변경 사항을 git [duplicate]의 다른 지점에 커밋하는 방법 (0) | 2020.10.02 |