2011-05-04 11 views
5

मैंने अभी "isinstance() considered harmful" पढ़ा है, और यह उचित लगता है। संक्षेप में, यह इस फ़ंक्शन के उपयोग से बचने के लिए तर्क देता है।बिना इंस्टेंसेंस के सूचियों की सूची में रिकर्सन()

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

def parseTree(input): 
    if isinstance (input, list): 
     for item in input: 
      parseTree(item) 
    else: 
     treatLeafNode(item) 

:

मैं निम्नलिखित के रूप में रिकर्सिवली सूचियों पार्स करने के लिए (वृक्ष की संरचना के उपयोग ommiting, चलो आसान बनाने में करते हैं और treatLeafNode (कहते हैं) प्रत्येक पत्ती नोड पर बुलाया जाना चाहिए) की योजना लेख, मैं सोच रहा हूं कि Isinstance() का उपयोग किए बिना उस पर पुनर्विचार करने का एक आसान तरीका है ...

क्या कोई भी किसी को जानता है?

उत्तर

10

आपकी स्थिति उन लोगों में से एक है जहां मैं isinstance का उपयोग करूंगा। आपकी डेटा संरचना अच्छी तरह से बाधित है, और आपको एक सूची के बीच अंतर करने की आवश्यकता है, न कि सूची में। यह पूछने के लिए कि क्या यह एक सूची है, isinstance का उपयोग करें। आप नहीं कहते हैं, लेकिन मुझे लगता है कि तार आपके पेड़ की पत्तियों में से हो सकते हैं, और सूचियों के रूप में वे पुनरावृत्त हैं, इसलिए यह उनके बीच बतख-टाइपिंग तरीकों में अंतर करने के लिए विचित्र रूप से है।

+1

++, ध्वनि सलाह –

5

आप इस्तेमाल कर सकते हैं

def parseTree(input): 
    try: 
     for item in input: 
      parseTree(item) 
    except TypeError: 
     treatLeafNode(item) 

ध्यान दें कि यह भी हालांकि तार से अधिक पुनरावृति होगी।

+1

@Andrey: अपनी बात क्या है? –

+0

क्षमा करें, मैं गलत था – Andrey

+1

@Sven: शायद एंड्री का मतलब था कि 'इनपुट में आइटम के लिए' भी सफल होगा यदि इनपुट 'स्ट्रिंग' है, तो यह कोड "पेड़" जैसे "[" abc ", [" rty " "," xyz "]]' –

2

क्या बेहतर काम कर सकते हैं एक नोड वस्तु जो एक मूल्य और बच्चों की एक सूची रख सकते हैं के साथ अपने वृक्ष संरचना encapsulating है:

class Node(object): 
    def __init__(self, children=[], value=None): 
     self.children = children 
     self.value = value 
    def isLeaf(self): 
     return len(self.children) == 0 

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

def parseTree(node): 
    if node.isLeaf(): 
     treatLeafNode(node) 
    else: 
     for child in node.children: 
      parseTree(child) 

ध्यान दें कि यह पेड़ पर गहराई-पहले खोज है: parseTree के रूप में लिखा जा सकता है।

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

0

याम का उपयोग करने के बारे में कैसे? आपको खुद को सत्यापन और पार्सिंग तर्क भी नहीं करना पड़ेगा।

पेड़ की तरह पार्स करने के लिए

- [[aMAN],[sTACK, OVER],[FLOW]] 
- [[aMAN1],[sTACK1, OVER1],[FLOW1]] 
- [[aMAN2],[sTACK2, OVER2],[FLOW2]] 

कोड दिखाई दे सकता है यह

import yaml      
f= open('test.yml') 
test = yaml.load(f.read()) 
print test 

आउटपुट:

[[['aMAN'], ['sTACK', 'OVER'], ['FLOW']], [['aMAN1'], ['sTACK1', 'OVER1'], ['FLOW1']], [['aMAN2'], ['sTACK2', 'OVER2'], ['FLOW2']]] 
0

वहाँ एक कारण यह है कि आप के रूप में सूचियों की एक सूची चुन लिया है आपकी पसंदीदा पेड़ संरचना? मैं कॉन्फ़िगरेशन फ़ाइल में लिखने के कई बेहतर तरीकों के बारे में सोच सकता हूं। कैसे के बारे में

a: b, i, j 
b: c, d, g 
d: e, f 
g: h 
j: k 

आप बहुत आसानी से पार्स कर सकते हैं एक शब्दकोश में है, और यह ऊपर में शामिल होने के एक पेड़ से

a 
|-- b 
| |-- c 
| |-- d 
| | |-- e 
| | `-- f 
| `-- g 
|  `-- h 
|-- i 
`-- j 
    `-- k 

: मान लीजिए आप एन्कोड करने के लिए कोशिश कर रहे हैं। वास्तव में, मुझे लगता है कि ConfigParser पहले से ही आपके लिए यह करेगा।

वरना, कैसे के बारे में:

a 
----b 
--------c 
--------d 
------------e 
------------f 
--------g 
------------h 
----i 
----j 
--------k