दिलचस्प पोस्ट
संपादक / प्रदर्शन टेम्पलेट्स में अनुभागों का उपयोग करना जावास्क्रिप्ट ऑब्जेक्ट सदस्य हैं जो प्रोटोटाइप हैं क्योंकि एरेज सभी क्लास इंस्टेंसेस द्वारा साझा किए जाते हैं जावास्क्रिप्ट में '1' से '0001' कन्वर्ट करें एंड्रॉइड प्रोग्रामेटिक रूप से होम स्क्रीन में शॉर्टकट कैसे जोड़ें {डुप्लिकेट] प्रत्येक श्रेणी के लिए शीर्ष 10 रिकॉर्ड चुनें पायथन में मौजूदा मॉड्यूल के गुणों का संदर्भ कैसे प्राप्त करें I जावा में सिंगलटन क्लास आईओएस 6/7 में संदेश "सेल सेल के लिए कोई इंडेक्स पथ पुनः उपयोग नहीं किया जा रहा है" का क्या अर्थ है? कैसे 2 गणना तार दिया कोसाइन समानता की गणना करने के लिए? – पायथन जावास्क्रिप्ट में {} या नया ऑब्जेक्ट () के साथ एक खाली ऑब्जेक्ट बनाएँ? फोनगैप प्लगइन: Base64 स्ट्रिंग को एक पीएनजी छवि को एंड्रॉइड में कन्वर्ट करने के लिए कैसे करें अपलोड की गई फाइल को चेक कैसे करें, चाहे वह एक छवि या अन्य फाइल है? एंड्रॉइड – असीन्क टास्क को मजबूती से रद्द करें JQuery के साथ चयनित <select> का पहला विकल्प कैसे बनाया जाए? पंक्ति में पंक्ति के बजाय एक बार में डेटाबेस में संपूर्ण डेटाटाले सम्मिलित करें?

क्या यह पायथन की पुनः कॉमपाइल का उपयोग करने लायक है?

क्या पायथन में नियमित अभिव्यक्ति के लिए संकलन का उपयोग करने में कोई लाभ है?

h = re.compile('hello') h.match('hello world') 

बनाम

 re.match('hello', 'hello world') 

वेब के समाधान से एकत्रित समाधान "क्या यह पायथन की पुनः कॉमपाइल का उपयोग करने लायक है?"

मेरे पास बहुत से अनुभव है जो एक संकलित किए गए रेगेक्स 1000s का समय बना रहा है, जिस पर उड़ान भरने के लिए बना है, और किसी भी असफल अंतर पर गौर नहीं किया है। जाहिर है, यह एक वास्तविक घटना है, और निश्चित रूप से संकलन के खिलाफ एक महान तर्क नहीं है, लेकिन मैंने अंतर पाया कि नगण्य होना चाहिए।

संपादित करें: वास्तविक पायथन 2.5 लाइब्रेरी कोड पर एक त्वरित नज़र के बाद, मुझे लगता है कि पायथन आंतरिक रूप से संकलित करता है और जब भी आप उन्हें फिर से उपयोग करते हैं ( re.match() लिए कॉल सहित re.match() , ताकि आप वास्तव में केवल बदल रहे हैं जब regex हो जाता है संकलित, और बहुत अधिक समय नहीं बचा जाना चाहिए – केवल कैश की जाँच करने के लिए लेता है (एक आंतरिक dict प्रकार पर एक कुंजी लुकअप)

मॉड्यूल re.py से (मेरी टिप्पणियां हैं):

 def match(pattern, string, flags=0): return _compile(pattern, flags).match(string) def _compile(*key): # Does cache check at top of function cachekey = (type(key[0]),) + key p = _cache.get(cachekey) if p is not None: return p # ... # Does actual compilation on cache miss # ... # Caches compiled regex if len(_cache) >= _MAXCACHE: _cache.clear() _cache[cachekey] = p return p 

मैं अभी भी अक्सर नियमित अभिव्यक्ति संकलित करता हूं, लेकिन केवल उन्हें एक अच्छा, पुन: प्रयोज्य नाम के साथ बाँध करने के लिए, किसी भी अपेक्षित प्रदर्शन लाभ के लिए नहीं।

मेरे लिए, re.compile का सबसे बड़ा लाभ किसी भी प्रकार का समयपूर्व अनुकूलन नहीं है (जो सभी बुराइयों की जड़ है , वैसे भी )। यह regex की इसकी परिभाषा को अलग करने में सक्षम है

यहां तक ​​कि एक सरल अभिव्यक्ति जैसे 0|[1-9][0-9]* (प्रमुख शून्य में बिना आधार 10 में पूर्णांक) यह काफी जटिल हो सकता है कि आपको इसे फिर से टाइप न करना पड़े, यह जांचें कि क्या आपने कोई टाइपो बनाया है, और बाद में पुन: जांचना होगा यदि डीबगिंग शुरू करने पर टाइपो होते हैं इसके अलावा, यह 0|[1-9][0-9]* से अधिक एक चर नाम जैसे num या num_b10 का उपयोग करने के लिए अच्छा है 0|[1-9][0-9]*

यह निश्चित रूप से तारों को संग्रहीत करने और उन्हें पुनः करने के लिए संभव है। हालांकि, यह कम पठनीय है:

 num = "..." # then, much later: m = re.match(num, input) 

बनाम संकलन:

 num = re.compile("...") # then, much later: m = num.match(input) 

हालांकि यह काफी करीब है, दूसरे की अंतिम पंक्ति बार-बार इस्तेमाल होने पर अधिक प्राकृतिक और सरल महसूस करती है।

FWIW:

 $ python -m timeit -s "import re" "re.match('hello', 'hello world')" 100000 loops, best of 3: 3.82 usec per loop $ python -m timeit -s "import re; h=re.compile('hello')" "h.match('hello world')" 1000000 loops, best of 3: 1.26 usec per loop 

इसलिए, यदि आप एक ही regex का उपयोग करने जा रहे हैं, तो re.compile (विशेष रूप से अधिक जटिल regexes के लिए) करने के लिए इसके लायक हो सकता है।

समयपूर्व अनुकूलन के खिलाफ मानक तर्क लागू होते हैं, लेकिन मुझे नहीं लगता कि आपको वास्तव में re.compile का उपयोग करके बहुत स्पष्टता / सीधापन खोना है अगर आपको संदेह है कि आपके regexps एक प्रदर्शन बाधा बन सकता है

यहां एक साधारण परीक्षण का मामला है:

 ~$ for x in 1 10 100 1000 10000 100000 1000000; do python -m timeit -n $x -s 'import re' 're.match("[0-9]{3}-[0-9]{3}-[0-9]{4}", "123-123-1234")'; done 1 loops, best of 3: 3.1 usec per loop 10 loops, best of 3: 2.41 usec per loop 100 loops, best of 3: 2.24 usec per loop 1000 loops, best of 3: 2.21 usec per loop 10000 loops, best of 3: 2.23 usec per loop 100000 loops, best of 3: 2.24 usec per loop 1000000 loops, best of 3: 2.31 usec per loop 

re.compile के साथ:

 ~$ for x in 1 10 100 1000 10000 100000 1000000; do python -m timeit -n $x -s 'import re' 'r = re.compile("[0-9]{3}-[0-9]{3}-[0-9]{4}")' 'r.match("123-123-1234")'; done 1 loops, best of 3: 1.91 usec per loop 10 loops, best of 3: 0.691 usec per loop 100 loops, best of 3: 0.701 usec per loop 1000 loops, best of 3: 0.684 usec per loop 10000 loops, best of 3: 0.682 usec per loop 100000 loops, best of 3: 0.694 usec per loop 1000000 loops, best of 3: 0.702 usec per loop 

इसलिए, यह इस सरल मामला के साथ संकलित करने के लिए प्रतीत होता है, भले ही आप केवल एक बार मैच करें

मैं सिर्फ खुद की कोशिश की। एक स्ट्रिंग के बाहर एक संख्या को पार्स करने और इसे संक्षेप करने के सरल मामले के लिए, एक संकलित नियमित अभिव्यक्ति ऑब्जेक्ट का इस्तेमाल करते हुए दो तरीके के रूप में तेजी से re विधियों का इस्तेमाल करते हैं।

जैसा कि अन्य लोगों ने बताया है, re तरीकों ( re.compile सहित) पहले संकलित अभिव्यक्तियों के कैश में नियमित अभिव्यक्ति स्ट्रिंग को देखते हैं। इसलिए, सामान्य स्थिति में, re विधियों का उपयोग करने की अतिरिक्त लागत केवल कैश लुकअप की लागत है।

हालांकि, कोड की जांच से पता चलता है कि कैश 100 भावों तक सीमित है। यह सवाल पूछता है, कैश को कितना दर्दनाक है? कोड में नियमित अभिव्यक्ति कंपाइलर, re.sre_compile.compile लिए एक आंतरिक इंटरफ़ेस है। अगर हम इसे कहते हैं, तो हम कैश को बायपास करते हैं। यह एक बुनियादी नियमित अभिव्यक्ति के लिए धीमी गति के दो आदेशों के बारे में बताता है, जैसे r'\w+\s+([0-9_]+)\s+\w*'

यहां मेरा परीक्षण है:

 #!/usr/bin/env python import re import time def timed(func): def wrapper(*args): t = time.time() result = func(*args) t = time.time() - t print '%s took %.3f seconds.' % (func.func_name, t) return result return wrapper regularExpression = r'\w+\s+([0-9_]+)\s+\w*' testString = "average 2 never" @timed def noncompiled(): a = 0 for x in xrange(1000000): m = re.match(regularExpression, testString) a += int(m.group(1)) return a @timed def compiled(): a = 0 rgx = re.compile(regularExpression) for x in xrange(1000000): m = rgx.match(testString) a += int(m.group(1)) return a @timed def reallyCompiled(): a = 0 rgx = re.sre_compile.compile(regularExpression) for x in xrange(1000000): m = rgx.match(testString) a += int(m.group(1)) return a @timed def compiledInLoop(): a = 0 for x in xrange(1000000): rgx = re.compile(regularExpression) m = rgx.match(testString) a += int(m.group(1)) return a @timed def reallyCompiledInLoop(): a = 0 for x in xrange(10000): rgx = re.sre_compile.compile(regularExpression) m = rgx.match(testString) a += int(m.group(1)) return a r1 = noncompiled() r2 = compiled() r3 = reallyCompiled() r4 = compiledInLoop() r5 = reallyCompiledInLoop() print "r1 = ", r1 print "r2 = ", r2 print "r3 = ", r3 print "r4 = ", r4 print "r5 = ", r5 </pre> And here is the output on my machine: <pre> $ regexTest.py noncompiled took 4.555 seconds. compiled took 2.323 seconds. reallyCompiled took 2.325 seconds. compiledInLoop took 4.620 seconds. reallyCompiledInLoop took 4.074 seconds. r1 = 2000000 r2 = 2000000 r3 = 2000000 r4 = 2000000 r5 = 20000 

'सचमुच कंपाइल' तरीके आंतरिक इंटरफ़ेस का उपयोग करते हैं, जो कि कैश को छोड़ देता है। ध्यान दें कि प्रत्येक लूप चलने पर संकलित होने वाले प्रत्येक संदेश को केवल 10,000 बार, दस लाख न केवल

मैं ईमानदार अबे से सहमत हूं कि दिए गए उदाहरणों में match(...) अलग हैं। वे एक-एक-एक तुलना नहीं करते हैं और इस प्रकार, परिणाम भिन्न होते हैं। मेरे उत्तर को आसान बनाने के लिए, मैं उन कार्यों के लिए ए, बी, सी, डी का उपयोग करता हूं। ओह, हाँ, हम 4 के बजाय 3 के बजाय 4 कार्यों के साथ काम कर रहे हैं।

कोड का यह भाग चलाना:

 h = re.compile('hello') # (A) h.match('hello world') # (B) 

यह कोड चलाने के समान है:

 re.match('hello', 'hello world') # (C) 

क्योंकि, जब स्रोत re.py में देखा जाता है, (ए + बी) का अर्थ है:

 h = re._compile('hello') # (D) h.match('hello world') 

और (सी) वास्तव में है:

 re._compile('hello').match('hello world') 

तो, (सी) के समान नहीं है (बी)। वास्तव में, (सी) कॉल (बी) कॉल करने के बाद (डी) जो कि (ए) द्वारा भी बुलाया जाता है दूसरे शब्दों में, (C) = (A) + (B) इसलिए, लूप के अंदर (ए + बी) की तुलना करना एक समान परिणाम है (सी) एक पाश के अंदर।

जॉर्ज के regexTest.py हमारे लिए यह साबित कर दिया।

 noncompiled took 4.555 seconds. # (C) in a loop compiledInLoop took 4.620 seconds. # (A + B) in a loop compiled took 2.323 seconds. # (A) once + (B) in a loop 

प्रत्येक व्यक्ति की रुचि है, 2.323 सेकंड का परिणाम कैसे प्राप्त करें सुनिश्चित करने के लिए कि compile(...) केवल एक बार कहा जाता है, हमें संकलित रीजेक्स ऑब्जेक्ट को स्मृति में संग्रहीत करने की आवश्यकता है अगर हम एक वर्ग का उपयोग कर रहे हैं, तो हम ऑब्जेक्ट को स्टोर कर सकते हैं और जब भी हर बार हमारे फ़ंक्शन को कॉल किया जाता है, पुनः उपयोग कर सकते हैं।

 class Foo: regex = re.compile('hello') def my_function(text) return regex.match(text) 

अगर हम कक्षा का उपयोग नहीं कर रहे हैं (जो आज मेरा अनुरोध है), तो मेरे पास कोई टिप्पणी नहीं है। मैं अभी भी पायथन में वैश्विक चर का उपयोग करने के लिए सीख रहा हूं, और मुझे पता है कि वैश्विक चर एक बुरी बात है

एक और बात, मेरा मानना ​​है कि (A) + (B) दृष्टिकोण का उपयोग ऊपरी हाथ है यहां कुछ तथ्य दिए गए हैं जैसा मैंने देखा (कृपया मुझे सही करें अगर मैं गलत हूं):

  1. कॉल एक बार, यह एक खोज को _cache में एक के बाद एक sre_compile.compile() के बाद एक regex ऑब्जेक्ट बनाने के लिए करेगा। एक कॉल दो बार, यह दो खोजों और एक संकलित करेगा (क्योंकि रीजक्स ऑब्जेक्ट कैश है)।

  2. अगर _cache बीच में _cache , तो फिर _cache ऑब्जेक्ट मेमोरी से रिलीज़ हो जाता है और पायथन को फिर से संकलन करने की आवश्यकता होती है। (कोई सुझाव देता है कि पायथन पुनः कंपाइल नहीं होगा।)

  3. यदि हम (ए) का उपयोग करके regex ऑब्जेक्ट रखते हैं, तो regex ऑब्जेक्ट अभी भी _cache में आ जाएगा और किसी तरह फ्लेवर मिलेगा। लेकिन हमारा कोड इस पर एक संदर्भ रखता है और रीजेक्स ऑब्जेक्ट को स्मृति से रिलीज़ नहीं किया जाएगा। उन, पायथन को फिर से संकलित करने की आवश्यकता नहीं है

  4. जॉर्ज के परीक्षण में 2 सेकंड का अंतर संकलित अंतहीन बनाम संकलित मुख्य रूप से चाबी बनाने और _cache की खोज करने के लिए आवश्यक समय है। इसका अर्थ यह नहीं है कि रेगेक्स का संकलन समय।

  5. जॉर्ज के सचमुग्ध परीक्षण का पता चलता है कि क्या हुआ अगर यह वास्तव में हर बार संकलन करता है: यह 100x धीमा हो जाएगा (वह 1,000,000 से 10,000 तक पाश कम कर देगा)।

यहां केवल ऐसे मामले हैं जो (ए + बी) (सी) से बेहतर हैं:

  1. अगर हम एक वर्ग के अंदर regex ऑब्जेक्ट का संदर्भ कैश कर सकते हैं।
  2. यदि हमें (बी) बार-बार (एक लूप या कई बार) कॉल करने की आवश्यकता है, तो हमें लूप के बाहर ऑब्जेक्ट regex के संदर्भ को कैश करना होगा।

ऐसा मामला (सी) काफी अच्छा है:

  1. हम एक संदर्भ कैश नहीं कर सकते
  2. हम केवल थोड़ी देर में इसका इस्तेमाल करते हैं।
  3. कुल मिलाकर, हमारे पास बहुत अधिक regex नहीं है (मान लें कि कंपाइल किए गए एक को कभी नहीं मिला है)

बस एक संक्षिप्त, यहां एबीसी हैं:

 h = re.compile('hello') # (A) h.match('hello world') # (B) re.match('hello', 'hello world') # (C) 

पढ़ने के लिए धन्यवाद।

सामान्य तौर पर, मुझे लगता है कि झंडे का उपयोग करना आसान है (कम से कम कैसे याद रखना आसान है), जैसे re.I जब झंडे इनलाइन का उपयोग करने के लिए पैटर्न को संकलित करते हैं

 >>> foo_pat = re.compile('foo',re.I) >>> foo_pat.findall('some string FoO bar') ['FoO'] 

बनाम

 >>> re.findall('(?i)foo','some string FoO bar') ['FoO'] 

अधिकतर, इसमें थोड़ा अंतर होता है कि क्या आप recompile का उपयोग करते हैं या नहीं। आंतरिक रूप से, सभी फ़ंक्शंस एक संकलन चरण के अनुसार लागू होते हैं:

 def match(pattern, string, flags=0): return _compile(pattern, flags).match(string) def fullmatch(pattern, string, flags=0): return _compile(pattern, flags).fullmatch(string) def search(pattern, string, flags=0): return _compile(pattern, flags).search(string) def sub(pattern, repl, string, count=0, flags=0): return _compile(pattern, flags).sub(repl, string, count) def subn(pattern, repl, string, count=0, flags=0): return _compile(pattern, flags).subn(repl, string, count) def split(pattern, string, maxsplit=0, flags=0): return _compile(pattern, flags).split(string, maxsplit) def findall(pattern, string, flags=0): return _compile(pattern, flags).findall(string) def finditer(pattern, string, flags=0): return _compile(pattern, flags).finditer(string) 

इसके अतिरिक्त, recompile () अतिरिक्त indirection और कैशिंग तर्क को छोड़कर:

 _cache = {} _pattern_type = type(sre_compile.compile("", 0)) _MAXCACHE = 512 def _compile(pattern, flags): # internal: compile pattern try: p, loc = _cache[type(pattern), pattern, flags] if loc is None or loc == _locale.setlocale(_locale.LC_CTYPE): return p except KeyError: pass if isinstance(pattern, _pattern_type): if flags: raise ValueError( "cannot process flags argument with a compiled pattern") return pattern if not sre_compile.isstring(pattern): raise TypeError("first argument must be string or compiled pattern") p = sre_compile.compile(pattern, flags) if not (flags & DEBUG): if len(_cache) >= _MAXCACHE: _cache.clear() if p.flags & LOCALE: if not _locale: return p loc = _locale.setlocale(_locale.LC_CTYPE) else: loc = None _cache[type(pattern), pattern, flags] = p, loc return p 

Re.compile का उपयोग करने से छोटे गति लाभ के अतिरिक्त, लोगों को पठनीयता भी पसंद होती है जो संभावित जटिल पैटर्न विशिष्टताओं के नाम से आती है और उन व्यावसायिक तर्क से अलग करती है जहां लागू होते हैं:

 #### Patterns ############################################################ number_pattern = re.compile(r'\d+(\.\d*)?') # Integer or decimal number assign_pattern = re.compile(r':=') # Assignment operator identifier_pattern = re.compile(r'[A-Za-z]+') # Identifiers whitespace_pattern = re.compile(r'[\t ]+') # Spaces and tabs #### Applications ######################################################## if whitespace_pattern.match(s): business_logic_rule_1() if assign_pattern.match(s): business_logic_rule_2() 

ध्यान दें, एक अन्य प्रतिवादी ने गलत तरीके से मान लिया था कि पीवाईसी फ़ाइलों को सीधे संकलित पैटर्नों में संग्रहीत किया जाता है; हालांकि, वास्तविकता में वे हर बार पुनर्निर्माण किया जाता है जब पीवाईसी भरी हुई है:

 >>> from dis import dis >>> with open('tmp.pyc', 'rb') as f: f.read(8) dis(marshal.load(f)) 1 0 LOAD_CONST 0 (-1) 3 LOAD_CONST 1 (None) 6 IMPORT_NAME 0 (re) 9 STORE_NAME 0 (re) 3 12 LOAD_NAME 0 (re) 15 LOAD_ATTR 1 (compile) 18 LOAD_CONST 2 ('[aeiou]{2,5}') 21 CALL_FUNCTION 1 24 STORE_NAME 2 (lc_vowels) 27 LOAD_CONST 1 (None) 30 RETURN_VALUE 

उपरोक्त disassembly पीवाईसी फ़ाइल से tmp.py युक्त होता है:

 import re lc_vowels = re.compile(r'[aeiou]{2,5}') 

दिलचस्प है, संकलन मेरे लिए अधिक कुशल साबित करता है (Win XP पर पायथन 2.5.2):

 import re import time rgx = re.compile('(\w+)\s+[0-9_]?\s+\w*') str = "average 2 never" a = 0 t = time.time() for i in xrange(1000000): if re.match('(\w+)\s+[0-9_]?\s+\w*', str): #~ if rgx.match(str): a += 1 print time.time() - t 

उपरोक्त कोड एक बार चल रहा है, और एक बार दो के साथ if लाइनें दूसरी तरफ टिप्पणी करती हैं, संकलित रेगेक्स दोगुनी दोगुनी है

इससे पहले कि मैं इस चर्चा पर ठोकर खाई, मैंने इस परीक्षा में भाग लिया। हालांकि, इसे चलाने के बाद मैंने सोचा कि मैं कम से कम अपने परिणाम पोस्ट करूँगा

मैंने जेफ फ्रिडल के "मास्टरींग रेगुलर एक्सप्रेशंस" में उदाहरण को चुरा लिया और बेकार किया। यह ओएसएक्स 10.6 (2 जीएचज़ इंटेल कोर 2 जोड़ी, 4 जीबी राम) चलने वाली मैकबुक पर है। पायथन संस्करण 2.6.1 है।

रन 1 – re.compile का उपयोग कर

 import re import time import fpformat Regex1 = re.compile('^(a|b|c|d|e|f|g)+$') Regex2 = re.compile('^[ag]+$') TimesToDo = 1000 TestString = "" for i in range(1000): TestString += "abababdedfg" StartTime = time.time() for i in range(TimesToDo): Regex1.search(TestString) Seconds = time.time() - StartTime print "Alternation takes " + fpformat.fix(Seconds,3) + " seconds" StartTime = time.time() for i in range(TimesToDo): Regex2.search(TestString) Seconds = time.time() - StartTime print "Character Class takes " + fpformat.fix(Seconds,3) + " seconds" Alternation takes 2.299 seconds Character Class takes 0.107 seconds 

रन 2 – re.compile का उपयोग नहीं करना

 import re import time import fpformat TimesToDo = 1000 TestString = "" for i in range(1000): TestString += "abababdedfg" StartTime = time.time() for i in range(TimesToDo): re.search('^(a|b|c|d|e|f|g)+$',TestString) Seconds = time.time() - StartTime print "Alternation takes " + fpformat.fix(Seconds,3) + " seconds" StartTime = time.time() for i in range(TimesToDo): re.search('^[ag]+$',TestString) Seconds = time.time() - StartTime print "Character Class takes " + fpformat.fix(Seconds,3) + " seconds" Alternation takes 2.508 seconds Character Class takes 0.109 seconds 

दिए गए उदाहरणों का उपयोग करना:

 h = re.compile('hello') h.match('hello world') 

उपर्युक्त उदाहरण में मिलान विधि नीचे दिए गए प्रयोग के समान नहीं है:

 re.match('hello', 'hello world') 

re.compile () एक नियमित अभिव्यक्ति ऑब्जेक्ट देता है , जिसका अर्थ है कि एक regex ऑब्जेक्ट है।

रिजेक्स ऑब्जेक्ट की अपनी वैकल्पिक विधि और वैकल्पिक पैरामीटर पैरामीटर के साथ है:

regex.match(string[, pos[, endpos]])

स्थिति

वैकल्पिक दूसरा पैरामीटर POS स्ट्रिंग में एक सूचकांक देता है जहां खोज शुरू होती है; यह 0 से चूक जाता है। यह पूरी तरह से स्ट्रिंग टुकड़ा करने की क्रिया के बराबर नहीं है; '^' पैटर्न चरित्र स्ट्रिंग की वास्तविक शुरुआत और एक नई रेखा के ठीक बाद स्थितियों पर मेल खाता है, लेकिन जरूरी नहीं कि सूचकांक में जहां खोज शुरू होनी है

endpos

वैकल्पिक पैरामीटर endpos सीमा तक कितनी दूर की खोज की जाएगी; ऐसा होगा जैसे स्ट्रिंग वर्णों को लंबे समय तक खिसकती है , इसलिए स्थिति से केवल endpos - 1 को मैच के लिए खोजा जाएगा। यदि एंडोज स्थिति से कम है, तो कोई मेल नहीं मिलेगा; अन्यथा, यदि आरएक्स एक संकलित नियमित अभिव्यक्ति वस्तु है, तो rx.search(string, 0, 50) rx.search(string[:50], 0) बराबर है।

रीजेक्स ऑब्जेक्ट की खोज , खोज और खोजी विधियों ने इन पैरामीटरों का भी समर्थन किया है।

re.match(pattern, string, flags=0) उनको समर्थन नहीं करता जैसा कि आप देख सकते हैं,
न ही इसकी खोज , खोज , और शोधक समकक्षों का पता नहीं है।

एक मैच ऑब्जेक्ट में इन पैरामीटर के पूरक हैं:

match.pos

पॉज़ का मान जो खोज () या मैच () रीजक्स ऑब्जेक्ट की विधि को पारित किया गया था। यह उस स्ट्रिंग में सूचकांक है जिस पर रे इंजन एक मैच की तलाश करना शुरू कर रहा था।

match.endpos

एंडोप्स का मान जो खोज () या मैच () विधि को एक रीजेक्स ऑब्जेक्ट के पास दिया गया था। यह उस स्ट्रिंग में सूचकांक है जिसके अलावा आरई इंजन नहीं जाएंगे।


एक regex ऑब्जेक्ट में दो अनूठे, संभवतः उपयोगी विशेषताएँ हैं:

regex.groups

पैटर्न में कैप्चरिंग समूहों की संख्या

regex.groupindex

समूह शब्दकोशों के लिए (? पी) द्वारा परिभाषित किसी भी प्रतीकात्मक समूह नामों को मैप करने वाला एक शब्दकोश। शब्दकोश खाली है अगर कोई प्रतीकात्मक समूह पैटर्न में उपयोग नहीं किया गया था।


और अंत में, एक मैच ऑब्जेक्ट में यह विशेषता है:

match.re

नियमित अभिव्यक्ति ऑब्जेक्ट जिसका मिलान () या खोज () विधि ने इस मैच के उदाहरण का उत्पादन किया।

Re.VERBOSE का उपयोग करते हुए मेरे regex पैटर्न पर टिप्पणी जोड़ने के रूप में re.compile () का उपयोग करने के एक अतिरिक्त लाभ है

 pattern = ''' hello[ ]world # Some info on my pattern logic. [ ] to recognize space ''' re.search(pattern, 'hello world', re.VERBOSE) 

यद्यपि यह आपके कोड को चलाने की गति को प्रभावित नहीं करता है, मुझे यह इस तरह करना है क्योंकि यह मेरी टिप्पणी करने की आदत का हिस्सा है। मैं पूरी तरह नापसंद खर्च समय उस तर्क को याद करने की कोशिश कर रहा हूं जो मेरे कोड के पीछे 2 महीने पीछे चला गया जब मैं संशोधनों को बदलना चाहता हूं।

यह अच्छा प्रश्न है। आप अक्सर लोगों को बिना किसी कारण के recompile का उपयोग देखते हैं। यह पठनीयता को कम करता है लेकिन यकीन है कि कई बार जब अभिव्यक्ति पूर्व संकलन के लिए कहा जाता है। जब आप इसे दोहराया बार एक लूप में या कुछ ऐसे प्रयोग करते हैं।

यह प्रोग्रामिंग के बारे में सब कुछ जैसा है (वास्तव में जीवन में सब कुछ) सामान्य ज्ञान लागू करें

प्रदर्शन को अलग करना, re.compile का उपयोग करना और मिलान करने के लिए संकलित नियमित अभिव्यक्ति ऑब्जेक्ट का उपयोग करना (जो भी नियमित अभिव्यक्ति संबंधी ऑपरेशन होता है) सीमेंटिक्स को पायथन रन-टाइम में स्पष्ट करता है

मुझे कुछ सरल कोड डिबग करने का कुछ दर्दनाक अनुभव था:

 compare = lambda s, p: re.match(p, s) 

और बाद में मैं तुलना में उपयोग करते हैं

 [x for x in data if compare(patternPhrases, x[columnIndex])] 

जहां patternPhrases को नियमित अभिव्यक्ति स्ट्रिंग वाला एक चर वाला माना जाता है, x[columnIndex] एक चर वाला स्ट्रिंग है।

मुझे परेशानी थी कि patternPhrases कुछ patternPhrases मेल नहीं खाती थी!

लेकिन अगर मैं re.compile प्रपत्र का उपयोग करता हूं:

 compare = lambda s, p: p.match(s) 

फिर

 [x for x in data if compare(patternPhrases, x[columnIndex])] 

पायथन ने शिकायत करते कि "स्ट्रिंग में मिलान का गुण नहीं है", जैसा कि compare स्थिति में तर्क मैपिंग की compare , x[columnIndex] को नियमित अभिव्यक्ति के रूप में प्रयोग किया जाता है! जब मैं वास्तव में

 compare = lambda p, s: p.match(s) 

मेरे मामले में, recompile का उपयोग नियमित अभिव्यक्ति के उद्देश्य के अधिक स्पष्ट है, जब यह मूल्य नग्न आंखों में छिपा हुआ है, इस प्रकार मैं पायथन रन-टाइम चेकिंग से अधिक सहायता प्राप्त कर सकता हूं।

इसलिए मेरे सबक की नैतिकता यह है कि जब नियमित रूप से अभिव्यक्ति सिर्फ शाब्दिक स्ट्रिंग नहीं होती है, तो मुझे recompile का इस्तेमाल करना चाहिए ताकि पायथन को मेरी धारणा को लागू करने में मदद मिल सके।

यह जवाब देर से पहुंच सकता है लेकिन एक दिलचस्प खोज है यदि आप कई बार regex का उपयोग करने की योजना बना रहे हैं तो कंपाइल का उपयोग वास्तव में आपको समय बचा सकता है (यह दस्तावेज़ों में भी उल्लेख किया गया है)। नीचे आप देख सकते हैं कि एक संकलित regex का उपयोग करना सबसे तेज़ है जब मैच विधि को सीधे उस पर कहा जाता है re.match के लिए एक कंपाइल किए गए रेगेक्स से गुजरने से यह धीमा हो जाता है और फिर से फ़ैसली स्ट्रिंग के साथ फिर से गुजरता है बीच में कहीं है।

 >>> ipr = r'\D+((([0-2][0-5]?[0-5]?)\.){3}([0-2][0-5]?[0-5]?))\D+' >>> average(*timeit.repeat("re.match(ipr, 'abcd100.10.255.255 ')", globals={'ipr': ipr, 're': re})) 1.5077415757028423 >>> ipr = re.compile(ipr) >>> average(*timeit.repeat("re.match(ipr, 'abcd100.10.255.255 ')", globals={'ipr': ipr, 're': re})) 1.8324008992184038 >>> average(*timeit.repeat("ipr.match('abcd100.10.255.255 ')", globals={'ipr': ipr, 're': re})) 0.9187896518778871 

(महीने बाद) अपने खुद के कैश को फिर से मिलान करना आसान है, या उस बात के लिए कुछ भी –

 """ Re.py: Re.match = re.match + cache efficiency: re.py does this already (but what's _MAXCACHE ?) readability, inline / separate: matter of taste """ import re cache = {} _re_type = type( re.compile( "" )) def match( pattern, str, *opt ): """ Re.match = re.match + cache re.compile( pattern ) """ if type(pattern) == _re_type: cpat = pattern elif pattern in cache: cpat = cache[pattern] else: cpat = cache[pattern] = re.compile( pattern, *opt ) return cpat.match( str ) # def search ... 

एक विंबनी, क्या यह अच्छा नहीं होगा यदि: कैशहंट (आकार =), कैचीइन्फो () -> आकार, हिट, निक्लर …

मैं वास्तव में सभी उपरोक्त उत्तरों का सम्मान करता हूं। मेरी राय से हां! सुनिश्चित करने के लिए, हर बार regex को संकलित करने के बजाय recompile का उपयोग करने के लायक है।

Recompile का उपयोग करना आपके कोड को और अधिक गतिशील बना देता है, क्योंकि आप फिर से संकलन के बजाय पहले से संकलित किए गए रेगएक्स को कॉल कर सकते हैं। यह बात आपको मामलों में लाभ देती है:

  1. प्रोसेसर प्रयास
  2. समय जटिलता
  3. Regex यूनिवर्सल बनाता है। (खोज, खोज, मैच में इस्तेमाल किया जा सकता है)
  4. और आपके प्रोग्राम को शांत दिखता है।

उदाहरण :

  example_string = "The room number of her room is 26A7B." find_alpha_numeric_string = re.compile(r"\b\w+\b") 

Findall में प्रयोग

  find_alpha_numeric_string.findall(example_string) 

खोज में उपयोग करना

  find_alpha_numeric_string.search(example_string) 

इसी तरह आप इसके लिए उपयोग कर सकते हैं: मिलान और विकल्प

दूसरे संस्करण का उपयोग करते समय उपयोग किए जाने से पहले नियमित अभिव्यक्तियां संकलित की जाती हैं। यदि आप इसे कई बार निष्पादित करने जा रहे हैं तो इसे पहले संकलित करना निश्चित रूप से बेहतर है। यदि हर बार जब आप एक ऑफ के लिए मैच करते हैं, तो संकलन नहीं करते तो ठीक है।

मैं प्रेरणा देना चाहता हूं कि प्री-कंपाइलिंग दोनों व्यावहारिक रूप से और 'literately' ('साक्षर प्रोग्रामिंग' के रूप में) लाभप्रद है। इस कोड स्निपेट पर नजर डालें:

 from re import compile as _Re class TYPO: def text_has_foobar( self, text ): return self._text_has_foobar_re_search( text ) is not None _text_has_foobar_re_search = _Re( r"""(?i)foobar""" ).search TYPO = TYPO() 

आपके आवेदन में, आप लिखते हैं:

 from TYPO import TYPO print( TYPO.text_has_foobar( 'FOObar ) ) 

यह कार्यक्षमता के मामले में उतना आसान है जितना इसे प्राप्त हो सकता है। क्योंकि यह उदाहरण इतनी छोटी है, मैंने एक ही पंक्ति में _text_has_foobar_re_search को प्राप्त करने का तरीका _text_has_foobar_re_search दिया है इस कोड का नुकसान यह है कि TYPO लाइब्रेरी ऑब्जेक्ट के जीवनकाल के लिए जो कुछ भी है, उसकी थोड़ी मेमोरी है; लाभ यह है कि जब फ़ॉबर खोज कर रहा हो, तो आप दो फंक्शन कॉल और दो क्लास शब्दकोश खोजों के साथ भाग लेंगे। कितने regexes re कैश कर रहे हैं और उस कैश के ऊपरी यहाँ अप्रासंगिक हैं

इस की तुलना में अधिक सामान्य शैली के साथ, नीचे:

 import re class Typo: def text_has_foobar( self, text ): return re.compile( r"""(?i)foobar""" ).search( text ) is not None 

आवेदन में:

 typo = Typo() print( typo.text_has_foobar( 'FOObar ) ) 

मैं आसानी से स्वीकार करता हूं कि मेरी शैली अजगर के लिए बहुत असामान्य है, शायद बहस का भी हो सकता है हालांकि, उदाहरण में, जिसने अधिक मिलान किया है, अजगर का अधिकतर प्रयोग किया जाता है, एक एकल मैच करने के लिए, हमें एक ऑब्जेक्ट इन्स्तांत करना होगा, तीन उदाहरण शब्दकोश लुकअप करना होगा, और तीन फ़ंक्शन कॉल करना होगा; additionally, we might get into re caching troubles when using more than 100 regexes. also, the regular expression gets hidden inside the method body, which most of the time is not such a good idea.

be it said that every subset of measures—targeted, aliased import statements; aliased methods where applicable; reduction of function calls and object dictionary lookups—can help reduce computational and conceptual complexity.

I've had a lot of experience running a compiled regex 1000s of times versus compiling on-the-fly, and have not noticed any perceivable difference

The votes on the accepted answer leads to the assumption that what @Triptych says is true for all cases. आवश्यक रूप से यह सही नहीं है। One big difference is when you have to decide whether to accept a regex string or a compiled regex object as a parameter to a function:

 >>> timeit.timeit(setup=""" ... import re ... f=lambda x, y: x.match(y) # accepts compiled regex as parameter ... h=re.compile('hello') ... """, stmt="f(h, 'hello world')") 0.32881879806518555 >>> timeit.timeit(setup=""" ... import re ... f=lambda x, y: re.compile(x).match(y) # compiles when called ... """, stmt="f('hello', 'hello world')") 0.809190034866333 

It is always better to compile your regexs in case you need to reuse them.

Note the example in the timeit above simulates creation of a compiled regex object once at import time versus "on-the-fly" when required for a match.

My understanding is that those two examples are effectively equivalent. The only difference is that in the first, you can reuse the compiled regular expression elsewhere without causing it to be compiled again.

Here's a reference for you: http://diveintopython3.ep.io/refactoring.html

Calling the compiled pattern object's search function with the string 'M' accomplishes the same thing as calling re.search with both the regular expression and the string 'M'. Only much, much faster. (In fact, the re.search function simply compiles the regular expression and calls the resulting pattern object's search method for you.)