कैसे जांचें कि पायथन में एक विधि मौजूद है या नहीं?


83

फ़ंक्शन में __getattr__(), यदि एक संदर्भित चर नहीं मिला है, तो यह एक त्रुटि देता है। मैं यह देखने के लिए कैसे जांच सकता हूं कि क्या एक चर या विधि किसी वस्तु के हिस्से के रूप में मौजूद है?

import string
import logging

class Dynamo:
 def __init__(self,x):
  print "In Init def"
  self.x=x
 def __repr__(self):
  print self.x
 def __str__(self):
  print self.x
 def __int__(self):
  print "In Init def"
 def __getattr__(self, key):
    print "In getattr"
    if key == 'color':
        return 'PapayaWhip'
    else:
        raise AttributeError


dyn = Dynamo('1')
print dyn.color
dyn.color = 'LemonChiffon'
print dyn.color
dyn.__int__()
dyn.mymethod() //How to check whether this exist or not

जवाबों:


91

dir()समारोह के बारे में पहले कैसे getattr()?

>>> "mymethod" in dir(dyn)
True

7
यह जाँच नहीं करता है कि यह एक विधि है या एक चर
hek2mgl

1
dir का उपयोग करना महान नहीं है - यह पुष्टि नहीं करता है कि नाम उदाहरण के लिए एक विधि है
टोनी सफ़ोकल 66

109

अनुमति माँगने की अपेक्षा क्षमा माँगना अधिक आसान है।

यह देखने के लिए जांच न करें कि क्या कोई विधि मौजूद है। "जाँच" पर कोड की एक भी लाइन बर्बाद न करें

try:
    dyn.mymethod() # How to check whether this exists or not
    # Method exists and was used.  
except AttributeError:
    # Method does not exist; What now?

57
लेकिन शायद वह वास्तव में इसे कॉल नहीं करना चाहता है, बस यह जांचने के लिए कि क्या वह तरीका है (जैसा कि मेरे मामले में है) ...
फ्लेवियस

49
ध्यान दें कि यह विफल हो जाएगा यदि dyn.mymethod()एक AttributeErrorही उठाता है।
डीके

10
जैसा कि @DK कहता है, यह किसी भी एट्रीब्यूट को जाल में फंसा देगा, जिसके लिए जाँच की जा रही विधि द्वारा उठाया जा सकता है, जो अवांछनीय हो सकता है (यह उल्लेख नहीं करने के लिए कि यह उस मामले में विधि की अनुपस्थिति का गलत अनुमान लगाएगा)।
श्रीवत्सआर

3
सिद्धांत रूप में अच्छा है, और पायथन में अन्य भाषाओं के विपरीत "नियंत्रण प्रवाह के रूप में" संस्कृति है। हालाँकि, यदि आप संतरी / रेवेन, या नए अवशेष जैसे अपवाद लॉगिंग टूल का उपयोग कर रहे हैं, तो ऐसे अपवादों को व्यक्तिगत रूप से फ़िल्टर करना होगा (यदि यह संभव है) या शोर उत्पन्न करें। मैं यह जांचना पसंद करूंगा कि क्या विधि कॉल करने के बजाय मौजूद है।
रिचवेल

2
यह कई सारे स्तरों पर गलत है। मेथड अपने आप में एट्रीब्यूट को बढ़ा सकता है और इसका पता लगाया जाएगा क्योंकि यह विधि मौजूद नहीं है! यह अपवादों को तोड़ने के लिए डिबगर समर्थन को भी बर्बाद कर देता है। मुझे यकीन है कि यह प्रदर्शन को प्रभावित करता है अगर बात लूप में होती है। अंतिम लेकिन सूची नहीं मैं पद्धति को निष्पादित नहीं करना चाहूंगा, अगर यह मौजूद है तो इसे मान्य करें। आपको इस उत्तर को हटाने पर विचार करना चाहिए या कम से कम इन सभी चेतावनियों को रखना चाहिए ताकि भोले लोग गुमराह न हों।
शीतल शाह

107

जांचें कि क्या कक्षा में ऐसी विधि है?

hasattr(Dynamo, key) and callable(getattr(Dynamo, key))

या

hasattr(Dynamo, 'mymethod') and callable(getattr(Dynamo, 'mymethod'))

आप के self.__class__बजाय का उपयोग कर सकते हैंDynamo


23
Noneकॉल करने योग्य नहीं है, इसलिए आप बस कर सकते हैं callable(getattr(Dynamo, 'mymethod', None))। मैंने इस उत्तर का उपयोग किया क्योंकि मेरा सुपर ()। मायमेथोड () फेंक सकता थाAttributeError
3

@sbutler दिलचस्प है कि काम करता है। PyCharm के अनुसार getattr के लिए हस्ताक्षर से def getattr(object, name, default=None):मुझे संदेह है कि यह सटीक नहीं है क्योंकि अगर यह होता तो मैं तीसरे पैरामीटर के रूप में किसी को भी पारित करने की अपेक्षा नहीं करता क्योंकि फ़ंक्शन का व्यवहार नहीं बदलता।
bszom

@bszom: एक अजगर शेल में, help(getattr)"जब एक डिफ़ॉल्ट तर्क दिया जाता है, तो यह तब वापस आ जाता है जब विशेषता मौजूद नहीं होती; इसके बिना, उस मामले में एक अपवाद उठाया जाता है।" - (और वास्तव में आप जांच कर सकते हैं कि गेटअटर एक अपवाद बढ़ाता है यदि विशेषता गायब है) तो स्पष्ट रूप से, जो भी PyCharm है, वह गलत है।
श्रीवत्सआर

@ श्रीवत्सआर मेरे संदेह की पुष्टि करने के लिए धन्यवाद। PyCharm एक IDE है।
bszom

4
सरल संस्करण: आप अगर वर्तमान वर्ग उदाहरण एक विशेषता है की जांच करना चाहते हैं और यह प्रतिदेय है, तो बस इस कार्य करें: if hasattr(self, "work") and callable(self.work)। यह जाँचता है कि यदि उदाहरण में कार्य विशेषता है (या तो एक चर या फ़ंक्शन हो सकता है), और फिर जाँचता है कि क्या यह कॉल करने योग्य है (इसका अर्थ है कि यह एक फ़ंक्शन है)।
मिच मैकमेबर्स

14

आप 'निरीक्षण' मॉड्यूल का उपयोग करके देख सकते हैं:

import inspect
def is_method(obj, name):
    return hasattr(obj, name) and inspect.ismethod(getattr(obj, name))

is_method(dyn, 'mymethod')

12

मैं नीचे उपयोगिता समारोह का उपयोग करें। यह लैम्ब्डा, क्लास मेथड्स के साथ-साथ इंस्टेंस मेथड्स पर काम करता है।

उपयोगिता विधि

def has_method(o, name):
    return callable(getattr(o, name, None))

उदाहरण उपयोग

चलो टेस्ट क्लास को परिभाषित करते हैं

class MyTest:
  b = 'hello'
  f = lambda x: x

  @classmethod
  def fs():
    pass
  def fi(self):
    pass

अब आप कोशिश कर सकते हैं,

>>> a = MyTest()                                                    
>>> has_method(a, 'b')                                         
False                                                          
>>> has_method(a, 'f')                                         
True                                                           
>>> has_method(a, 'fs')                                        
True                                                           
>>> has_method(a, 'fi')                                        
True                                                           
>>> has_method(a, 'not_exist')                                       
False                                                          

2
यह उत्तर अन्य उत्तरों की तुलना में अधिक उपयुक्त (मेरी राय में कम से कम) है क्योंकि यह एक सामान्य दृष्टिकोण ( tryकथन का उपयोग करते हुए) का उपयोग नहीं करता है और जब भी सदस्य वास्तविक कार्य करता है तब यह जांच करता है। महान शेयर!
ymz

4

कैसे इसे देखने के बारे में dyn.__dict__?

try:
    method = dyn.__dict__['mymethod']
except KeyError:
    print "mymethod not in dyn"

अधिवेशन द्वारा अंडरबार-उपसर्ग विधियों का अर्थ है 'निजी'।
xtofl

डबल-अंडरबार उपसर्ग प्लस डबल-अंडरबार प्रत्यय का अर्थ है 'यह आमतौर पर पायथन इंटरप्रेटर द्वारा ही उपयोग किया जाता है' और आमतौर पर सबसे आम उपयोग मामलों के लिए उपयोगकर्ता के कार्यक्रम से समान प्रभाव प्राप्त करने का कोई तरीका है (इस मामले में यह होगा) एक विशेषता के लिए डॉट नोटेशन का उपयोग करना), लेकिन अगर इसका उपयोग मामला वास्तव में इसके लिए कहता है तो इसे न तो निषिद्ध है और न ही इसका उपयोग करना गलत है।
डेस्ट्रैंगिस

इसकी मनाही नहीं है। गलत व्यक्तिपरक है: यह इस बात पर निर्भर करता है कि आप उन प्रोग्रामर्स को कितना भ्रमित करना चाहते हैं जो सम्मेलनों का पालन करते हैं: इसका उपयोग तब तक न करें जब तक आपके पास कोई विकल्प न हो।
xtofl

3

शायद इस तरह, सभी विधि को कॉल करने योग्य है

app = App(root) # some object call app 
att = dir(app) #get attr of the object att  #['doc', 'init', 'module', 'button', 'hi_there', 'say_hi']

for i in att: 
    if callable(getattr(app, i)): 
        print 'callable:', i 
    else: 
        print 'not callable:', i

1

यदि आपकी विधि किसी कक्षा के बाहर है और आप इसे चलाना नहीं चाहते हैं और अपवाद नहीं है तो यह मौजूद नहीं है:

'mymethod' in globals()


1
>>> myadd (x, y) को लौटाएं: ग्लोबल्स में वापसी x + y >>> 'myadd' () True
gerowam

-1

मुझे लगता है कि आपको inspectपैकेज देखना चाहिए । यह आपको कुछ चीजों को 'रैप' करने की अनुमति देता है। जब आप dirविधि का उपयोग करते हैं तो यह विधियों, विरासत में मिली विधियों और अन्य सभी विशेषताओं से टकराव को संभव बनाता है, जैसे:

class One(object):

    def f_one(self):
        return 'class one'

class Two(One):

    def f_two(self):
        return 'class two'

if __name__ == '__main__':
    print dir(Two)

आपके द्वारा प्राप्त की गई सरणी dir(Two)में दोनों f_oneऔर f_twoबहुत सारे सामान शामिल हैं। साथ inspectआप यह कर सकते हैं:

class One(object):

    def f_one(self):
        return 'class one'

class Two(One):

    def f_two(self):
        return 'class two'

if __name__ == '__main__':
    import inspect

    def testForFunc(func_name):
        ## Only list attributes that are methods
        for name, _ in inspect.getmembers(Two, inspect.ismethod):
            if name == func_name:
                return True
        return False

    print testForFunc('f_two')

यह उदाहरण अभी भी दो वर्गों में दोनों तरीकों को सूचीबद्ध करता है, लेकिन यदि आप निरीक्षण को केवल एक विशिष्ट वर्ग में कार्य करने के लिए सीमित करना चाहते हैं तो इसके लिए थोड़ा और काम करने की आवश्यकता है, लेकिन यह बिल्कुल संभव है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.