2010-03-11 4 views
22
में कोई भी नहीं

मैं अपने आप को भी अक्सर एक सा निम्न कार्य लग रहा है:संक्षिप्त तरीके से() और उसका उपयोग यह अजगर

attr = getattr(obj, 'attr', None) 
if attr is not None: 
    attr() 
    # Do something, either attr(), or func(attr), or whatever 
else: 
    # Do something else 

वहाँ कि लेखन का एक और अधिक pythonic तरीका है? क्या यह बेहतर है? (प्रदर्शन में कम से कम नहीं, IMO।)

try: 
    obj.attr() # or whatever 
except AttributeError: 
    # Do something else 
+0

"कम से कम नहीं के प्रदर्शन में, IMO"। आपको शायद इसे मापना चाहिए। आप पाएंगे कि पायथन अपवाद बहुत तेज़ हैं। –

+1

यदि यह वास्तव में एक बाधा है (शायद नहीं), प्रदर्शन भी आम मामले पर निर्भर करता है - क्या विशेषता आमतौर पर मौजूद होती है, या क्या यह आमतौर पर मौजूद नहीं होती है? – orip

उत्तर

26

चूंकि आप attr पर कॉल कर रहे हैं, तो आप coul बस करना चाहूंगी:

def default_action(): 
    # do something else 

action = getattr(obj, 'attr', default_action) 

action() 
+0

मैंने कभी इस बारे में सोचा नहीं, लेकिन यह सुनिश्चित है कि मेरे कुछ उपयोग मामलों के लिए पूरी तरह से काम करता है! –

5

एक और अच्छा मुहावरा है:

if hasattr(obj, 'attr'): 
    ...something... 
else: 
    ...something else... 

दो विकल्प आपको पोस्ट मैं पहली बार एक पसंद करते हैं से। सदस्यों तक पहुंचने पर अपवाद फेंकने की धारणा सिर्फ उस चीज को नहीं लगती है जिसका उपयोग अपवादों के लिए किया जाना था।

+0

-1 चूंकि AttributeError "सदस्यों तक पहुंचने पर" उपयोग करने के लिए एक बहुत ही स्पष्ट अपवाद है। –

+2

यह एक तरह का खुला प्रश्न है। मुझे इस स्थिति में एक अच्छा अभ्यास के रूप में 'AttributeError' का उपयोग नहीं मिलता है, आप करते हैं। क्या इसका मतलब है कि आप सही हैं और मैं नहीं हूं? मुझे ऐसा नहीं लगता है कि – pajton

1

कोशिश/छोड़कर आमतौर पर अधिक पायथनिक माना जाता है। यदि ओबीजे के पास विशेषता है तो यह और भी अधिक कुशल है, क्योंकि यह परीक्षण को समाप्त करता है - अगर अपवाद नहीं फेंक दिया गया है तो ब्लॉक को ओवरहेड नहीं है। दूसरी ओर यदि ओबीजे में विशेषता नहीं है तो यह कम कुशल है क्योंकि इसमें अपवाद फेंकने और पकड़ने का ऊपरी भाग होगा।

+2

शायद यह पाइथोनिक है, लेकिन यह बदसूरत है और मेरा मानना ​​है कि अपवाद इस तरह के उद्देश्य के लिए नहीं हैं। पायथन में आप 'इंडेंटेशन एरर' भी पकड़ सकते हैं, क्या यह कुछ कोड को घेरने के लिए भी पाइथोनिक है जिसे आप निश्चित रूप से इंडेंट नहीं कर रहे हैं? – pajton

+0

ऐसा क्यों नहीं है? मान लीजिए कि आप एक प्लगइन मॉड्यूल आयात कर रहे हैं, और मॉड्यूल आयात करने में विफल रहता है। फेंक दिया अपवाद कहता है क्यों। यदि आपको ऐसा करने के लिए प्रेरित किया गया था, तो आप त्रुटि को पकड़ सकते हैं और उपयोगकर्ता को ठीक से इसे ठीक करने के बारे में बता सकते हैं ("फ़ाइल वाई के लाइन एक्स पर इंडेंट समस्या को साफ़ करें")। मैं इस तरह की लचीलापन की सराहना करता हूं। –

+0

और मैं आपको "कुछ कोड को घेरने" के लिए चुनौती देता हूं जो एक कोशिश ब्लॉक के साथ ठीक तरह से इंडेंट नहीं है .... आपको इससे अधिक अप्रत्यक्ष होना चाहिए क्योंकि पार्सर 'कोशिश करें' से पहले समस्या को पकड़ लेगा: संरचना पूरी हो गई है। –

6

try/except विकल्प के रूप में आप इसे कोड, गलती से एक AttributeError कि attr() बुला रहा है, पकड़ा जा करने के लिए कुछ में समस्याओं के कारण हो सकता है। विशेषता अनुपलब्ध, उपयोग होने के लिए आप try/except है, जो उचित और काफी अच्छी तरह से करता है, तो यह दुर्लभ है प्रदर्शन है के साथ कोड करने के लिए करना चाहते हैं:

try: 
    attr = obj.attr 
except AttributeError: 
    dosome(thingelse) 
else: 
    attr() 

इस जाएगा नहीं कारण "आकस्मिक पकड़ने" के रूप में ऊपर। किस दृष्टिकोण के लिए बेहतर है, मैं आम तौर पर अपवाद-पकड़ने वाले दृष्टिकोण - "ईएएफपी" के साथ जाता हूं, "अनुमति से क्षमा मांगना आसान है" (एक आदर्श वाक्य जिसे अक्सर एडमिरल ग्रेस हूपर, कोबोल और सीओडीएएसवाईएल के पीछे चालक बल) के लिए जिम्मेदार ठहराया जाता है, निश्चित रूप से लागू होता है पाइथन के लिए अच्छी तरह से ;-)।

0

आह, यह सटीक कोड पर निर्भर करता है। आपके दो टूल्स:

  • हैशर (ओबीजे, 'एटीआर') सही है अगर केवल और अगर obj.attr मौजूद है तो सही हो जाता है।
  • getattr (obj, 'attr', other_value) obj.attr रिटर्न यदि वह मौजूद है, और other_value
  • कोशिश एक = obj.attr/विफलता()/बाकी do_something को छोड़कर (क) जब प्रदर्शन पठनीयता धड़कता है।

अधिकतर सामान्य मामलों रहे हैं:

the_name = getattr(user, 'name', '<Unknown User>') 
user.name = getattr(user, 'name', '<Unknown User>') 
if not hasattr(name, 'user'): 
    try_asking_again() 
name = user.name if hasattr(user, 'name') else do_expensive_name_lookup(user) 

बेहतर, पूरी प्रक्रिया को समझने के लिए इस स्निपेट को देखो:

class Thing(): 
    def __init__(self): 
     self.a = 'A' 

    def __getattr__(self, attr): 
     if attr == "b": 
      return "B" 
     else: 
      raise AttributeError("Thing instance has no attribute '" + attr + "'") 

item = Thing() 
print "hasattr(a) is " + str(hasattr(item, "a")) 
print "a is " + item.a 
print "hasattr(b) is " + str(hasattr(item, "b")) 
print "b is " + item.b 
out = "c is " + item.c if hasattr(item, "c") else "No C" 
print out 
print "and c is also " + getattr(item, "c", "Not Assigned") 
print "c throws an Attribute exception " + item.c 

जो इस आउटपुट है:

hasattr(a) is True 
a is A 
hasattr(b) is True 
b is B 
No C 
and c is also Not Assigned 
Traceback (most recent call last): 
    File "attr_snippet.py", line 23, in <module> 
    print "c throws an Attribute exception " + item.c 
    File "attr_snippet.py", line 9, in __getattr__ 
    raise AttributeError("Thing instance has no attribute '" + attr + "'") 
AttributeError: Thing instance has no attribute 'c' 
5

जो जवाब की तरह, लेकिन छोटे:

getattr(obj, 'attr', lambda: None)() 
+0

हाँ, यह काम करता है। मैं अभी भी ज्यादातर मामलों में कोशिश/छोड़ने के दृष्टिकोण का उपयोग करता हूं हालांकि अन्य लोगों को पढ़ना आसान होता है। – chhantyal

संबंधित मुद्दे