2011-07-18 13 views
9

मेरे पास ऐसी विधियां हैं जो उन वस्तुओं से प्राप्त करने के लिए डिक्ट्स या अन्य ऑब्जेक्ट्स और "फ़ील्ड्स" के नाम स्वीकार करती हैं। यदि ऑब्जेक्ट एक नियम है तो नामित कुंजी पुनर्प्राप्त करने के लिए विधि __getitem__ का उपयोग करती है, अन्यथा यह नामित विशेषता पुनर्प्राप्त करने के लिए getattr का उपयोग करती है। वेब टेम्पलेटिंग भाषाओं में यह बहुत आम है। उदाहरण के लिए, एक Chameleon टेम्पलेट में आप हो सकता है:पायथन में हाइब्रिड गेटैटर + __getitem__ क्यों बनाया गया है?

<p tal:content="foo.keyname">Stuff goes here</p> 

आप {'keyname':'bar'} की तरह एक dict के रूप में foo में पास है, तो foo.keyname 'बार' पाने के लिए 'कीनेम' कुंजी को हासिल करेगा। यदि foo एक वर्ग की तरह का एक उदाहरण है:

class Foo(object): 
    keyname = 'baz' 

तो foo.keynamekeyname विशेषता से मूल्य को हासिल करेगा।

def lookup_attr(obj, key): 
    try: 
     return getattr(obj, key) 
    except AttributeError as exc: 
     try: 
      get = obj.__getitem__ 
     except AttributeError: 
      raise exc 
     try: 
      return get(key) 
     except KeyError: 
      raise exc 

मैं की तरह my own package में इसे लागू किया गया है:: गिरगिट ही है कि समारोह (chameleon.py26 मॉड्यूल में) इस तरह लागू करता

try: 
    value = obj[attribute] 
except (KeyError, TypeError): 
    value = getattr(obj, attribute) 

बात है, कि एक बहुत आम पैटर्न है। मैंने उस विधि को देखा है या बहुत सारे मॉड्यूल में इसके साथ बहुत ही समान है। तो भाषा के मूल में, या कम से कम कोर मॉड्यूल में ऐसा कुछ क्यों नहीं है? यह असफल रहा, क्या यह एक निश्चित तरीका है कि लिखा जाना चाहिए?

+2

मैं दृढ़ता से ऑब्जेक्ट करता हूं कि "बात यह है कि यह एक सुंदर आम पैटर्न है"। स्पष्ट से स्पष्ट स्पष्ट है। विशेषता पहुंच पूरी तरह से कुछ है जो कुंजी द्वारा उपयोग ... –

+1

हां, लेकिन पेज टेम्पलेट भाषाओं जैसे कुछ संदर्भों में यह अभी भी काफी आम है। मैंने इसे देखा है (और इसे लागू करने की आवश्यकता है) अक्सर यह इच्छा करने के लिए पर्याप्त है कि इसे मूल या एक सामान्य मॉड्यूल में दोहराया गया हो। –

+2

ऐसा कुछ भी नहीं है - संभवतः क्योंकि पाइथन डेवलपर खराब प्रोग्रामिंग शैली को लागू नहीं करना चाहता .... प्वाइंट..फिर आप खराब कोड लिखना चाहते हैं तो आपको इसे स्पष्ट रूप से लिखना होगा .... स्पष्ट रूप से स्पष्ट है । –

उत्तर

15

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

"अजगर क्यों प्रदान नहीं करता है किसी भी निर्मित रास्ते के इलाज के लिए विशेषताएं और वस्तुओं को परिवर्तनीय के रूप में? "


मैंने इस प्रश्न पर काफी विचार किया है, और मुझे लगता है कि उत्तर बहुत आसान है। जब आप एक कंटेनर प्रकार बनाते हैं, तो विशेषताओं और आइटम के बीच अंतर करना बहुत महत्वपूर्ण है। किसी भी उचित रूप से अच्छी तरह से विकसित कंटेनर प्रकार में कई गुण होंगे - हालांकि हमेशा तरीकों से नहीं - जो इसे अपनी सामग्री को सुंदर तरीके से प्रबंधित करने में सक्षम बनाता है। तो उदाहरण के लिए, एक dict0 items, values, keys, iterkeys और इसी तरह से है। इन विशेषताओं को . नोटेशन का उपयोग करके एक्सेस किया जाता है। दूसरी ओर, वस्तुओं को [] नोटेशन का उपयोग करके एक्सेस किया जाता है। तो कोई टकराव नहीं हो सकता है।

क्या होता है जब आप . नोटेशन का उपयोग करके आइटम एक्सेस सक्षम करते हैं? अचानक आपके पास ओवरस्पेपिंग नामस्थान है। अब आप टकराव कैसे संभालते हैं? यदि आप एक नियम को उपclass करते हैं और इसे यह कार्यक्षमता देते हैं, तो आप नियम के रूप में items जैसी चाबियों का उपयोग नहीं कर सकते हैं, या आपको किसी प्रकार का नेमस्पेस पदानुक्रम बनाना होगा। पहला विकल्प एक नियम बनाता है जो कठिन, पालन करने में कठोर है, और लागू करने में कठोर है। दूसरा विकल्प टकराव की समस्या को पूरी तरह से हल किए बिना जटिलता का एक कष्टप्रद मात्रा बनाता है, क्योंकि आपको अभी भी यह निर्दिष्ट करने के लिए एक वैकल्पिक इंटरफ़ेस होना चाहिए कि आप items आइटम या items विशेषता चाहते हैं या नहीं।

अब, कुछ प्रकार के बहुत ही प्राचीन प्रकार के लिए, यह स्वीकार्य है। शायद यही कारण है कि मानक लाइब्रेरी में namedtuple है, उदाहरण के लिए। (लेकिन (_asdict की तरह विरासत से बचाता है ध्यान दें कि namedtuple ये बहुत समस्याओं के अधीन है, जो शायद यही वजह है कि यह एक कारखाने समारोह के रूप में लागू किया गया था) और का उपयोग करता है अजीब, निजी विधि के नाम।)

यह भी बहुत, बहुत, बहुत आसान है object का उप-वर्ग बनाने के लिए कोई (सार्वजनिक) विशेषता नहीं है और setattr पर इसका उपयोग करें। यह __getattribute__, __setattr__ और __delattr__ आह्वान करने के लिए __getitem__, __setitem__, और __delitem__ ओवरराइड करने के लिए है, इसलिए है कि आइटम का उपयोग सिर्फ getattr() के लिए वाक्यात्मक चीनी, setattr(), आदि हो जाता है और भी बहुत आसान है (हालांकि कि थोड़ा अधिक संदिग्ध के बाद से यह कुछ हद तक अप्रत्याशित व्यवहार बनाता है।)

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

4

आप आसानी से अपना खुद का dict सबक्लास लिख सकते हैं जो मूल रूप से इस तरह से व्यवहार करता है। एक न्यूनतम कार्यान्वयन, जो मैं एक विशेषताओं में से "ढेर" कहते हैं, इसलिए की तरह है:

class Pile(dict): 
    def __getattr__(self, key): 
     return self[key] 
    def __setattr__(self, key, value): 
     self[key] = value 

दुर्भाग्य से यदि आप के बजाय, या तो शब्दकोशों या विशेषता से लदी वस्तुओं आप के लिए पारित से निपटने के लिए सक्षम होना चाहिए शुरुआत से वस्तु का नियंत्रण रखते हुए, इससे मदद नहीं मिलेगी।

आपकी स्थिति में मैं शायद आपके पास जो कुछ भी है, उसका उपयोग कर रहा हूं, इसे एक समारोह में तोड़ने के अलावा, मुझे इसे हर समय दोहराना नहीं है।

+2

यह सिर्फ बात है; मेरे पास वास्तव में नियंत्रण नहीं है कि इसमें क्या हो रहा है और मैं इसे अपने पैकेज के उपयोगकर्ताओं के लिए जितना संभव हो सके उतना आसान बनाना चाहता हूं, वैसे ही वही अर्थशास्त्र का उपयोग करना जो हर किसी को पहले ही हल कर चुका है। :-) उत्तर के लिए धन्यवाद, यद्यपि। जो भी इसे कम करता है उसके बारे में खेद है। : - / –

5

अजगर मानक पुस्तकालय में निकटतम बात एक namedtuple(), http://docs.python.org/dev/library/collections.html#collections.namedtuple

Foo = namedtuple('Foo', ['key', 'attribute']) 
foo = Foo(5, attribute=13) 
print foo[1] 
print foo.key 

है या फिर आप आसानी से अपने खुद प्रकार है कि हमेशा वाकई वहां दुकानों dict है, लेकिन विशेषता सेटिंग और हो रही है की उपस्थिति की अनुमति देता है परिभाषित कर सकते हैं :

class MyDict(dict): 
    def __getattr__(self, attr): 
     return self[attr] 
    def __setattr__(self, attr, value): 
     self[attr] = value 

d = MyDict() 

d.a = 3 
d[3] = 'a' 
print(d['a']) # 3 
print(d[3]) # 'a' 
print(d['b']) # Returns a keyerror 

लेकिन d.3 ऐसा नहीं करते हैं, क्योंकि वह एक सिंटैक्स त्रुटि है। इस तरह एक हाइब्रिड स्टोरेज प्रकार बनाने के लिए निश्चित रूप से अधिक जटिल तरीके हैं, कई उदाहरणों के लिए वेब पर खोजें।

जहां तक ​​दोनों की जांच करने के लिए, गिरगिट रास्ता पूरी तरह से दिखता है। जब 'मानक पुस्तकालय में दोनों करने का कोई तरीका नहीं है' की बात आती है तो ऐसा इसलिए होता है क्योंकि अस्पष्टता बीएडी है। हां, हमारे पास पाइथन में डकटाइपिंग और अन्य सभी प्रकार की मास्कराइडिंग है, और कक्षाएं वास्तव में वैसे भी शब्दकोश हैं, लेकिन किसी बिंदु पर हम एक वर्ग से सूची के मुकाबले एक कंटेनर से अलग कार्यक्षमता चाहते हैं, जैसा कि हम एक वर्ग से चाहते हैं, इसकी विधि संकल्प आदेश के साथ , ओवरराइडिंग, आदि

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