2012-11-28 16 views
14

में गतिशील विशेषता रही मेरे पास है और एक छद्म या विशेष विशेषता है कि तीन अलग अलग तरीकों से नामित किया जा सकता है के साथ वस्तु:अजगर

(नोट मैं कोड जो वस्तु उत्पन्न करता है को नियंत्रित नहीं करते) (निर्भर करता है जो एक सेट है) विशेषताओं में मूल्य बिल्कुल वैसा ही है, और मुझे लगता है कि प्राप्त करने के लिए आगे की प्रक्रिया के लिए की जरूरत है, तो डेटा स्रोत की निर्भर करता है, मैं की तरह कुछ हो सकता है:

>>> obj.a 
'value' 
>>> obj.b 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: Obj instance has no attribute 'b' 
>>> obj.c 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: Obj instance has no attribute 'c' 

या

>>> obj.a 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: Obj instance has no attribute 'a' 
>>> obj.b 
'value' 
>>> obj.c 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: Obj instance has no attribute 'c' 

या

>>> obj.a 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: Obj instance has no attribute 'a' 
>>> obj.b 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: Obj instance has no attribute 'b' 
>>> obj.c 
'value' 

मैं 'value' और दुर्भाग्य से __dict__ संपत्ति हो रही है कि वस्तु में मौजूद नहीं है में दिलचस्पी रखता हूँ। तो मैं उस मूल्य को प्राप्त करने के लिए क्या कर रहा था, बस getattr कॉल का एक गुच्छा था।

>>> g = lambda o, l: getattr(o, l[0], getattr(o, l[1], getattr(o, l[2], None))) 
>>> g(obj, ('a', 'b', 'c')) 
'value' 

अब, मुझे पता है कि यह करने के लिए एक बेहतर तरीका है कि क्या वहाँ चाहते हैं: यह मानते हुए कि संभावनाओं केवल तीन हैं, कोड इस तरह देखा? मैं कर रहा हूँ के रूप में 100% आश्वस्त मैं क्या किया है :)

अग्रिम धन्यवाद

+0

बस जांचने के लिए - 'get_value()' (या समान) नहीं है या जैसा कि आप 'डेटा के स्रोत के आधार पर' उल्लेख करते हैं - कोई मौजूदा (या व्युत्पन्न मैपिंग) नहीं है स्रोत -> विशेषता का नाम? –

उत्तर

28

की तरह कैसे के बारे में:

for name in 'a', 'b', 'c': 
    try: 
     thing = getattr(obj, name) 
    except AttributeError: 
     pass 
    else: 
     break 
+0

की जांच करूंगा, मैं वास्तव में कोशिश करने से बचने की कोशिश कर रहा था/इसे छोड़कर .. मुझे यह उल्लेख करना चाहिए था :) – rhormaza

+1

सामान्य पायथनिक तरीके से कोशिश/छोड़कर, किसी भी अच्छे कारण से आप इससे बचना चाहते हैं? – wim

+0

कोई भी वास्तव में अच्छा कारण नहीं है, बस कोड को संक्षिप्त रखना चाहता था और मुझे लगता है कि एक कोशिश/छोड़कर थोड़ा अधिक था :) दूसरी बात जो मैं अब जांच रहा था वह यह है कि ब्लॉक किसी के मामले में डिफ़ॉल्ट मान प्रदान नहीं करता है ये गुण मौजूद हैं, हालांकि यह बेहद असंभव है, फिर भी मुझे लगता है कि रक्षात्मक दृष्टिकोण का उपयोग करना हमेशा अच्छा होता है :) – rhormaza

0

मैं dir का उपयोग कर यू अनिवार्य रूप से एक ही बात __dict__ सामान्य हो जाएगा ...

targetValue = "value" 
for k in dir(obj): 
    if getattr(obj,k) == targetValue: 
     print "%s=%s"%(k,targetValue) 

कुछ लगता है

>>> class x: 
... a = "value" 
... 
>>> dir(x) 
['__doc__', '__module__', 'a'] 
>>> X = x() 
>>> dir(X) 
['__doc__', '__module__', 'a'] 
>>> for k in dir(X): 
...  if getattr(X,k) == "value": 
...  print "%s=%s"%(k,getattr(X,k)) 
... 
a=value 
>>> 
+0

इस के लिए धन्यवाद, मैंने पूरी तरह से डीआईआर() को याद किया ... बस सोच रहा है ... कैसे dir() कॉल आंतरिक रूप से काम करता है। मैं – rhormaza

2

इस आइटम के किसी भी संख्या के साथ काम करने का लाभ दिया है:

def getfirstattr(obj, *attrs): 
    return next((getattr(obj, attr) for attr in attrs 
        if hasattr(obj, attr)), None) 

यह है कि यह अंतिम मूल्य पर दो लुकअप करता बहुत नाबालिग दोष यह है: एक बार जांच करने के लिए उस गुण मौजूद है, एक और वास्तव में मूल्य प्राप्त करने के लिए। यह एक नेस्टेड जनरेटर अभिव्यक्ति का उपयोग कर से बचा जा सकता है:

def getfirstattr(obj, *attrs): 
    return next((val for val in (getattr(obj, attr, None) for attr in attrs) 
        if val is not None), None) 

लेकिन मैं वास्तव में यह एक बड़ा सौदा है नहीं लग रहा है। जनरेटर अभिव्यक्ति शायद डबल-लुकअप के साथ एक सादे पुराने लूप की तुलना में तेज़ होने जा रही है।

+1

के लिए धन्यवाद मैंने लगभग इस प्रभाव में कुछ पोस्ट किया है। समस्या यह है कि आप जिस तत्व को चाहते हैं उसके लिए दो बार जांचना समाप्त कर देते हैं (एक बार 'हैट्टर' के साथ और एक बार 'गेटैटर' के साथ)। आखिरकार, मैंने फैसला किया कि यह विम द्वारा पोस्ट किए गए स्पष्ट लूप से वास्तव में बेहतर नहीं था - हालांकि मैं लूप पर होने वाले किसी भी फायदे के बारे में सुनने के लिए खुला हूं। – mgilson

+0

डबल-लुकअप से बचने के लिए आप नेस्टेड जनरेटर का उपयोग कर सकते हैं, मुझे लगता है, लेकिन यह तब होता है जब यह विशेषता पाता है, इसलिए मैं इसे मामूली कमी मानता हूं। हालांकि, मैंने अभी ऐसा संस्करण जोड़ा है। – kindall

+0

अच्छा एक ... मैं एक नज़र डालने वाला हूं .. धन्यवाद – rhormaza

0

आपकी ऑब्जेक्ट की संरचना के आधार पर ऐसा करने का एक बेहतर तरीका हो सकता है, लेकिन कुछ भी नहीं जानना, यहां एक पुनरावर्ती समाधान है जो आपके वर्तमान समाधान की तरह काम करता है सिवाय इसके कि यह तर्कसंगत तर्कों के साथ काम करेगा:

g = lambda o, l: getattr(o, l[0], g(o, l[1:])) if l else None 
+0

मुझे सादगी और ब्रेवटी – rhormaza

-1

और एक और एक:

reduce(lambda x, y:x or getattr(obj, y, None), "a b c".split(), None) 

(अजगर 3 में आप functools से कम करने के लिए आयात करने के लिए है।यह पायथन 2 में एक बिल्टिन है)

+0

के लिए वास्तव में यह पसंद आया, यह मानता है कि 'बूल (obj.b)' सत्य है। विचार करें कि अगर आपके पास 'obj.a = 0' था तो क्या होगा। मुझे नहीं लगता कि आप इसे उठाएंगे। – mgilson