파이썬 변수가 함수인지 어떻게 알 수 있습니까?


687

변수 x가 있으며 함수를 가리키는 지 여부를 알고 싶습니다.

나는 다음과 같은 일을 할 수 있기를 바랐다.

>>> isinstance(x, function)

그러나 그것은 나에게 준다 :

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name 'function' is not defined

내가 선택한 이유는

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

37
나는 몇 가지를 찾아 문제를 해결 작업 답의 숫자로 우울 해요 통화 @ryan에 의해 제안 속성 또는 호출 기능 ... 깨끗한 방법은 유형의 (a) == types.functionType에 관한 것입니다
애 스터

44
@AsTeR 오리 유형 개체의 속성을 확인하는 적절한 방법은 오리 크기의 컨테이너에 맞는지 확인하지 않고 물체가 qua는지 묻는 것입니다. "직접 비교"접근 방식은 내장 기능과 같은 많은 기능에 대해 잘못된 답변을 제공합니다.
John Feminella

3
@JohnFeminella 원칙적으로 동의합니다. OP는 함수인지 여부에 따라 호출 가능 여부를 묻지 않았습니다. 아마도 그는 예를 들어 함수와 클래스 사이에 구별이 필요하다고 주장 할 수 있습니까?
McKay

3
내 목적을 위해 insepct.getsource다양한 객체에 사용 하고 싶었 기 때문에 여기에 왔으며 실제로 객체를 호출 할 수 있는지 여부가 아니라 '기능'을 제공 할 수 있는지 여부가 중요합니다 type(obj). Google이 나를 여기로 인도했기 때문에 AsTeR의 의견이 가장 유용한 답변이라고 말했습니다. 사람들이 찾 __call__거나 인터넷을 이용할 수있는 다른 장소가 많이 있습니다 callable.
tsbertalan

4
그것은 자본 F.와 types.FunctionType입니다 @AsTeR
벤의 Mares

답변:


892

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함수가 무엇인지에 대한 구체적인 아이디어가 없다면 사용 하지 마십시오 .


73
또한 함수인지 여부를 알려주지 않고 호출 할 수있는 경우에만 알려줍니다.
Chris B.

23
구별이 중요한지 여부에 따라 응용 프로그램에 따라 다릅니다. 나는 그것이 원래의 질문에 대한 것이 아니라는 것이 옳다고 생각하지만, 그것은 확실하지 않습니다.
Chris B.

5
클래스에는 호출 함수가 첨부 될 수 있습니다. 따라서 이것은 구별하기에 좋은 방법이 아닙니다. Ryan의 방법이 더 좋습니다.
Brian Bruggeman

43
"Duck 타이핑"개념은 이것을 더 나은 답으로 만들어줍니다. 예를 들어 "기능처럼 작동하는 것이 중요한 이유는 무엇입니까?"
jcomeau_ictx

8
예를 들어 데코레이터를 작성할 때 호출 가능한 함수와 함수의 구별이 중요한 유스 케이스가 있습니다 (Ryan의 답변에 대한 내 의견 참조).
Turion

267

내장 네임 스페이스에 생성자가없는 내장 유형 (예 : 함수, 생성기, 메서드)이 types모듈에 있습니다. 당신은 사용할 수 있습니다 types.FunctionTypeisinstance전화 :

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

여기에는 일반적으로 필요하지 않은 매우 구체적인 "기능"개념이 사용됩니다. 예를 들어 zip(기술적으로 클래스)를 거부합니다 .

>>> type(zip), isinstance(zip, types.FunctionType)
(<class 'type'>, False)

open (내장 함수의 유형이 다릅니다) :

>>> type(open), isinstance(open, types.FunctionType)
(<class 'builtin_function_or_method'>, False)

random.shuffle(숨겨진의 기술적 방법 random.Random예) :

>>> type(random.shuffle), isinstance(random.shuffle, types.FunctionType)
(<class 'method'>, False)

types.FunctionType바이트 코드를 디 컴파일하거나 클로저 변수를 검사하는 것과 같이 인스턴스에 특정한 작업을 수행하는 경우을 사용 types.FunctionType하지만 함수처럼 호출 할 수있는 객체가 필요한 경우을 사용하십시오 callable.


5
질문에 +1합니다. 그러나 객체가 함수인지 또는 호출 가능한 객체인지를 추측하는 것은 일반적으로 실수입니다. OP의 추가 정보가 없으면 당연히이를 기각하기는 어렵지만 여전히 ...
bobince

47
예를 들어 'open'과 같은 내장 함수의 경우 실제로 False를 반환합니다. 따라서 구체적으로 isinstance (f, (types.FunctionType, types.BuiltinFunctionType))를 사용해야합니다. 물론 함수 나 메서드가 아닌 함수 만 엄격히 원한다면
Lukasz Korzybski

5
@ ŁukaszKorzybski 그리고 더 예의 바르려면 functools.partial을 확인해야합니다 : isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))또는 f.func그러한 경우 확인하십시오.
estani 2012

3
@bobince,이 유스 케이스는 어떻습니까 : @fooas @foo와 as 모두 사용할 수 있는 데코레이터를 작성하고 싶습니다 @foo(some_parameter). 그런 다음 호출 할 대상을 확인해야합니다. 예를 들어 장식하는 함수 (첫 번째 경우) 또는 매개 변수 (두 번째 경우에는 추가 데코레이터를 반환해야 함)
Turion

types.BuiltinFunctionType또한 ( "normal") 내장 메소드 의 유형입니다 callable. 경로를 사용 하지 않을 경우 허용하지 않을 것 입니다.
user2357112는

92

Python 2.1부터는 모듈 isfunction에서 가져올 수 있습니다 inspect.

>>> from inspect import isfunction
>>> def f(): pass
>>> isfunction(f)
True
>>> isfunction(lambda x: x)
True

3
멋지지만 openand와 같은 내장 함수에 대해서는 False를 반환하는 것 같습니다 hasattr.
Zecc

12
@Zecc isbuiltin 이 바로 그런 것입니다.
Paolo

13
inspect.isfunctiondocstring : "객체가 사용자 정의 함수 인 경우 true를 반환
Mark Mikofski

4
'isfunction'은 functool.partial 함수를 인식하지 않습니다.
ishmael

74

받아 들여진 대답은 정확한 것으로 생각되었을 당시에있었습니다. 결과적 으로 파이썬 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()


5
hasattr(o, '__call__')접근 의 함정에 대한 놀라운 그림과 callable()가능한 경우 왜 우월한가.
MestreLion

39

다음은 부울을 반환해야합니다.

callable(x)

1
이렇게하면 문제가 해결되지만, 여전히 미스터리가 만들어졌습니다. x가 모듈 builtin 에서 'function'클래스 이고 help (x .__ class__)가 "class function"을 설명하면 왜 "function"이 "정의되지 않은"것입니까?
Ken

1
"function"은 키워드 또는 내장 유형이 아닙니다. 함수 유형은 "types"모듈에서 "types.FunctionType"으로 정의
Chris B.


19

callable(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)

당신은 얻을 것이다 <class 'A'> True<type function> True출력으로.

isinstance무언가가 함수인지 확인하기 위해 완벽하게 작동합니다 (시도 isinstance(b, types.FunctionType)). 무언가를 불러 낼 수 있는지 정말로 알고 싶다면 hasattr(b, '__call__')그것을 사용 하거나 시도해보십시오.

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

물론 이것은 호출 가능 여부를 알려주지 않지만 TypeError처음 실행될 때 호출 할 수 있는지 또는 호출 할 수 없는지를 나타 냅니다. 그것은 당신에게 중요하지 않을 수 있습니다.


8
그것을 부르는 것은 나쁜 생각입니다. 부작용이 있거나 실제로 무언가를하는데 시간이 오래 걸리는 경우 어떻게해야합니까?
asmeurer

@asmeurer-왜 함수를 호출하지 않으면 함수인지 알아야합니까?
detly

1
@detly : 디버깅을 위해 정기적으로 객체의 모든 변수를 인쇄하고 싶습니다. 메서드는 일반적으로 나에게 유용하지 않으므로 실행하고 싶지 않습니다. 결국 나는 단지 호출 할 수없는 모든 속성을 해당 값으로
나열

2
그냥 있기 때문에 당신이있어 그것을 호출하지 않을거야 의미하지 않는다 호출하지. 아마도 당신은 파견을하고 있습니다.
asmeurer

4
호출 가능 여부를 알기 위해 예외를 사용하는 데 큰 문제가 있습니다. 무엇는 경우 입니다 호출하지만, 호출 당신이 찾고있는 예외가 발생합니다? 당신은 모두 자동으로 오류 무시거야 하고 그것을 호출 여부 오진을. EAFP를 사용하는 경우 실제로 시도를 너무 많이하지 않으려 고하지만이 사용 사례에 대해서는 그렇게 할 수있는 방법이 없습니다.
Ben

15

구문 적으로 함수처럼 보이는 모든 기능, 즉 함수, 메소드, 내장 fun / meth, lambda ...를 감지하지만 호출 가능한 오브젝트 ( 메소드가 정의 된 오브젝트)를 제외하려면__call__ 다음 중 하나를 시도하십시오.

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

나는 이것을 모듈 의 is*()검사 코드와 비교 inspect했으며 특히 목표가 함수를 필터링하거나 객체의 규칙적인 속성을 감지하는 경우 위의 표현이 훨씬 더 완벽합니다.


types모듈을 알려 주셔서 감사합니다 . make_stemmer()때로는 함수와 때로는 호출 가능한 Stemmer인스턴스를 반환 하는 팩토리를 테스트하고 있었고 차이를 감지해야했습니다.
호브


6

당신이 배운 경우 C++, 당신은 function object또는에 익숙해야, 할 functor수있는 물건을 의미합니다 be called as if it is a function.

C ++에서는 an ordinary function함수 객체이며 함수 포인터도 있습니다. 보다 일반적으로를 정의하는 클래스의 객체도 마찬가지입니다 operator(). C ++ 11과 큰에서 the lambda expression는 IS functor너무합니다.

비슷하게 파이썬에서는 이것들 functors이 모두 callable입니다. An ordinary function호출 가능, a lambda expression호출 가능, 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]

펑터가 호출 가능하다고 판결하십시오. 보시다시피, 모두 호출 가능합니다.

res = [callable(xfunc)  for xfunc in xfuncs]
print("functors callable:")
print(res)

"""
functors callable:
[True, True, True, True, True, True, True, True]
"""

펑터의 유형 (유형 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>
"""

데이터를 사용하여 호출 가능한 functor 유형의 테이블을 그립니다.

여기에 이미지 설명을 입력하십시오

그런 다음 적절한 펑터 유형을 선택할 수 있습니다.

같은 :

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

6

허용 된 답변으로 John Feminella는 다음과 같이 말했습니다.

오리 유형 개체의 속성을 확인하는 올바른 방법은 오리 크기의 컨테이너에 맞는지 확인하지 말고 떨리는 지 묻는 것입니다. "직접 비교"접근 방식은 내장 기능과 같은 많은 기능에 대해 잘못된 답변을 제공합니다.

함수를 엄격하게 구별하기 위해 두 개의 라이브러리가 있지만 필자는 필적할만한 표를 그립니다.

8.9. 유형 — 동적 유형 작성 및 내장 유형의 이름 — Python 3.7.0 documentation

30.13. 검사 — 라이브 객체 검사 — Python 3.7.0 documentation

#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이 더 지정한 경우 수요.


5

함수는 __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가 python보다 더 많은 경우 논란의 여지가 있습니다 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!

예외 처리를 사용하여 예상치 못한 동작 만 방지하고 논리 흐름에는 절대 사용하지 마십시오. 확실히 Pythonic이 아닙니다.
gotgenes 2016 년

자 hasattr은 기본적으로 try / except 블록에서 getattr을 수행합니다 (C에도 있음). blog.jancewicz.net/2007/10/reflection-hasattr.html
dbr

@ dbr : 그러나 hasattr은 더 미적입니다.
Nikhil Chelliah 2016 년

5

다른 몇 가지 방법이 있습니다.

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!

이거 좋다! 모든 버전의 python2.x 및 python3.x에서 작동합니다!
Saurav Kumar

4

대신 검사의 '__call__'(기능에 배타적이지 인), 당신은 사용자 정의 함수는 속성이 있는지 여부를 확인할 수 있습니다 func_name, func_doc등이이 방법에 대한 작업을하지 않습니다.

>>> def x(): pass
... 
>>> hasattr(x, 'func_name')
True

확인하는 또 다른 방법은 모듈 의 isfunction()방법을 사용하는 것입니다 inspect.

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

객체가 메소드인지 확인하려면 inspect.ismethod()


4

클래스에도 __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

1
John Feminella의 답변 hasattr(obj, '__call__')은 모호합니다.
GoingMyWay

4

파이썬 클래스도 호출 가능합니다.

함수를 얻으려면 (그리고 함수로 표준 함수와 람다를 의미합니다)

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)

2

클래스가 무엇이든 함수이므로 인스턴스 x 클래스의 이름을 사용하여 다음을 비교할 수 있습니다.


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

2

일부 답변에서 사용 hasattr(obj, '__call__')하고 callable(.)언급 한 솔루션 에는 주요 단점이 있습니다. 둘 다 메소드 True와 함께 클래스 및 클래스 인스턴스를 반환 합니다 __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-라이브 객체 검사를 살펴보십시오 .


2

정확한 기능 검사기

호출 가능 은 매우 좋은 솔루션입니다. 그러나 나는 이것을 John Feminella와 반대되는 방식으로 취급하고 싶었습니다. 이것을 다음과 같이 취급하는 대신 :

오리 유형 개체의 속성을 확인하는 올바른 방법은 오리 크기의 컨테이너에 맞는지 확인하지 말고 떨리는 지 묻는 것입니다. "직접 비교"접근 방식은 내장 기능과 같은 많은 기능에 대해 잘못된 답변을 제공합니다.

우리는 이것을 다음과 같이 취급 할 것입니다 :

오리가 있는지 확인하는 올바른 방법은 오리가 qua 수 있는지 확인하는 것이 아니라 표면에서 오리처럼 보이는지 확인하는 대신 실제로 여러 필터를 통해 오리인지 확인하는 것입니다.

어떻게 구현할 것인가

'types'모듈에는 함수를 감지 할 수있는 많은 클래스가 있습니다. types.FunctionType 이지만 메소드 유형, 내장 유형 및 람다 유형과 같은 다른 유형도 많이 있습니다. 또한 'functools.partial'객체를 함수로 간주합니다.

함수인지 확인하는 간단한 방법은 이러한 모든 유형에 대해 인스턴스 조건을 사용하는 것입니다. 이전에는 위의 모든 항목을 상속받는 기본 클래스를 만들고 싶었지만 Python에서는 위의 클래스 중 일부를 상속 할 수 없으므로 그렇게 할 수 없습니다.

다음은 어떤 클래스가 어떤 함수를 분류 할 수 있는지에 대한 표입니다.

kinght- 金의 함수 테이블 kinght- 金의 위 함수 테이블

그것을하는 코드

자, 이것은 위에서 설명한 모든 작업을 수행하는 코드입니다.

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로 정의 함수 만 사용하는 경우 객체가 함수인지 확인하는 기본 방법입니다. 또는 partial .

그리고 나는 그것이 모든 것을 마무리한다고 생각합니다. 좋은 하루 되세요!


1

Python3에서는 if 가 함수이고 그렇지 않은 경우 결과 type (f) == type (lambda x:x)를 산출 했습니다. 그러나 나는 덜 선호한다고 생각합니다 . 하고 싶었지만 작동하지 않습니다.TruefFalseisinstance (f, types.FunctionType)type (f) is function


0

이전 답변에 이어, 나는 이것을 생각해 냈습니다.

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)

0

당신은 이것을 시도 할 수 있습니다 :

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')

-1

값이 호출 가능한 경우 코드가 계속 호출을 수행하는 경우 호출을 수행하고 catch하십시오 TypeError.

def myfunc(x):
  try:
    x()
  except TypeError:
    raise Exception("Not callable")

4
이것은 위험합니다. 부작용 x이 무엇인지 모릅니다 .
cwallenpoole

-2

다음은이를 확인하는 "재배 방법"입니다. 또한 람다와 함께 작동합니다.

def a():pass
type(a) #<class 'function'>
str(type(a))=="<class 'function'>" #True

b = lambda x:x*2
str(type(b))=="<class 'function'>" #True

-3

이것은 나를 위해 작동합니다 :

str(type(a))=="<class 'function'>"

1
결과가 빈 문자열인지 어떻게 알 수 있습니까? 함수를 들어, 내가 얻을 "<type 'function'>"정수를 들어, 내가 얻을 "<type 'int'>"내가 당신을 위해 일하고 표시되지 않습니다, 그래서 : /
pawamoy

이제는 Python 3에서만 작동합니다. :) 원래 의도의 의도에 따라 불완전합니다. 내장 open기능을 고려해야합니까? 파이썬 3에서 str(type(open))제공합니다 <class 'builtin_function_or_method'>.
pawamoy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.