मैं कैसे पता लगा सकता हूं कि पायथन चर एक फ़ंक्शन है?


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
मैं कुछ कॉल विशेषता या कॉल करने योग्य फ़ंक्शन की तलाश में समस्या के आसपास काम करने वाले उत्तरों की संख्या से उदास हूं ... एक साफ तरीका टाइप (a) == type.functionType है जैसा कि @ryan द्वारा सुझाया गया है
AsTeR

44
@AsTeR डक-टाइप की गई वस्तुओं के गुणों की जांच करने का उचित तरीका यह है कि वे उनसे पूछें कि क्या वे शांत हैं, यह देखने के लिए नहीं कि वे बतख के आकार के कंटेनर में फिट हैं या नहीं। "सीधे तुलना करें" दृष्टिकोण कई कार्यों के लिए गलत जवाब देगा, जैसे कि बिलिंस।
जॉन फेमिनाला

3
@JohnFeminella जबकि मैं सिद्धांत रूप में आपके साथ सहमत हूं। ओपी ने यह नहीं पूछा कि क्या यह कॉल करने योग्य था, अगर यह एक फ़ंक्शन है। शायद यह तर्क दिया जा सकता है कि उन्हें बीच अंतर की आवश्यकता थी, उदाहरण के लिए, कार्य और वर्ग?
मैके 15

3
अपने उद्देश्यों के लिए, मैं यहां आया क्योंकि मैं insepct.getsourceविभिन्न वस्तुओं पर उपयोग करना चाहता था , और यह वास्तव में मायने नहीं रखता कि क्या वस्तु कॉल करने योग्य थी, लेकिन क्या यह ऐसा कुछ था जो इसके लिए 'फ़ंक्शन' देगा type(obj)। चूंकि Google ने मुझे यहां पहुंचाया, मैं कहूंगा कि AsTeR की टिप्पणी सबसे उपयोगी उत्तर थी (मेरे लिए)। लोगों को खोजने __call__या करने के लिए इंटरनेट पर बहुत सारी जगह हैं callable
tsbertalan

4
@AsTeR यह एक प्रकार है। FunctionType, एक पूंजी एफ के साथ
बेन मार्स

जवाबों:


892

यदि यह Python 2.x के लिए है या Python 3.2+ के लिए है, तो आप भी उपयोग कर सकते हैं callable()। यह पदावनत हुआ करता था, लेकिन अब इसका उपयोग नहीं किया गया है, इसलिए आप इसे फिर से उपयोग कर सकते हैं। : आप चर्चा यहाँ पढ़ सकते हैं http://bugs.python.org/issue10518 । आप इसके साथ कर सकते हैं:

callable(obj)

यदि यह पायथन 3.x के लिए है, लेकिन 3.2 से पहले, जांच लें कि ऑब्जेक्ट में कोई __call__विशेषता है या नहीं। आप इसके साथ कर सकते हैं:

hasattr(obj, '__call__')

अक्सर सुझाए गए types.FunctionTypesदृष्टिकोण सही नहीं होते हैं क्योंकि यह कई मामलों को कवर करने में विफल रहता है जो आप संभवतः इसे पास करना चाहते हैं, जैसे बिल्टइन के साथ:

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

>>> callable(open)
True

बतख-टाइप की गई वस्तुओं के गुणों की जांच करने का उचित तरीका यह है कि वे उनसे पूछें कि क्या वे शांत हैं, यह देखने के लिए नहीं कि वे बतख के आकार के कंटेनर में फिट हैं या नहीं। types.FunctionTypeजब तक आपके पास कोई विशिष्ट विचार न हो कि फ़ंक्शन क्या है, तब तक उपयोग न करें ।


73
यह भी आपको यह नहीं बताएगा कि क्या यह एक फ़ंक्शन है - बस अगर यह कहा जा सकता है।
क्रिस बी।

23
आवेदन पर निर्भर करता है कि क्या अंतर मायने रखता है या नहीं; मुझे संदेह है कि आप सही हैं कि यह मूल प्रश्न के लिए नहीं है, लेकिन यह निश्चित है।
क्रिस बी।

5
कक्षाओं में इससे जुड़ा एक कॉल फ़ंक्शन हो सकता है। तो यह निश्चित रूप से भेद करने के लिए एक अच्छी विधि नहीं है। रयान का तरीका बेहतर है।
ब्रायन ब्रूगमैन

43
"बत्तख टाइपिंग" अवधारणा इसे बेहतर उत्तर बनाती है, उदाहरण के लिए "जब तक यह एक कार्य करता है तो इससे क्या फर्क पड़ता है?"
jcomeau_ictx

8
ऐसे यूसेकस हैं जहां एक कॉल करने योग्य और एक फ़ंक्शन के बीच का अंतर महत्वपूर्ण है, उदाहरण के लिए जब एक डेकोरेटर लिखते हैं (रयान के जवाब पर मेरी टिप्पणी देखें)।
Turion

267

बिल्ट-इन प्रकार के निर्माणकर्ता जिनके पास अंतर्निहित नेमस्पेस (जैसे फ़ंक्शन, जनरेटर, विधियाँ) 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

ध्यान दें कि यह "फ़ंक्शन" की एक बहुत ही विशिष्ट धारणा का उपयोग करता है जो आमतौर पर आपकी ज़रूरत नहीं है। उदाहरण के लिए, यह अस्वीकार करता है 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 प्रश्न का उत्तर। हालांकि, यह अनुमान लगाने की कोशिश करना कि कोई वस्तु एक फ़ंक्शन है - या यहां तक ​​कि अगर यह कोई कॉल करने योग्य ऑब्जेक्ट है - तो आमतौर पर एक गलती है। ओपी से अधिक जानकारी के बिना इसे हाथ से बाहर करना मुश्किल है, लेकिन फिर भी ...
बॉब

47
यह वास्तव में निर्मित कार्यों के लिए गलत लौटाएगा, जैसे 'ओपन' जैसे। तो विशिष्ट होने के लिए आपको आइंस्टीन (f, (types.FunctionType, types.BuiltinFunctionType)) का उपयोग करना होगा। और निश्चित रूप से यदि आप कड़ाई से सिर्फ कार्य करना चाहते हैं, तो न तो कॉलबेल और न ही तरीके।
लुकाज़ कोरज़ीबकी

5
@ ToukaszKorzybski और अधिक उत्कृष्ट होने के लिए ... आपको फंक्शनल टूलशिप के लिए भी जाँच करनी चाहिए: isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))या f.funcऐसे मामले में जाँच करनी चाहिए ।
एस्टानी

3
@bobince, कैसे इस USECASE के बारे में: मैं एक डेकोरेटर लिखना चाहते @fooहै कि मैं दोनों के रूप में उपयोग कर सकते हैं @fooऔर के रूप में @foo(some_parameter)। इसके बाद यह जांचने की जरूरत है कि इसे किसके साथ बुलाया जा रहा है, उदाहरण के लिए (पहला मामला) सजाने के लिए फ़ंक्शन या पैरामीटर (दूसरा मामला, जिसमें इसे आगे डेकोरेटर को वापस करने की आवश्यकता है)।
Turion

types.BuiltinFunctionTypeयह भी ("सामान्य") निर्मित तरीकों का प्रकार है , जिसे आप संभवतः अनुमति नहीं देना चाहते हैं, यदि आप callableमार्ग नहीं जा रहे हैं ।
user2357112

92

पायथन 2.1 के बाद से आप मॉड्यूल isfunctionसे आयात कर सकते हैं inspect

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

3
अच्छा है, लेकिन यह की तरह निर्मित कार्यों के लिए झूठी वापस जाने के लिए लगता है openऔर hasattr
ज़ेके

12
@ ज़ेक इनबिल्ट उसके लिए है।
पाओलो

13
inspect.isfunctionडॉकस्ट्रिंग देखें : "ऑब्जेक्ट उपयोगकर्ता द्वारा परिभाषित फ़ंक्शन होने पर वापस लौटें।"
मार्क मिकोफ़्स्की

4
ध्यान दें कि 'इस्फ़ंक्शन' फंक्शनलूलपार्टिकल फ़ंक्शंस को नहीं पहचानता है।
इस्माईल

74

स्वीकृत उत्तर उस समय दिया गया था जब इसे सही माना गया था। जैसा कि यह पता चला है, इसका कोई विकल्प नहीं है callable(), जो कि पायथन 3.2 में है: विशेष रूप से, परीक्षण की गई वस्तु 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(), यदि उपलब्ध हो, श्रेष्ठ है।
मेस्टेरलियन

39

निम्नलिखित को एक बूलियन वापस करना चाहिए:

callable(x)

1
यही कारण है कि हल करती है उसकी समस्या है, लेकिन वह अभी भी एक रहस्य बनाया: अगर एक्स मॉड्यूल में वर्ग 'समारोह' का है निर्मित है, और मदद (एक्स .__ class__) का वर्णन करता है "वर्ग समारोह", क्यों "समारोह" जाहिरा तौर पर "परिभाषित नहीं" है?
केन

1
"फ़ंक्शन" एक कीवर्ड या एक अंतर्निहित प्रकार नहीं है। कार्यों के प्रकार को "प्रकार" मॉड्यूल में, "type.FunctionType" के रूप में परिभाषित किया गया है
क्रिस बी।

25

पायथन के 2to3 टूल ( http://docs.python.org/dev/library/2to3.html ) सुझाव देते हैं:

import collections
isinstance(obj, collections.Callable)

ऐसा लगता है कि यह hasattr(x, '__call__')विधि के बजाय http://bugs.python.org/issue7006 के कारण चुना गया था ।


1
यह बग रिपोर्ट में callable()py3.3 को वापस लाने के बारे में भी बताया गया है : bugs.python.org/issue10518#msg122309
luckydonald

19

callable(x) सत्य वापस आ जाएगा यदि पारित किया गया ऑब्जेक्ट पायथन में बुलाया जा सकता है, लेकिन फ़ंक्शन पायथन 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
यह जानने के लिए अपवादों का उपयोग करने के साथ एक बड़ी समस्या है कि क्या यह कॉल करने योग्य था या नहीं; क्या यह अगर है प्रतिदेय, लेकिन बुला यह एक अपवाद आप देख रहे हैं को जन्म देती है? आप दोनों चुपचाप एक त्रुटि और गलतफहमी की अनदेखी करेंगे कि क्या यह कॉल करने योग्य था। जब आप ईएएफपी का उपयोग कर रहे हैं तो आप वास्तव में कोशिश में बहुत अधिक डालने से बचना चाहते हैं, लेकिन इस उपयोग के मामले में ऐसा करने का कोई तरीका नहीं है।
बेन

15

यदि आप हर उस चीज़ का पता लगाना चाहते हैं जो वाक्य-रचना की तरह दिखती है: एक फंक्शन, मेथड, बिल्ट-इन फन / मैथ, लैम्ब्डा ... लेकिन कॉल करने योग्य ऑब्जेक्ट्स ( __call__विधि द्वारा परिभाषित ऑब्जेक्ट्स ) को बाहर करें, तो यह एक कोशिश करें:

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

मैंने इसकी तुलना मॉड्यूल is*()में चेक के कोड के साथ की है inspectऔर ऊपर की अभिव्यक्ति बहुत अधिक पूर्ण है, खासकर यदि आपका लक्ष्य किसी भी फ़ंक्शन को फ़िल्टर कर रहा है या किसी ऑब्जेक्ट के नियमित गुणों का पता लगा रहा है।


मुझे typesमॉड्यूल की ओर इशारा करने के लिए धन्यवाद । मैं एक make_stemmer()कारखाने का परीक्षण कर रहा था जो कभी-कभी एक फ़ंक्शन और कभी-कभी एक कॉल करने योग्य Stemmerउदाहरण लौटाएगा , और मुझे अंतर का पता लगाने की आवश्यकता थी।
hobs


6

आप सीखा है तो C++, आप से परिचित होना चाहिए function objectया functor, किसी भी वस्तु जो कर सकते हैं इसका मतलब हैbe called as if it is a function

C ++ में, an ordinary functionएक फ़ंक्शन ऑब्जेक्ट है, और इसलिए एक फ़ंक्शन पॉइंटर है; अधिक सामान्यतः, एक वर्ग की एक वस्तु है जो परिभाषित करता है operator()। सी ++ 11 और अधिक से अधिक में, the lambda expressionहै functorभी।

समानता, पायथन में, वे functorsसभी हैं callableAn 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]
"""

फ़नकार के प्रकार (type.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

6

स्वीकार किए गए उत्तर के रूप में, जॉन फेमिनाला ने कहा कि:

बतख-टाइप की गई वस्तुओं के गुणों की जांच करने का उचित तरीका यह है कि वे उनसे पूछें कि क्या वे शांत हैं, यह देखने के लिए नहीं कि क्या वे बतख के आकार के कंटेनर में फिट होते हैं। "सीधे तुलना करें" दृष्टिकोण कई कार्यों के लिए गलत जवाब देगा, जैसे कि बिलिंस।

हालांकि, कार्यों को कड़ाई से अलग करने के लिए दो काम हैं, मैं एक विस्तृत तुलनीय तालिका आकर्षित करता हूं:

8.9। प्रकार - गतिशील प्रकार का निर्माण और निर्मित प्रकारों के नाम - पायथन 3.7.0 प्रलेखन

30.13। निरीक्षण - जीवित वस्तुओं का निरीक्षण करें - अजगर 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


5

एक फ़ंक्शन एक __call__विधि के साथ सिर्फ एक वर्ग है , इसलिए आप कर सकते हैं

hasattr(obj, '__call__')

उदाहरण के लिए:

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

>>> x = 2
>>> hasattr(x, '__call__')
False

यह करने का "सबसे अच्छा" तरीका है, लेकिन इसके आधार पर आपको यह जानने की आवश्यकता है कि क्या यह कॉल करने योग्य या नोट है, तो आप इसे केवल एक कोशिश / निष्पादित ब्लॉक में डाल सकते हैं:

try:
    x()
except TypeError:
    print "was not callable"

यह तर्कपूर्ण है कि अगर कोशिश करना / छोड़ना अधिक पायथन के अलावा है if hasattr(x, '__call__'): x().. तो मैं कहूंगा कि hasattrआप अधिक सटीक हैं, क्योंकि आप गलत प्रकार से गलत टाइप टाइप को पकड़ नहीं पाएंगे , उदाहरण के लिए:

>>> def x():
...     raise TypeError
... 
>>> hasattr(x, '__call__')
True # Correct
>>> try:
...     x()
... except TypeError:
...     print "x was not callable"
... 
x was not callable # Wrong!

केवल अप्रत्याशित व्यवहार से बचाने के लिए अपवाद हैंडलिंग का उपयोग करें, तर्क प्रवाह के लिए कभी नहीं - यह निश्चित रूप से पायथन नहीं है।
gotgenes

खैर, hasattr मूल रूप से एक कोशिश / ब्लॉक को छोड़कर (सी में) के अलावा एक getattr करता है। blog.jancewicz.net/2007/10/reflection-hasattr.html
dbr

@dbr: लेकिन हयात और अधिक सौंदर्यवादी है।
निखिल चेलियाह

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 के सभी संस्करण पर काम करना चाहिए!
सौरव कुमार

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
अपने जवाब से सहमत हों, जॉन फेमिनाला का जवाब hasattr(obj, '__call__')अस्पष्ट है।
गोइंगमवाय सेप

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

यदि आपको अन्य प्रकारों की जांच करने की आवश्यकता है, तो निरीक्षण पर एक नज़र डालें - जीवित वस्तुओं का निरीक्षण करें


2

एक सटीक समारोह परीक्षक

कॉल करने योग्य एक बहुत अच्छा समाधान है। हालाँकि, मैं जॉन फेमिनाला के विपरीत व्यवहार करना चाहता था। इसके बजाय इस तरह का कहना है:

बतख-टाइप की गई वस्तुओं के गुणों की जांच करने का उचित तरीका यह है कि वे उनसे पूछें कि क्या वे शांत हैं, यह देखने के लिए नहीं कि क्या वे बतख के आकार के कंटेनर में फिट होते हैं। "सीधे तुलना करें" दृष्टिकोण कई कार्यों के लिए गलत जवाब देगा, जैसे कि बिलिंस।

हम इसका इलाज इस तरह करेंगे:

यह जांचने का उचित तरीका है कि कोई चीज बतख है या नहीं, यह देखने के लिए कि क्या वह नष्ट हो सकती है, बल्कि यह देखने के लिए कि क्या यह वास्तव में कई फिल्टर के माध्यम से बतख है, सिर्फ जांच करने के बजाय अगर यह सतह से बतख की तरह लगता है।

हम इसे कैसे लागू करेंगे

'प्रकार' मॉड्यूल में फ़ंक्शन का पता लगाने के लिए बहुत सारी कक्षाएं हैं, सबसे उपयोगी प्रकार हैं। जंक्शन टाइप , लेकिन एक विधि प्रकार, एक प्रकार में निर्मित और एक टाइप जैसे कई अन्य भी हैं। हम एक फंक्शनल होने के नाते एक 'फंक्शनल टूलपार्टियल' ऑब्जेक्ट पर भी विचार करेंगे।

यदि हम यह जाँचते हैं कि यह एक सरल तरीका है, तो इन सभी प्रकारों पर आइंस्टीन की स्थिति का उपयोग करके। पहले, मैं एक बेस क्लास बनाना चाहता था जो उपरोक्त सभी में से विरासत में मिली हो, लेकिन मैं ऐसा करने में असमर्थ हूं, क्योंकि पायथन हमें उपरोक्त कुछ वर्गों से विरासत में प्राप्त करने की अनुमति नहीं देता है।

यहां बताया गया है कि कौन सी कक्षाएं किन कार्यों को वर्गीकृत कर सकती हैं:

राजहट से कार्य सारणी- ht Kinght द्वारा ऊपर फ़ंक्शन तालिका- ht

कोड जो यह करता है

अब, यह वह कोड है जो ऊपर वर्णित सभी कार्यों को करता है।

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 (आंशिक) है, क्योंकि यह एक वर्ग है, एक फ़ंक्शन नहीं है, और यह बिल्कुल फ़ंक्शन है, न कि कक्षाएं। यहां आपके लिए एक पूर्वावलोकन है जिसमें से कोड को आज़माया जा सकता है।

निष्कर्ष

कॉल करने योग्य (obj) यह जांचने का पसंदीदा तरीका है कि क्या वस्तु एक फ़ंक्शन है अगर आप निरपेक्षता पर बत्तख टाइप करके जाना चाहते हैं

हमारा रिवाज is_function (obj) है , हो सकता है कि कुछ संपादन के साथ यह जांचने की पसंदीदा विधि हो कि क्या कोई वस्तु एक फ़ंक्शन है यदि आप किसी फ़ंक्शन के रूप में कॉल करने योग्य वर्ग का उदाहरण नहीं देते हैं, लेकिन केवल फ़ंक्शन अंतर्निहित , या लंबो के साथ परिभाषित करते हैं , def , या आंशिक

और मुझे लगता है कि यह सब लपेटता है। आपका दिन शुभ हो!


1

Python3 में मैं के साथ आया था type (f) == type (lambda x:x)जो पैदावार Trueकरता है, तो fएक समारोह है और Falseअगर यह नहीं है। लेकिन मुझे लगता है कि मैं पसंद isinstance (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

यदि कोड कॉल पर जाता है यदि मूल्य कॉल करने योग्य है, तो कॉल और कैच करें 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

अब केवल पायथन 3 के लिए काम करता है :) इसके अलावा सवाल के मूल इरादे के आधार पर, यह अधूरा होगा: क्या बिलिन openको एक फ़ंक्शन माना जाना चाहिए ? पायथन में str(type(open))देता <class 'builtin_function_or_method'>है 3.
pawamoy
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.