পাইথন ভেরিয়েবল একটি ফাংশন কিনা তা আমি কীভাবে সনাক্ত করব?


686

আমার একটি পরিবর্তনশীল রয়েছে 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
আমি কিছু খুঁজছেন দ্বারা আপনি সমস্যা কাজ করছে উত্তর সংখ্যা দ্বারা বিষণ্ণ করছি কল অ্যাট্রিবিউট বা callable ফাংশন ... একটি পরিষ্কার উপায় হিসেবে @ryan দ্বারা প্রস্তাবিত প্রকার (ক) == types.functionType সম্পর্কে
Aster

44
@ এসটিআর হাঁস-টাইপযুক্ত বস্তুর বৈশিষ্ট্য যাচাই করার সঠিক উপায় হ'ল তারা জিজ্ঞাসাবাদ করছে যে তারা হাঁসফাঁস করছে কি না, তারা হাঁসের আকারের পাত্রে ফিট করে কি না তা দেখুন। "সরাসরি এটি তুলনা করুন" পদ্ধতিটি অনেকগুলি কার্যকারিতা যেমন বিল্টিনের মতো ভুল উত্তর দেয়।
জন Feminella

3
@ জনফেমিনেল্লা যখন আমি নীতিগতভাবে আপনার সাথে একমত হই। ওপি এটি কলযোগ্য কিনা তা জিজ্ঞাসা করেনি, এটি যদি কোনও ফাংশন হয়। সম্ভবত এটি যুক্তিযুক্ত হতে পারে যে তার জন্য একটি পার্থক্য প্রয়োজন, উদাহরণস্বরূপ, ফাংশন এবং শ্রেণি?
ম্যাককে

3
আমার উদ্দেশ্যগুলির জন্য, আমি এখানে এসেছি কারণ আমি insepct.getsourceবিভিন্ন ধরণের অবজেক্টগুলিতে ব্যবহার করতে চেয়েছিলাম , এবং এটি বস্তুটি কলযোগ্য কিনা তা নয় তবে এটি 'ফাংশন' দেবে এমন কিছু কিনা তা গুরুত্বপূর্ণ type(obj)। যেহেতু গুগল আমাকে এখানে নিয়েছে, তাই আমি বলব যে AsTeR এর মন্তব্যটি সবচেয়ে দরকারী উত্তর ছিল (আমার জন্য)। লোকেরা আবিষ্কার করতে __call__বা আবিষ্কার করার জন্য ইন্টারনেটে প্রচুর অন্যান্য জায়গা রয়েছে callable
tsbertalan

4
@ এসটিআর এটি টাইপস.ফুনেশন টাইপ, একটি মূলধন এফ সহ
বেন

উত্তর:


891

এটি পাইথন ২.x বা পাইথন ৩.২+ এর জন্য হলে আপনিও এটি ব্যবহার করতে পারেন callable()। এটি হ্রাস করা হত, তবে এখন অবচয়হীন, তাই আপনি এটি আবার ব্যবহার করতে পারেন। আপনি এখানে আলোচনাটি পড়তে পারেন: http://bugs.python.org/issue10518 । আপনি এটি দিয়ে এটি করতে পারেন:

callable(obj)

এটি যদি পাইথন ৩.x এর জন্য হয় তবে ৩.২ এর আগে, বস্তুর কোনও __call__বৈশিষ্ট্য আছে কিনা তা পরীক্ষা করুন । আপনি এটি দিয়ে এটি করতে পারেন:

hasattr(obj, '__call__')

শীর্ষ-প্রস্তাবিত types.FunctionTypesপদ্ধতির সঠিক নয় কারণ এটি বিল্টিনের মতো, সম্ভবত আপনি এটি পাস করতে চান এমন অনেকগুলি ক্ষেত্রে কভার করতে ব্যর্থ হয়:

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

>>> callable(open)
True

হাঁসের ধরণের জিনিসগুলির বৈশিষ্ট্য যাচাই করার সঠিক উপায় হ'ল তারা কোঁকছেন কিনা তা জিজ্ঞাসা করা, তারা হাঁসের আকারের পাত্রে ফিট করে কিনা তা দেখার জন্য নয়। types.FunctionTypeকোনও ফাংশন কী তা সম্পর্কে আপনার নির্দিষ্ট ধারণা না থাকলে ব্যবহার করবেন না ।


73
এটি কোনও ফাংশন কিনা তাও আপনাকে জানায় না - যদি এটি বলা যেতে পারে।
ক্রিস বি।

23
পার্থক্য বিবেচনা করে বা না তা প্রয়োগের উপর নির্ভর করে; আমি সন্দেহ করি যে আপনি ঠিক বলেছেন যে এটি মূল প্রশ্নের জন্য নয়, তবে এটি নিশ্চিত নয়।
ক্রিস বি।

5
ক্লাসগুলির সাথে এটির সাথে একটি কল ফাংশন থাকতে পারে। সুতরাং এটি অবশ্যই আলাদা করার জন্য একটি ভাল পদ্ধতি নয়। রায়ান এর পদ্ধতি আরও ভাল।
ব্রায়ান ব্রুজম্যান 20

43
"হাঁসের টাইপিং" ধারণাটি এটিকে আরও ভাল উত্তর দেয়, যেমন "এটি যদি কোনও ফাংশন যতক্ষণ তার মতো আচরণ করে তবে কী ব্যাপার?"
jcomeau_ictx

8
এমন ব্যবহারের ক্ষেত্রে রয়েছে যেখানে কলযোগ্য এবং একটি ফাংশনের মধ্যে পার্থক্য অত্যন্ত গুরুত্বপূর্ণ, উদাহরণস্বরূপ ডেকোরেটার লেখার সময় (রায়ের উত্তর সম্পর্কে আমার মন্তব্য দেখুন)।
টিউরিওন

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। তবে কোনও বস্তু একটি ফাংশন কিনা তা অনুমান করার চেষ্টা করা - বা এটি কোনও কলযোগ্য বস্তু হলেও - সাধারণত একটি ভুল usually ওপি থেকে আরও তথ্য ছাড়া এটা অবশ্যই হাত থেকে খারিজ করতে কঠিন, কিন্তু এখনও ...
bobince

47
এটি প্রকৃতপক্ষে বিল্টিন ফাংশনগুলির জন্য যেমন 'খোলা' যেমন মিথ্যা ফিরিয়ে দেবে। সুতরাং সুনির্দিষ্ট হতে আপনাকে আইসনস্ট্যান্স ব্যবহার করতে হবে (এফ, (প্রকার। ফাংশনটাইপ, প্রকারসমূহ। বিল্টিন ফাংশনটাইপ))। এবং অবশ্যই যদি আপনি কঠোরভাবে কেবল ফাংশন চান, কলযোগ্য বা পদ্ধতি নয়।
লুকাসজ করজিবস্কি

5
@ AsukaszKorzybski এবং আরও স্বর্গরাজ্য হওয়ার জন্য ... আপনারও ফান্টাকুলস.পার্পেশিয়াল: isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))বা এই f.funcজাতীয় ক্ষেত্রে চেক করা উচিত ।
ইস্তানী

3
@ ববিন্স, কীভাবে এই ইউসকেস সম্পর্কে: আমি একটি ডেকরেটর লিখতে চাই @fooযা আমি উভয় হিসাবে @fooএবং হিসাবে ব্যবহার করতে পারি @foo(some_parameter)। তারপরে এটি যা বলা হচ্ছে তা যাচাই করা দরকার, উদাহরণস্বরূপ (প্রথম কেস) সাজানোর ফাংশন বা প্যারামিটার (দ্বিতীয় কেস, এটিতে আরও একটি সাজসজ্জা ফেরানোর দরকার আছে)।
টিউরিওন

types.BuiltinFunctionTypeআপনি যদি রুটে না যান তবে ("সাধারণ") অন্তর্নির্মিত পদ্ধতিগুলিরও প্রকার যা আপনি সম্ভবত মঞ্জুরি দিতে চান না callable
ব্যবহারকারী 2357112

92

পাইথন ২.১ যেহেতু আপনি মডিউলটি isfunctionথেকে আমদানি করতে পারেন inspect

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

3
নিস, কিন্তু এটা মত builtin কাজকর্মের জন্য মিথ্যা ফিরে বলে মনে হয় openএবং hasattr
Zecc

12
@ Zecc isbuiltin এর জন্য রয়েছে।
পাওলো

13
inspect.isfunctionডক্টরসিংটি দেখুন : "যদি বস্তুটি ব্যবহারকারী-সংজ্ঞায়িত ফাংশন হয় তবে সত্যটি প্রত্যাবর্তন করুন।"
মার্ক মিকোফস্কি

4
নোট করুন যে 'isfunction' functool.partial ফাংশনগুলি চিনতে পারে না।
ইসমাইল

74

গ্রহণযোগ্য উত্তরটি যখন সঠিকভাবে বলে মনে করা হয়েছিল তখন was এটি সক্রিয় আউট হিসাবে, আছে কোন বিকল্প জন্য 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(), যদি তা পাওয়া যায় তবে এটি সর্বোত্তম।
MestreLion

39

নীচেরগুলিতে একটি বুলিয়ান ফেরত দেওয়া উচিত:

callable(x)

1
যে সমাধান তার সমস্যা, কিন্তু তিনি এখনও একটি রহস্য তৈরি করেছি: যদি এক্স মডিউলে বর্গ 'ফাংশনটি' হল builtin , এবং সাহায্যের (এক্স .__ class__) বর্ণনা করে "শ্রেণী ফাংশন", কেন "ফাংশন" দৃশ্যত "সংজ্ঞায়িত করা হয়"?
কেন

1
"ফাংশন" কোনও কীওয়ার্ড বা অন্তর্নির্মিত প্রকার নয়। ফাংশনগুলির ধরণটি "প্রকার" মডিউলে "টাইপস.ফাংশনটাইপ" হিসাবে সংজ্ঞায়িত করা হয়েছে
ক্রিস বি।

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 এর জন্য ফিরিয়ে আনার বিষয়ে বাগের প্রতিবেদনেও উল্লেখ করা হয়েছে : বাগসপিটিথন.আর
বিসু

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

@ এসম্যুরার - আপনি যদি এটি না ডাকছেন তবে এটির কোনও ক্রিয়াকলাপ কিনা তা আপনার আর কেন জানতে হবে?
অবশেষে

1
@ তাত্পর্যপূর্ণ: ডিবাগিংয়ের জন্য আমি নিয়মিতভাবে কোনও অবজেক্টে সমস্ত ভেরিয়েবল মুদ্রণ করতে চাই, পদ্ধতিগুলি সাধারণত আমার কাজে লাগে না তাই আমি এগুলি সম্পাদন করতে চাই না। শেষ পর্যন্ত আমি কেবল প্রতিটি অ-কলযোগ্য সম্পত্তি সম্পর্কিত মানগুলির সাথে তালিকায়
রাখি

2
আপনি যেহেতু এটি কল করছেন না তার অর্থ এই নয় যে এটি কল করা হচ্ছে না। সম্ভবত আপনি প্রেরণ করছেন।
asmeurer

4
এটি কলযোগ্য কিনা তা জানার জন্য ব্যতিক্রমগুলি ব্যবহার করার ক্ষেত্রে একটি বড় সমস্যা রয়েছে; কি এটা যদি হয় callable কিন্তু কলিং এটি একটি ব্যতিক্রম আপনি যা খুঁজছেন উত্থাপন? আপনি উভয়ই চুপচাপ একটি ত্রুটি উপেক্ষা করবেন এবং এটি কলযোগ্য কিনা তা ভুল নির্ণয় করবেন। আপনি যখন ইএএফপি ব্যবহার করছেন আপনি সত্যিকার অর্থে খুব বেশি চেষ্টা করা এড়াতে চান তবে এই ব্যবহারের ক্ষেত্রে এটি করার কোনও উপায় নেই।
বেন

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

সি ++ এ, 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]

বিচারক ওয়েদার ফান্টার কলযোগ্য ble আপনি দেখতে পাচ্ছেন যে এগুলি সকলেই কলযোগ্য।

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

6

গৃহীত উত্তর হিসাবে, জন ফেমেনেলা বলেছিলেন:

হাঁসের ধরণের জিনিসগুলির বৈশিষ্ট্য যাচাই করার সঠিক উপায় হ'ল তারা কোঁকছেন কিনা তা জিজ্ঞাসা করা, তারা হাঁসের আকারের পাত্রে ফিট করে কিনা তা দেখার জন্য নয়। "সরাসরি এটি তুলনা করুন" পদ্ধতিটি অনেকগুলি কার্যকারিতা যেমন বিল্টিনের মতো ভুল উত্তর দেয়।

তবুও, কার্যগুলি আলাদাভাবে আলাদা করার জন্য দুটি লিব রয়েছে, আমি একটি সম্পূর্ণ তুলনামূলক টেবিল আঁকছি:

8.9। প্রকারভেদ - গতিশীল টাইপ তৈরি এবং অন্তর্নির্মিত প্রকারের নাম - পাইথন ৩.7.০ ডকুমেন্টেশন

30,13। পরিদর্শন করুন - লাইভ অবজেক্টগুলি পরিদর্শন করুন - পাইথন ৩.7.০ ডকুমেন্টেশন

#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!

শুধুমাত্র অপ্রত্যাশিত আচরণের বিরুদ্ধে রক্ষা করতে ব্যতিক্রম হ্যান্ডলিং ব্যবহার করুন, কখনও যুক্তি প্রবাহের জন্য নয় - এটি অবশ্যই পাইথোনিক নয়।
পেয়ে গেজেসনেস

ওয়েল, হ্যাশট্রা মূলত একটি চেষ্টা / ব্লক ব্যতীত গেটআটার করে (যদিও সি তে থাকে)। blog.jancewicz.net/2007/10/reflection-hasattr.html
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!

এটা সুন্দর! পাইথন 2.x এবং পাইথন 3.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__')অস্পষ্ট।
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

আপনার যদি অন্য ধরণের জন্য যাচাই করতে হয় তবে পরিদর্শন করুন - লাইভ অবজেক্টগুলি পরীক্ষা করুন


2

একটি সঠিক ফাংশন চেকার

কলযোগ্য একটি খুব ভাল সমাধান। যাইহোক, আমি জন ফেমেনিেলার বিপরীত আচরণ এটি করতে চেয়েছিলেন। এর পরিবর্তে এই কথার সাথে চিকিত্সা করার পরিবর্তে:

হাঁসের ধরণের জিনিসগুলির বৈশিষ্ট্য যাচাই করার সঠিক উপায় হ'ল তারা কোঁকছেন কিনা তা জিজ্ঞাসা করা, তারা হাঁসের আকারের পাত্রে ফিট করে কিনা তা দেখার জন্য নয়। "সরাসরি এটি তুলনা করুন" পদ্ধতিটি অনেকগুলি কার্যকারিতা যেমন বিল্টিনের মতো ভুল উত্তর দেয়।

আমরা এটির মতো আচরণ করব:

কিছু কিছু হাঁস কিনা তা যাচাই করার সঠিক উপায়টি এটি কোঁকড়ে উঠতে পারে কিনা তা নয়, বরং এটি দেখার জন্য যে এটি কোনও ফিল্টার দিয়ে সত্যই একটি হাঁস কিনা তা সন্ধান করার পরিবর্তে এটি কেবল পৃষ্ঠ থেকে হাঁসের মতো মনে হচ্ছে কিনা তা যাচাই করে।

আমরা কীভাবে এটি বাস্তবায়ন করব

' টাইপস ' মডিউলে ফাংশন সনাক্তকরণের জন্য প্রচুর ক্লাস রয়েছে, সর্বাধিক দরকারী হ'ল টাইপস. ফাংশনটাইপ , তবে আরও রয়েছে প্রচুর পরিমাণে, যেমন একটি মেথড টাইপ, বিল্ট ইন টাইপ এবং ল্যাম্বডা টাইপের মতো। আমরা একটি 'ফান্টাকুলস. পার্টিশিয়াল' অবজেক্টটিকে একটি ফাংশন হিসাবে বিবেচনা করব।

এটি যে ফাংশন কিনা তা আমরা যা সহজভাবে পরীক্ষা করি তা হ'ল এই সমস্ত ধরণের আইসনস্ট্যান্স শর্ত ব্যবহার করে। পূর্বে, আমি একটি বেস ক্লাস তৈরি করতে চেয়েছিলাম যা উপরের সমস্তটি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়েছে, তবে আমি এটি করতে পারছি না, কারণ পাইথন আমাদের উপরের কিছু শ্রেণীর কাছ থেকে উত্তরাধিকারী হওয়ার অনুমতি দেয় না।

কোন শ্রেণিগুলি কী কী ফাংশনগুলিকে শ্রেণিবদ্ধ করতে পারে তার একটি সারণী এখানে রয়েছে:

কিংহট- from থেকে ফাংশন সারণী 金 কিংহট- by দ্বারা ফাংশন টেবিলের উপরে 金

কোড যা এটি করে

এখন, এই কোডটি যা উপরে থেকে বর্ণিত সমস্ত কাজ করে।

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]

একটি মিথ্যাটি হ'ল_ফংশান (আংশিক), কারণ এটি একটি শ্রেণি, কোনও ফাংশন নয় এবং এটি হুবহু ফাংশন, ক্লাস নয়। কোডটি চেষ্টা করে দেখতে আপনার এখানে একটি পূর্বরূপ

উপসংহার

callable (obj) যদি একটি বস্তু একটি ফাংশন যদি আপনি যেতে চান চেক করতে পছন্দের পদ্ধতি হাঁস-টাইপিং উপর পরম

আমাদের কাস্টম is_function (জেজ) , হতে পারে কিছু সম্পাদনা সহ একটি বস্তু ফাংশন কিনা তা যাচাই করার জন্য পছন্দসই পদ্ধতি হ'ল আপনি যদি কোনও ফাংশন হিসাবে কলযোগ্য শ্রেণীর উদাহরণ গণনা করেন না তবে কেবল বিল্ট-ইন বা সংশ্লেষযুক্ত বা ল্যাম্বডা , ডিএফ দ্বারা সংজ্ঞায়িত ফাংশনগুলি অথবা আংশিক

এবং আমি মনে করি যে এটি সমস্ত আবৃত করে। আপনার দিনটি শুভ হোক!


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
cwanlenpoole

-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'>", তাই আমি এটি দেখতে পাচ্ছি না যে এটি আপনার জন্য কীভাবে কাজ করছে: /
পাওয়াময়

এখন কেবল পাইথন 3 এর জন্য কাজ করে :) এছাড়াও প্রশ্নের মূল অভিপ্রায় অনুসারে এটি অসম্পূর্ণ হবে: বিল্টইনকে openকোনও ফাংশন হিসাবে বিবেচনা করা উচিত ? পাইথন 3 এ str(type(open))দেয়<class 'builtin_function_or_method'>
পাওয়াময়
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.