2016-04-12 6 views
7

चलो कहते हैं कि मैं इन पारसर्स करते हैं:से संशोधित करना उपज द्वारा दिया गया मान

parsers = { 
    ".foo": parse_foo, 
    ".bar", parse_bar 
} 

parse_foo और parse_bar दोनों जनरेटर है कि एक के बाद एक पंक्तियां प्राप्त कर रहे हैं। मैं एक एकल प्रेषण समारोह बनाने के लिए चाहते हैं, तो मैं यह कर जाएगा:

def parse(ext): 
    yield from parsers[ext]() 

वाक्य रचना से उपज अप और जनरेटर नीचे आसानी से सुरंग जानकारी के लिए मुझे अनुमति देता है।

उपज परिणामों को संशोधित करते समय सुरंग को बनाए रखने का कोई तरीका है?
ऐसा करने से सुरंग को तोड़ने जबकि आसान है:

def parse(ext): 
    for result in parsers[ext](): 
     # Add the extension to the result 
     result.ext = ext 
     yield result 

लेकिन इस तरह से मैं पार्सर को .send() या .throw() सभी तरह उपयोग नहीं कर सकते।

एकमात्र तरीका जिस पर मैं सोच रहा हूं वह try: ... except Exception: ... की तरह बदसूरत कर रहा है और अपवाद को पास करता है, जबकि .send() के लिए ऐसा करता है। यह बदसूरत, गन्दा और बग प्रवण है।

+0

मुझे लगता है कि आपका सर्वश्रेष्ठ दांव शायद एक 'passthrough_map' करता है जनरेटर के माध्यम से map' जबकि' गुजर send' और 'throw' क्या' करता है लागू करने के लिए किया जाएगा आप मैपिंग कर रहे हैं आईआईआरसी, यह सही करना मुश्किल है, लेकिन आपको केवल इसे एक बार सही करने की आवश्यकता है, और फिर जब भी आपको उस कार्यक्षमता की आवश्यकता होती है तो आप इसका पुन: उपयोग कर सकते हैं। – user2357112

उत्तर

0

दुर्भाग्य से कोई अंतर्निहित नहीं है जो करता है। आप इसे कक्षाओं का उपयोग करके स्वयं लागू कर सकते हैं लेकिन cotoolz नामक पैकेज को map() फ़ंक्शन लागू करता है जो वास्तव में करता है।

उनका नक्शा फ़ंक्शन बिल्टिन map() से 4 गुना धीमा है, लेकिन यह जनरेटर प्रोटोकॉल से अवगत है, और इसी तरह के पायथन कार्यान्वयन से तेज़ है (यह सी में लिखा गया है और एक सी 99 कंपाइलर की आवश्यकता है)।

अपने पृष्ठ से एक उदाहरण:

>>> def my_coroutine(): 
...  yield (yield (yield 1)) 
>>> from cotoolz import comap 
>>> cm = comap(lambda a: a + 1, my_coroutine()) 
>>> next(cm) 
2 
>>> cm.send(2) 
3 
>>> cm.send(3) 
4 
>>> cm.send(4) 
Traceback (most recent call last): 
    ... 
StopIteration 
0

parse_foo और parse_bar एक्सटेंशन जोड़ने है:

def parse_foo(ext): 
    # Existing code 
    ... 
    # Add an extension to the item(s) 
    item.ext = ext 

def parse(ext): 
    yield from parsers[ext](ext) 

या बस प्रत्येक समारोह में यह हार्डकोड:

def parse_foo(): 
    # Existing code 
    ... 
    # Add an extension to the item(s) 
    item.ext = ".foo" 
+0

यह 'प्रेषण' और 'फेंक' तोड़ता है। – user2357112

+0

यह काम नहीं करता है और वास्तव में 'प्रेषण' और 'फेंक' तोड़ता है। – Bharel

+0

@ user2357112 यह किस तरह से 'भेज' और 'फेंक' तोड़ता है? –

2

अलावा try ... yield ... except ऐसा करने का एक और तरीका है: एक नया जनरेटर को लागू करने से। इस वर्ग के साथ आप सभी आदानों और अपने अंतर्निहित जनरेटर के आउटपुट को बदलने कर सकते हैं:

identity = lambda x: x 
class map_generator: 
    def __init__(self, generator, outfn = identity, 
     infn = identity, throwfn = identity): 
    self.generator = generator 
    self.outfn = outfn 
    self.infn = infn 
    self.throwfn = throwfn 
    self.first = True 
    def __iter__(self): 
    return self 
    def __next__(self): 
    return self.send(None) 
    def _transform(self, value): 
    if self.first: 
     self.first = False 
     return value 
    else: 
     return self.infn(value) 
    def send(self, value): 
    return self.outfn(self.generator.send(self._transform(value))) 
    def throw(self, value): 
    return self.outfn(self.generator.throw(self.throwfn(value))) 
    def next(self): # for python2 support 
    return self.__next__() 

उपयोग:

def foo(): 
    for i in "123": 
    print("sent to foo: ", (yield i)) 

def bar(): 
    dupe = lambda x:2*x 
    tripe = lambda x:3*x 
    yield from map_generator(foo(), dupe, tripe) 

i = bar() 
print("received from bar: ", i.send(None)) 
print("received from bar: ", i.send("B")) 
print("received from bar: ", i.send("C")) 

... 

received from bar: 11 
sent to foo: BBB 
received from bar: 22 
sent to foo: CCC 
received from bar: 33 

संपादित करें: आप collections.Iterator से प्राप्त करना चाहते हो सकता है, लेकिन यह में आवश्यक नहीं है यह उपयोग

+0

आपने जवाब देने के लिए बहुत बहुत धन्यवाद। मुझे [cotoolz] (https://pypi.python.org/pypi/cotoolz) नामक एक पैकेज मिला जो स्पष्ट रूप से ऐसा करता है, लेकिन इसे सी में कार्यान्वित किया जाता है जिसके परिणामस्वरूप तेजी से निष्पादन होता है, इसलिए मैं इसके साथ जाऊंगा। – Bharel

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