পাইথনের রি ডট কম ব্যবহার করা কি উপযুক্ত?


461

পাইথনে নিয়মিত প্রকাশের জন্য সংকলন ব্যবহার করে কি কোনও সুবিধা রয়েছে?

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

বনাম

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


58
আমি কেবল এমন একটি ক্ষেত্রে দৌড়েছি যেখানে ব্যবহার করে re.compile10-50x উন্নতি দেওয়া হয়েছে। নৈতিক যে যদি আপনি regexes অনেক আছে (চেয়েও বেশি MAXCACHE = 100) এবং আপনি তাদেরকে বার প্রতিটি (এবং পৃথক অনেক ব্যবহার MAXCACHE বেশি করে, মাঝে regexes যাতে প্রতিটি এক ক্যাশে থেকে রাঙা পরার: তাই ব্যবহার একই বারটি অনেক বার এবং তারপরে পরবর্তীটিতে গণনা করা হয় না), তবে এটি অবশ্যই সংকলন করতে সহায়তা করবে। অন্যথায়, এটি কোনও পার্থক্য করে না।
শ্রীভাত্সারআর

8
একটি ছোট বিষয় লক্ষণীয় তা হল যে স্ট্রিংগুলির জন্য যেগুলি in>python -m timeit -s "import re" "re.match('hello', 'hello world')" 1000000 loops, best of 3: 1.41 usec per loop >python -m timeit "x = 'hello' in 'hello world'" 10000000 loops, best of 3: 0.0513 usec per loop
রেইগেক্সের

পছন্দ করুন আপনি কি একটি উদাহরণ সহ একটি উত্তর পোস্ট করতে পারেন যা 10x-50x উন্নতি দেখায়? এখানে প্রদত্ত বেশিরভাগ উত্তর আসলে কিছু সুনির্দিষ্ট ক্ষেত্রে একটি 3x উন্নতি দেখায় এবং অন্যান্য ক্ষেত্রে প্রায় কোনও উন্নতি হয় না।
বাসজ

1
@ বাসজ ডোন, একটি উত্তর পোস্ট করেছেন । আমি ডিসেম্বর ২০১৩ সালে পাইথনটি যা ব্যবহার করছিলাম তা খনন করতে আমি বিরক্ত করিনি, তবে প্রথম যে সোজাসুজি চেষ্টা করেছিলাম তা একই আচরণ দেখায়।
শ্রীভাতসার

উত্তর:


436

অন-ফ্লাইটি সংকলন করার তুলনায় একটি সংকলিত রেইগেক্স এ্যানেল চালানোর প্রচুর অভিজ্ঞতা পেয়েছি, এবং কোনও অনুভূতিগত পার্থক্য লক্ষ্য করিনি। স্পষ্টতই, এটি বিস্ময়কর এবং অবশ্যই এর বিরুদ্ধে একটি দুর্দান্ত যুক্তি নয় সংকলনের , তবে আমি পার্থক্যটি নগণ্য বলে মনে করেছি।

সম্পাদনা: বাস্তব পাইথন ২.২ লাইব্রেরি কোডটিতে এক ঝলক দেখার পরে আমি দেখতে পাচ্ছি যে পাইথন অভ্যন্তরীণভাবে যখনই আপনি সেগুলি ব্যবহার করতে (যখন কল সহ re.match()) ব্যবহার করেন তখনই অভ্যন্তরীণভাবে সংকলন করে এবং ক্যাচস রেজিওসগুলিকে সংকলন করে এবং যাতে আপনি সত্যই কেবল পরিবর্তন করছেন যখন রাজকেন্দ্রটি সংকলিত হয়ে যায় এবং ' টি মোটেও বেশি সময় সাশ্রয় করছে না - ক্যাশে যাচাই করতে কেবল সময় লাগে (একটি অভ্যন্তরীণে কী অনুসন্ধান)dict ধরণের লুকোচুরি)।

মডিউল রি.পি. থেকে (মন্তব্যগুলি আমার):

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

আমি এখনও প্রায়শই নিয়মিত প্রকাশগুলি প্রাক-সংকলন করি তবে কেবল তাদের প্রত্যাশিত পারফরম্যান্স লাভের জন্য নয়, কেবল একটি সুন্দর, পুনরায় ব্যবহারযোগ্য নামের সাথে আবদ্ধ করতে।


12
আপনার উপসংহারটি আপনার উত্তরের সাথে বেমানান। যদি রেজেক্সগুলি স্বয়ংক্রিয়ভাবে সংকলিত হয় এবং সংরক্ষণ করা হয় তবে বেশিরভাগ ক্ষেত্রে হাতে হাতে এটি করার প্রয়োজন নেই।
jfs

84
জেএফ সেবাস্তিয়ান, এটি প্রোগ্রামারের কাছে সিগন্যাল হিসাবে কাজ করে যে প্রশ্নে থাকা রেজিএক্সএক্স অনেক ব্যবহৃত হবে এবং এটি নিক্ষিপ্ত হওয়ার উদ্দেশ্যে নয়।
ক্যালিসিন

40
এর চেয়েও বড় কথা, আমি বলতে চাই যে আপনি যদি নিজের অ্যাপ্লিকেশনটির কিছু পারফরম্যান্সের সমালোচনামূলক অংশে সংকলন ও ক্যাশে আঘাতের শিকার না হতে চান তবে আপনার অ্যাপ্লিকেশনটির একটি অ-সমালোচিত অংশে হাত দেওয়ার আগে সেগুলি সংকলন করা ভাল you're ।
এডি পার্কার

20
আমি যদি আপনার একই রেজেক্সটিকে একাধিকবার পুনরায় ব্যবহার করে সংকলিত রেজেক্স ব্যবহার করার মূল সুবিধাটি দেখি, ফলে টাইপসের সম্ভাবনা হ্রাস পায়। যদি আপনার কেবল একবার এটি কল করা হয় তবে কমম্পাইল করা আরও পঠনযোগ্য।
monkut

18
সুতরাং, মূল পার্থক্যটি তখন ঘটবে যখন আপনি প্রচুর আলাদা রেইগেক্স ব্যবহার করতে পারেন (_MAXCACHE এর চেয়ে বেশি), তাদের মধ্যে কয়েকটি মাত্র একবার এবং অন্যরা প্রচুর বার ... তারপরে আপনার সংকলিত অভিব্যক্তিগুলি আরও বেশি ব্যবহৃত হয় তাদের জন্য রাখা জরুরী সম্পূর্ণ হয়ে গেলে ক্যাশে থেকে বেরিয়ে যাবেন না।
ফোরট্রান

133

আমার জন্য, সবচেয়ে বড় সুবিধা re.compile হ'ল এর ব্যবহার থেকে রেজেক্সের সংজ্ঞা আলাদা করতে সক্ষম হচ্ছেন।

এমনকি একটি সরল অভিব্যক্তি যেমন 0|[1-9][0-9]*(অগ্রণী জিরো ব্যতীত 10 বেসে পূর্ণসংখ্যার) যথেষ্ট জটিল হতে পারে যে আপনি এটি পুনরায় টাইপ করতে হবে না, আপনি কোনও টাইপস তৈরি করেছেন কিনা তা পরীক্ষা করে দেখুন এবং পরে আপনি যখন ডিবাগিং শুরু করছেন তখন টাইপগুলি রয়েছে কিনা তা যাচাই করতে হবে । এছাড়াও, নাম বা 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)

এটি মোটামুটি কাছাকাছি থাকলেও, দ্বিতীয়টির শেষ লাইনটি বারবার ব্যবহার করার সময় আরও প্রাকৃতিক এবং সরল মনে হয়।


5
আমি এই উত্তরের সাথে একমত; প্রায়শই রি.কম্পাইল ব্যবহার করে ফলাফল বেশি, কম পঠনযোগ্য কোড নয়।
কার্ল মায়ার

1
কখনও কখনও বিপরীতটি সত্য হয়, যদিও - উদাহরণস্বরূপ যদি আপনি এক জায়গায় রেজেক্সকে সংজ্ঞায়িত করেন এবং এর মিলে যাওয়া গ্রুপগুলি অন্য কোনও দূরবর্তী জায়গায় ব্যবহার করেন।
কেন উইলিয়ামস

1
@ কেনউইলিয়ামস অগত্যা, মূল সংজ্ঞা থেকে দূরে ব্যবহৃত হলেও নির্দিষ্ট উদ্দেশ্যে নির্দিষ্ট নামযুক্ত রেইগেক্স পরিষ্কার হওয়া উচিত। উদাহরণস্বরূপ us_phone_numberবা social_security_numberইত্যাদি
ব্রায়ান এম শেল্ডন

2
@ ব্রায়ানএম.শেল্ডন রিজেক্সকে ভালভাবে নামকরণ করা আপনাকে এর বিভিন্ন ক্যাপচারিং গ্রুপগুলি কী প্রতিনিধিত্ব করে তা জানতে আপনাকে সত্যই সহায়তা করে না।
কেন উইলিয়ামস

68

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

সুতরাং, আপনি যদি একইre.compile রেজিक्सকে প্রচুর পরিমাণে ব্যবহার করতে যাচ্ছেন তবে এটি করা ভাল হতে পারে (বিশেষত আরও জটিল রেগেক্সগুলির জন্য)।

অকাল অপটিমাইজেশনের বিরুদ্ধে স্ট্যান্ডার্ড আর্গুমেন্টগুলি প্রযোজ্য, তবে আপনি মনে করেন না যে আপনি re.compileযদি সন্দেহ করেন যে আপনার রেজেক্সপস কোনও পারফরম্যান্স বাধা হয়ে উঠতে পারে তবে আপনি ব্যবহার করে সত্যিই খুব স্পষ্টতা / সরলতা হারাবেন না।

হালনাগাদ:

পাইথন ৩.6 এর অধীনে (আমি সন্দেহ করি যে উপরের সময়গুলি পাইথন ২.x ব্যবহার করে সম্পন্ন হয়েছিল) এবং 2018 হার্ডওয়্যার (ম্যাকবুক প্রো), এখন আমি নিম্নলিখিত সময়গুলি পেয়েছি:

% python -m timeit -s "import re" "re.match('hello', 'hello world')"
1000000 loops, best of 3: 0.661 usec per loop

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

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

% python --version
Python 3.6.5 :: Anaconda, Inc.

আমি একটি কেসও যুক্ত করেছি (শেষ দুটি রানের মধ্যে উদ্ধৃতি চিহ্নের পার্থক্যগুলি লক্ষ্য করুন) যা দেখায় যে re.match(x, ...)আক্ষরিক [মোটামুটি] সমতুল্য re.compile(x).match(...), অর্থাত্ সংকলিত উপস্থাপনাটির পিছনে কোনও ক্যাশে ঘটেনি বলে মনে হয়।


5
আপনার পদ্ধতির সাথে এখানে বড় সমস্যা, যেহেতু সেটআপ যুক্তিটি সময় সহ অন্তর্ভুক্ত নয়। সুতরাং, আপনি দ্বিতীয় উদাহরণ থেকে সংকলনের সময়টি সরিয়ে ফেলেছেন এবং প্রথম উদাহরণে কেবল এটি গড়িয়েছেন। এর অর্থ এই নয় যে প্রথম উদাহরণটি প্রতিবার সংকলিত হয়।
ট্রিপটিচ

1
হ্যাঁ, আমি সম্মত হই যে এটি দুটি মামলার ন্যায্য তুলনা নয়।
কিভ

7
আমি আপনাকে যা বলতে চাইছি তা দেখতে পাচ্ছি, তবে সত্যিকারের অ্যাপ্লিকেশনটিতে ঠিক কী ঘটবে যেখানে রেজিএক্সএক্সপ বহুবার ব্যবহৃত হয়?
ডিএফ।

26
@Triptych, @Kiv: কম্পাইল পুরো পয়েন্ট regexps ব্যবহার থেকে আলাদা হয় সংকলন কমানোর জন্য; সময় থেকে এটি অপসারণ হ'ল ডিএফের ঠিক কী করা উচিত ছিল, কারণ এটি সত্য-বিশ্বের ব্যবহারকে সবচেয়ে নির্ভুলভাবে উপস্থাপন করে। টাইমিট.পি এখানে সময় নির্ধারণের সাথে সংকলনের সময়টি বিশেষত অপ্রাসঙ্গিক; এটি বেশ কয়েকটি রান করে এবং কেবলমাত্র সবচেয়ে সংক্ষিপ্ততম একটির প্রতিবেদন করে, যে বিন্দুতে সংকলিত রিজেক্সএক্স ক্যাশে হয়। আপনি এখানে যে অতিরিক্ত ব্যয় দেখতে পাচ্ছেন তা হ'ল রেজিএক্সপ্যাক সংকলনের ব্যয় নয়, তবে এটি সংকলিত রেজএক্সপ্যাক ক্যাশে (একটি অভিধান) অনুসন্ধানের ব্যয়।
jemfinch

3
@ ট্রিপইচ কি import reসেটআপের বাইরে সরানো উচিত ? আপনি কোথায় পরিমাপ করতে চান এটি সবই। যদি আমি অজগর স্ক্রিপ্টটি বহুবার চালিত করি তবে এটির import reসময় হিট হবে। দু'টির তুলনা করার সময় সময় নির্ধারণের জন্য দুটি লাইন আলাদা করা জরুরী। হ্যাঁ আপনি যেমনটি বলেছেন ঠিক তখনই আপনার সময়টি হিট হবে। তুলনাটি দেখায় যে হয় আপনি একবার হিট সময় নিয়েছেন এবং সংকলনের মাধ্যমে কম সময়ের হিটটি পুনরাবৃত্তি করুন বা আপনি প্রতিটি সময় হিট গ্রহণ করে কলগুলির মধ্যে ক্যাশে সাফ হয়ে যাবেন বলে ধরে নিয়েছেন, যা এটি উল্লেখ করা হয়েছে যে ঘটতে পারে। একটি সময় যুক্ত করা h=re.compile('hello')স্পষ্ট করতে সাহায্য করবে।
টম ম্যাদডেল্টেন

39

এখানে একটি সাধারণ পরীক্ষার কেস:

~$ 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

সুতরাং, আপনি কেবল একবারে মিললেও, সংকলনটি এই সাধারণ ক্ষেত্রে দ্রুততর বলে মনে হয় ।


2
পাইথনের এটি কোন সংস্করণ?
কাইল স্ট্র্যান্ড

2
এটি আসলে কোনও ব্যাপার নয়, বিন্দুটি হল আপনি যে পরিবেশে কোডটি
চালাবেন

1
আমার জন্য 1000 লুপ বা আরও বেশিের জন্য পারফরম্যান্স প্রায় একই রকম। সংকলিত সংস্করণ 1-100 লুপের জন্য দ্রুত। (উভয় পাইথন ২.7 এবং ৩.৪)।
জিট্রাক্স

2
আমার পাইথন ২.7.৩ সেটআপে খুব কমই কোনও পার্থক্য রয়েছে। কখনও কখনও সংকলন দ্রুত হয়, কখনও কখনও আইটি এর ধীর। পার্থক্যটি সর্বদা <5%, তাই আমি এই তফাতটিকে অনিশ্চয়তা পরিমাপ হিসাবে গণ্য করি, কারণ ডিভাইসে কেবল একটি সিপিইউ রয়েছে U
ডাকারন

1
পাইথনে ৩.৪.৩ এ দুটি পৃথক রান দেখা গেছে: সংকলিত ব্যবহার কমপাইল না করেও ধীর ছিল।
জেলফির কালটসটহল

17

আমি কেবল এটি চেষ্টা করেছিলাম। একটি স্ট্রিংয়ের বাইরে কোনও সংখ্যাকে পার্স করার এবং সংমিশ্রণের সাধারণ ক্ষেত্রে, একটি সংমিত নিয়মিত অভিব্যক্তি অবজেক্টটি 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 বার পুনরুক্ত করা হয়, এক মিলিয়ন নয় Note


আমি আপনার সাথে সম্মত হই যে সংকলিত রেজেক্সগুলি কম-সংকলিতের চেয়ে অনেক বেশি দ্রুত চলে। আমি ১০,০০০ এরও বেশি বাক্য চালিয়েছি এবং রেজেক্সগুলি সংকলন না করা এবং প্রতিবার পূর্ণ রান করার পূর্বাভাসটি 8 ঘন্টা নির্ধারণ করা হয়েছিল যখন আমি চালিত সংকলিত রেজেক্স প্যাটার্নগুলির সাথে সূচক অনুসারে একটি অভিধান তৈরি করেছিলাম 2 মিনিটের জন্য পুরো জিনিস। আমি উপরের উত্তরগুলি বুঝতে পারি না ...
এলি বোরোডাচ

12

আমি আন্তরিক আবির সাথে একমত যে match(...)প্রদত্ত উদাহরণগুলিতে পৃথক পৃথক। এগুলি এক-একের তুলনা নয় এবং ফলস্বরূপ পৃথক পৃথক। আমার উত্তরকে সহজ করার জন্য, আমি প্রশ্নযুক্ত functions ফাংশনগুলির জন্য এ, বি, সি, ডি ব্যবহার করি। ওহ হ্যাঁ, আমরা re.py3 এর পরিবর্তে 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),। অতএব, একটি লুপের ভিতরে (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

সবার আগ্রহ হ'ল ২.৩৩৩ সেকেন্ডের ফলাফল কীভাবে পাওয়া যায়। compile(...)কেবল একবার কল করা হয়েছে তা নিশ্চিত করার জন্য , আমাদের সংকলিত রেজেক্স অবজেক্টটি মেমরিতে সংরক্ষণ করতে হবে। আমরা যদি কোনও ক্লাস ব্যবহার করে থাকি তবে প্রতিবার আমাদের ফাংশনটি কল করার সময় আমরা বস্তুটি সংরক্ষণ করতে এবং পুনরায় ব্যবহার করতে পারি।

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

আমরা যদি ক্লাসটি ব্যবহার না করে (যা আজ আমার অনুরোধ), তবে আমার কোনও মন্তব্য নেই। আমি এখনও পাইথনে গ্লোবাল ভেরিয়েবল ব্যবহার করতে শিখছি এবং আমি জানি গ্লোবাল ভেরিয়েবল একটি খারাপ জিনিস।

আরও একটি বিষয়, আমি বিশ্বাস করি যে (A) + (B)পদ্ধতির ব্যবহারের উপরের হাত রয়েছে। আমি পর্যবেক্ষণ হিসাবে এখানে কিছু তথ্য রয়েছে (দয়া করে আমি ভুল হলে আমাকে সংশোধন করুন):

  1. একবার কল করে, একটি রেজেেক্স অবজেক্ট তৈরি _cacheকরতে তার পরে একটি অনুসন্ধান করবে sre_compile.compile()। দু'বার কল করুন, এটি দুটি অনুসন্ধান করবে এবং একটি সংকলন করবে (কারণ রেজেক্স অবজেক্ট ক্যাশে হয়েছে)।

  2. যদি এর _cacheমধ্যে বিভ্রান্ত হয় তবে রেজেক্স অবজেক্টটি মেমরি থেকে প্রকাশিত হয় এবং পাইথনকে আবার সংকলন করতে হবে। (কেউ পরামর্শ দিয়েছেন যে পাইথন পুনরায় সংকলন করবে না))

  3. আমরা যদি (এ) ব্যবহার করে রেজেক্স অবজেক্টটি রাখি তবে রেজেক্স অবজেক্টটি এখনও _ ক্যাশে প্রবেশ করবে এবং কোনওভাবে ফ্লাশ হয়ে যাবে। তবে আমাদের কোড এটিতে একটি রেফারেন্স রাখে এবং রেজেক্স অবজেক্টটি মেমরি থেকে মুক্তি পাবে না। এগুলি, পাইথনের আবার সংকলন করার দরকার নেই।

  4. জর্জের পরীক্ষায় সংকলিত ইনলুপের 2 সেকেন্ডের পার্থক্য হ'ল মূলত কীটি তৈরি করতে এবং _ ক্যাশে অনুসন্ধান করার জন্য প্রয়োজনীয় সময়। এর অর্থ রেগেক্সের সংকলনের সময় নয়।

  5. জর্জের সত্যিকারের সংকলন পরীক্ষাটি দেখায় যে এটি প্রতিবার সংকলনটি সত্যিই পুনরায় করা হলে কী হবে: এটি 100x ধীর হবে (তিনি লুপটি ১,০০,০০০ থেকে কমিয়ে ১০,০০০ করেছেন)।

এখানে (কেবলমাত্র A (B)) (সি) এর চেয়ে ভাল যেগুলি এখানে রয়েছে:

  1. আমরা যদি কোনও শ্রেণীর অভ্যন্তরে রেজেক্স অবজেক্টের একটি রেফারেন্স ক্যাশে করতে পারি।
  2. যদি আমাদের বারবার (বি) কল করা প্রয়োজন (একটি লুপের ভিতরে বা একাধিকবার), আমাদের অবশ্যই লুপের বাইরে রেজেক্স অবজেক্টের রেফারেন্সটি ক্যাশে করতে হবে।

কেস (সি) যথেষ্ট ভাল:

  1. আমরা কোনও রেফারেন্সকে ক্যাশে করতে পারি না।
  2. আমরা এটি একবারে একবার ব্যবহার করি।
  3. সামগ্রিকভাবে, আমাদের খুব বেশি রেজেেক্স নেই (সংকলিতটি কখনই ফ্লাশ হবে না বলে ধরে নিন)

কেবল একটি পুনরুদ্ধার, এখানে এবিসি রয়েছে:

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

পড়ার জন্য ধন্যবাদ.


8

বেশিরভাগ ক্ষেত্রে, আপনি re.compile ব্যবহার করেন বা না করেন তাতে কিছুটা পার্থক্য নেই। অভ্যন্তরীণভাবে, সমস্ত ফাংশন একটি সংকলন পদক্ষেপের পদে প্রয়োগ করা হয়:

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)

তদ্ব্যতীত, re.compile () অতিরিক্ত দিকনির্দেশ এবং ক্যাশে যুক্তিটিকে বাইপাস করে:

_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

উপরের বিচ্ছিন্নতাগুলি পিওয়াইসি ফাইল থেকে একটি ধারণার জন্য আসে tmp.py:

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

1
হয় "def search(pattern, string, flags=0):"একটি টাইপো?
ফুক্লভ

1
মনে রাখবেন যে যদি patternইতিমধ্যে একটি সংকলিত প্যাটার্ন হয় তবে ক্যাশিং ওভারহেড তাৎপর্যপূর্ণ হয়ে ওঠে: হ্যাশিং SRE_Patternএ ব্যয়বহুল এবং প্যাটার্নটি কখনই ক্যাশে লেখা হয় না, তাই প্রতিবার সাথে একবারে অনুসন্ধান ব্যর্থ হয় KeyError
এরিক ডুমিনিল

5

সাধারণভাবে, আমি 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']

আপনি re.findallযেভাবেই হোক তৃতীয় যুক্তি হিসাবে পতাকা ব্যবহার করতে পারেন ।
অ্যাডারচক্স

5

প্রদত্ত উদাহরণগুলি ব্যবহার করে:

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

ম্যাচ উপরোক্ত উদাহরণের পদ্ধতি নিচে ব্যবহার করা হিসাবে একই নয়:

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

re.compile () একটি নিয়মিত এক্সপ্রেশন অবজেক্ট দেয় , যার অর্থ hএকটি রেইজেক্স অবজেক্ট।

Regex বস্তুর নিজস্ব হয়েছে ম্যাচ ঐচ্ছিক সঙ্গে পদ্ধতি পিওএস এবং endpos প্যারামিটার:

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

পিওএস

Alচ্ছিক দ্বিতীয় প্যারামিটার পোস্টগুলি স্ট্রিংটিতে একটি সূচি দেয় যেখানে অনুসন্ধান শুরু করা হবে; এটি 0 এ ডিফল্ট হয় এটি স্ট্রিং টুকরো টুকরো করার মতো সম্পূর্ণরূপে সমান নয়; '^'প্যাটার্ন চরিত্র স্ট্রিং এর বাস্তব শুরুতে এবং মাত্র একটি newline পর অবস্থানের সময়ে ম্যাচ, কিন্তু না অগত্যা সূচক যেখানে অনুসন্ধান শুরু করতে এ।

endpos

Alচ্ছিক প্যারামিটার এন্ডপোস সীমাটি কতটা সন্ধান করা হবে তা সীমাবদ্ধ করে; মনে হবে স্ট্রিংটি এন্ডপোস অক্ষর দীর্ঘ, সুতরাং কেবলমাত্র পজ থেকে অক্ষরগুলি endpos - 1কোনও মিলের জন্য অনুসন্ধান করা হবে। তাহলে endpos চেয়ে কম হয় পিওএস , কোন মিল খুঁজে পাওয়া যায় হবে; অন্যথায়, যদি rx একটি সংমিত নিয়মিত অভিব্যক্তি অবজেক্ট হয়,rx.search(string, 0, 50) সমান rx.search(string[:50], 0)

রেজেক্স অবজেক্টের অনুসন্ধান , সন্ধানকারী এবং সন্ধানকারী পদ্ধতিগুলিও এই পরামিতিগুলিকে সমর্থন করে।

re.match(pattern, string, flags=0)আপনি যেমন দেখতে পারেন তেমন সেগুলি সমর্থন করে না
এবং এর অনুসন্ধান , সন্ধান এবং পাওয়া যায় না finditer প্রতিরূপ।

একজন ম্যাচ অবজেক্টের এমন বৈশিষ্ট্য রয়েছে যা এই পরামিতিগুলির পরিপূরক:

match.pos

কোনও রেজেক্স অবজেক্টের অনুসন্ধান () বা ম্যাচ () পদ্ধতিতে পাস করা পোস্টের মান। আরআর ইঞ্জিনটি ম্যাচের জন্য সন্ধান করতে শুরু করেছে এমন স্ট্রিংয়ের এটি সূচক।

match.endpos

রিজেক্স অবজেক্টের অনুসন্ধান () বা ম্যাচ () পদ্ধতিতে পাস করা এন্ডপোসের মান। এটি স্ট্রিংয়ের সূচক যা এর বাইরে আর ই ইঞ্জিন যাবে না।


একজন রেজেক্স অবজেক্ট দুটি অনন্য, সম্ভবত কার্যকর, বৈশিষ্ট্য রয়েছে:

regex.groups

প্যাটার্নে ক্যাপচার গ্রুপগুলির সংখ্যা।

regex.groupindex

(? পি) দ্বারা সংখ্যার সংখ্যায় সংজ্ঞায়িত কোনও প্রতীকী গ্রুপের নাম ম্যাপ করা একটি অভিধান। নকশাগুলি খালি রয়েছে যদি কোনও প্রতীকী গোষ্ঠী বিন্যাসে ব্যবহার না করা হত।


এবং অবশেষে, একটি ম্যাচ অবজেক্ট এই বৈশিষ্ট্যটি রয়েছে:

match.re

যার মিল () বা অনুসন্ধান () পদ্ধতিটি এই মিলের উদাহরণটি তৈরি করে নিয়মিত প্রকাশের বস্তু।


4

পারফরম্যান্স পার্থক্য একদিকে রেখে, রেটপাইল ব্যবহার করে এবং সংযুক্ত নিয়মিত এক্সপ্রেশন অবজেক্টটি ম্যাচ করার জন্য (নিয়মিত এক্সপ্রেশন সম্পর্কিত ক্রিয়াকলাপ যাই হোক না কেন) শব্দার্থকে পাইথন রান-টাইমে আরও পরিষ্কার করে দেয়।

কিছু সাধারণ কোড ডিবাগ করার জন্য আমার কিছু বেদনাদায়ক অভিজ্ঞতা ছিল:

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

এবং পরে আমি তুলনা ব্যবহার করব

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

যেখানে patternPhrasesনিয়মিত প্রকাশের স্ট্রিং যুক্ত একটি ভেরিয়েবল হিসাবে গণ্য হবে,x[columnIndex] এটি একটি ভেরিয়েবল।

আমার সমস্যা ছিল যা patternPhrasesকিছু প্রত্যাশিত স্ট্রিংয়ের সাথে মেলে না!

তবে আমি যদি re.compile ফর্মটি ব্যবহার করি:

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

তারপরে

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

পাইথন, অভিযোগ আছে করবে অবস্থানগত যুক্তি ম্যাপিং দ্বারা যে "স্ট্রিং ম্যাচ অ্যাট্রিবিউট নেই" compare, x[columnIndex]রেগুলার এক্সপ্রেশন !, যখন আমি আসলে বোঝানো হিসাবে ব্যবহার করা হয়

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

আমার ক্ষেত্রে, রেটপাইল ব্যবহার করা নিয়মিত অভিব্যক্তির উদ্দেশ্যটির সাথে আরও স্পষ্ট হয়, যখন এর মূল্যটি নগ্ন চোখে লুকিয়ে থাকে, সুতরাং পাইথন রান-টাইম চেকিংয়ের থেকে আরও সহায়তা পেতে পারি।

সুতরাং আমার পাঠের নৈতিকতাটি হ'ল যখন নিয়মিত প্রকাশটি কেবল আক্ষরিক স্ট্রিং হয় না, তখন আমার কাছে আমার অনুমানটি দৃsert় রাখতে সাহায্য করার জন্য পাইথনকে পুনরায় ডটকমের সাহায্যে ব্যবহার করা উচিত।


4

Re.pirile () ব্যবহার করার জন্য একটি অতিরিক্ত সংযোজন রয়েছে, re.VERBOSE ব্যবহার করে আমার রেজেক্স প্যাটার্নগুলিতে মন্তব্য যুক্ত করার আকারে

pattern = '''
hello[ ]world    # Some info on my pattern logic. [ ] to recognize space
'''

re.search(pattern, 'hello world', re.VERBOSE)

যদিও এটি আপনার কোডটি চালানোর গতিকে প্রভাবিত করে না, তবে এটি আমার মন্তব্য করার অভ্যাসের অংশ হওয়ায় আমি এটি এটি করতে পছন্দ করি। আমি যখন পরিবর্তন করতে চাই তখন লাইন থেকে 2 মাস পরে আমার কোডটির পিছনে যে যুক্তিটি মনে হয়েছিল তা মনে করার চেষ্টা করার সময়টি আমি সাধারণত পছন্দ করি না।


1
আমি আপনার উত্তর সম্পাদনা করেছি। আমি মনে করি উল্লেখ re.VERBOSEকরা সার্থক, এবং এটি এমন কিছু যুক্ত করে যা অন্য উত্তরগুলি মনে হয় ফেলেছে। তবে আপনার উত্তরটি "আমি এখানে পোস্ট করছি কারণ আমি এখনও মন্তব্য করতে পারি না" এটি মুছে ফেলার বিষয়ে নিশ্চিত। উত্তর ব্যতীত অন্য কোনও কিছুর জন্য উত্তর বাক্সটি ব্যবহার করবেন না। আপনি যে কোনও জায়গায় মন্তব্য করতে সক্ষম হওয়া থেকে মাত্র এক বা দুটি ভাল উত্তর দূরে রয়েছেন (৫০ রেপ), তাই দয়া করে ধৈর্য ধরুন। উত্তর বাক্সগুলিতে মন্তব্য করা যখন আপনি জানেন যে আপনাকে সেখানে আর দ্রুত পাবেন না। এটি আপনাকে ডাউনভিটস এবং মুছে ফেলা উত্তরগুলি পাবে।
skrrgwasme

4

পাইথন ডকুমেন্টেশন অনুযায়ী :

ক্রম

prog = re.compile(pattern)
result = prog.match(string)

সমতুল্য

result = re.match(pattern, string)

কিন্তু ব্যবহার re.compile() জন্য ফলস্বরূপ নিয়মিত অভিব্যক্তি অবজেক্টটি এবং সংরক্ষণ করা আরও কার্যকর হয় যখন এক্সপ্রেশনটি একক প্রোগ্রামে বেশ কয়েকবার ব্যবহৃত হবে।

সুতরাং আমার উপসংহারটি হ'ল, যদি আপনি অনেকগুলি ভিন্ন পাঠ্যের জন্য একই প্যাটার্নটি মেলাতে চলেছেন তবে আপনি এটির পূর্বনির্ধারিত করুন।


3

মজার বিষয় হল, সংকলনটি আমার পক্ষে আরও কার্যকর প্রমাণিত হয়েছে (উইন এক্সপি-তে পাইথন ২.২.২):

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লাইনের সাথে একবারে অন্যভাবে মন্তব্য করা হয়েছে, সংকলিত রেজেক্স দ্বিগুণ দ্রুত


2
ডিএফ এর পারফরম্যান্স তুলনা হিসাবে একই সমস্যা। আপনি সংকলন বিবৃতি নিজেই পারফরম্যান্স ব্যয় অন্তর্ভুক্ত না করা পর্যন্ত এটি সত্যই ন্যায্য নয়।
কার্ল মেয়ার 19

6
কার্ল, আমি একমত নই।
সংকলনটি

@ এলিবেন: আমি কার্ল মায়ারের সাথে একমত সংকলন দুটি ক্ষেত্রেই হয়। ট্রিপটিচ উল্লেখ করেছেন যে ক্যাশে জড়িত, সুতরাং একটি অনুকূল ক্ষেত্রে (পুনরায় ক্যাশে থাকে) উভয় পন্থা হ'ল (এন + 1), যদিও আপনি স্পষ্টভাবে re.compile ব্যবহার করবেন না যখন +1 অংশ এক ধরণের লুকানো।
পেপ্রিকা

1
নিজের বেঞ্চমার্কিং কোডটি লিখবেন না। টাইমাইট.পি ব্যবহার করতে শিখুন যা মান বিতরণের অন্তর্ভুক্ত।
jemfinch

আপনি কতটা সময় লুপের জন্য প্যাটার্ন স্ট্রিংটি পুনরায় তৈরি করছেন। এই ওভারহেড তুচ্ছ হতে পারে না।
আইসআর্ডার

3

আমি এখানে আলোচনাটি করার আগে এই পরীক্ষাটি চালিয়েছি। যাইহোক, এটি চালানোর পরে আমি ভেবেছিলাম আমি কমপক্ষে আমার ফলাফল পোস্ট করব।

আমি জেফ ফ্রেডেলের "মাস্টারিং রেগুলার এক্সপ্রেশনস" এর উদাহরণটি চুরি করে জারজ করে দিয়েছি। এটি ওএসএক্স 10.6 (2 গিগাহার্টজ ইন্টেল কোর 2 ডুয়ো, 4 জিবি র‌্যাম) চলমান ম্যাকবুকে রয়েছে। পাইথন সংস্করণটি 2.6.1 .1

রেটপাইল ব্যবহার করে 1 চালান

import re 
import time 
import fpformat
Regex1 = re.compile('^(a|b|c|d|e|f|g)+$') 
Regex2 = re.compile('^[a-g]+$')
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 - পুনর্নির্মাণ ফাইলটি ব্যবহার করছেন না

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('^[a-g]+$',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

3

এই উত্তরটি দেরিতে আসতে পারে তবে এটি একটি আকর্ষণীয় অনুসন্ধান find আপনি যদি একাধিকবার রিজেক্স ব্যবহার করার পরিকল্পনা করে থাকেন তবে (এটি ডক্সেও উল্লেখ করা হয়েছে) কম্পাইল ব্যবহার করা আপনার সময়কে বাঁচাতে পারে। নীচে আপনি দেখতে পাচ্ছেন যে কোনও সংকলিত রেইগেক্স ব্যবহার করা যখন ম্যাচ পদ্ধতিতে সরাসরি ডাকা হয় তখন এটি সবচেয়ে দ্রুত। re.match এ একটি সংকলিত রেজেক্স পাস করা এটি আরও ধীর করে তোলে এবং প্যাটার স্ট্রিংয়ের সাথে 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

3

পারফরম্যান্স ছাড়াও।

ব্যবহারটি compileআমাকে
১ মডিউল (পুনরায়) ,
২ রেজেক্স অবজেক্ট
৩. ম্যাচ অবজেক্টের সাথে ধারণাটি আলাদা করতে সহায়তা করে
যখন আমি রেজেক্স শিখতে শুরু করি

#regex object
regex_object = re.compile(r'[a-zA-Z]+')
#match object
match_object = regex_object.search('1.Hello')
#matching content
match_object.group()
output:
Out[60]: 'Hello'
V.S.
re.search(r'[a-zA-Z]+','1.Hello').group()
Out[61]: 'Hello'

পরিপূরক হিসাবে, আমি reআপনার রেফারেন্সের জন্য মডিউলটির একটি বিস্তৃত চিটপত্রক তৈরি করেছি ।

regex = {
'brackets':{'single_character': ['[]', '.', {'negate':'^'}],
            'capturing_group' : ['()','(?:)', '(?!)' '|', '\\', 'backreferences and named group'],
            'repetition'      : ['{}', '*?', '+?', '??', 'greedy v.s. lazy ?']},
'lookaround' :{'lookahead'  : ['(?=...)', '(?!...)'],
            'lookbehind' : ['(?<=...)','(?<!...)'],
            'caputuring' : ['(?P<name>...)', '(?P=name)', '(?:)'],},
'escapes':{'anchor'          : ['^', '\b', '$'],
          'non_printable'   : ['\n', '\t', '\r', '\f', '\v'],
          'shorthand'       : ['\d', '\w', '\s']},
'methods': {['search', 'match', 'findall', 'finditer'],
              ['split', 'sub']},
'match_object': ['group','groups', 'groupdict','start', 'end', 'span',]
}

2

আমি সত্যিই উপরের সমস্ত উত্তর শ্রদ্ধা। আমার মতামত থেকে হ্যাঁ! নিশ্চিতরূপে, বার বার, পুনরায় এবং পুনরায় সংকলনের পরিবর্তে re.compile ব্যবহার করা ভাল।

Re.compile ব্যবহার করা আপনার কোডটিকে আরও গতিশীল করে তোলে, কারণ আপনি আবার কম্পাইল করে এবং অগাইন না করে ইতিমধ্যে সংকলিত রেজেক্স কল করতে পারেন। এই জিনিসটি ক্ষেত্রে আপনার উপকার করে:

  1. প্রসেসর প্রচেষ্টা
  2. সময় জটিলতা।
  3. রেজেক্সকে ইউনিভার্সাল করে তোলে (
  4. এবং আপনার প্রোগ্রামটি দুর্দান্ত দেখায়।

উদাহরণ:

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

ফাইন্ডাল মধ্যে ব্যবহার

 find_alpha_numeric_string.findall(example_string)

অনুসন্ধানে ব্যবহার করা হচ্ছে

  find_alpha_numeric_string.search(example_string)

একইভাবে আপনি এটি ব্যবহার করতে পারেন: ম্যাচ এবং সাবস্টিটিউট


1

এটা একটা ভালো প্রশ্ন। আপনি প্রায়শই দেখেন লোকজন বিনা কারণেই পুনরায় কম্পিউটার ব্যবহার করে। এটি পাঠযোগ্যতা কমিয়ে দেয়। তবে নিশ্চিত যে প্রচুর বার সংকলন করার সময় এক্সপ্রেশনটির জন্য ডাকা হয়। আপনি যখন এটি কোনও লুপে বা এরকম বারবার বারবার ব্যবহার করেন।

এটি প্রোগ্রামিং সম্পর্কে সমস্ত কিছুই (আসলে জীবনের প্রতিটি জিনিস) এর মতো। সাধারণ জ্ঞান প্রয়োগ করুন।


আমি আমার সংক্ষিপ্ত ঝাঁকুনির মধ্য দিয়ে যতদূর বলতে পারি, সংক্ষেপে পাইথন রে ডটকম ()) ব্যতীত ব্যবহারের কথা উল্লেখ করে নি, যা আমাকে কৌতূহলী করেছিল।
ম্যাট

রেজেক্স অবজেক্ট প্রসঙ্গে আরও একটি অবজেক্ট যুক্ত করে। যেমনটি আমি বলেছি, অনেকগুলি পরিস্থিতি রয়েছে যেখানে re.compile () এর স্থান রয়েছে। ওপি প্রদত্ত উদাহরণ তাদের মধ্যে একটিও নয়।
পিইজেড

1

(মাস পরে) আপনার নিজের ক্যাশে পুনরায় ম্যাচের চারপাশে যুক্ত করা সহজ, বা এই বিষয়ে অন্য কিছু -

""" 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 ...

একটি উইবনি, এটি যদি সুন্দর হয় না: ক্যাশেহিন্ট (আকার =), ক্যাচইনফো () -> আকার, হিট, নকল ...


1

ফ্লাই-অন-ফ্লাই কম্পাইল করে একটি সংকলিত রেইজেক্স বারের প্রচুর অভিজ্ঞতা অর্জন করেছি, এবং কোনও অনুভূতিগত পার্থক্য লক্ষ্য করিনি

গৃহীত উত্তরের ভোটগুলি অনুমানের দিকে নিয়ে যায় যে @ ট্রিপটিচ যা বলেছেন তা সব ক্ষেত্রেই সত্য। এটি অগত্যা সত্য নয়। একটি বড় পার্থক্য হ'ল যখন আপনাকে সিদ্ধান্ত নিতে হয় যে কোনও ফাংশনের প্যারামিটার হিসাবে একটি রেজেক্স স্ট্রিং বা একটি সংকলিত রেজেক্স অবজেক্ট গ্রহণ করবেন কিনা:

>>> 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

আপনার রেজেেক্সগুলি পুনরায় ব্যবহারের প্রয়োজন হলে সংকলন করা সর্বদা ভাল।

উপরের টাইমিটের উদাহরণটি নোট করুন যখন কোনও ম্যাচের জন্য প্রয়োজনীয় হয় তখন "অন-দ্য ফ্লাই" বনাম "আমদানির সময় একবার" সংকলিত রেইগেক্স অবজেক্টের সিমুলেট করে।


1

বিকল্প উত্তর হিসাবে, আমি দেখতে পাচ্ছি যে এর আগে এর আগে উল্লেখ করা হয়নি, আমি এগিয়ে গিয়ে পাইথন 3 ডক্সকে উদ্ধৃত করব :

আপনার কি এই মডিউল-স্তরের ফাংশনগুলি ব্যবহার করা উচিত, না আপনার প্যাটার্নটি পাওয়া উচিত এবং এর পদ্ধতিগুলি নিজে কল করা উচিত? আপনি যদি কোনও লুপের মধ্যে একটি রেজিক্স অ্যাক্সেস করেন তবে প্রাক-সংকলন এটি কয়েকটি ফাংশন কলগুলি সংরক্ষণ করবে। লুপগুলির বাইরে, অভ্যন্তরীণ ক্যাশে খুব বেশি পার্থক্য নেই thanks


1

অনুরোধre.compile হিসাবে এখানে 50 গুণ বেশি দ্রুত ব্যবহার করার উদাহরণ রয়েছে ।

পয়েন্টটি ঠিক উপরের মন্তব্যে যেমনটি করেছি ঠিক তেমনই, যথা, re.compileযখন আপনার ব্যবহার যেমন সংকলন ক্যাশে থেকে বেশি উপকার না পান তখন ব্যবহার করা একটি উল্লেখযোগ্য সুবিধা হতে পারে। এটি অন্তত একটি নির্দিষ্ট ক্ষেত্রে ঘটে (যে আমি অনুশীলনে নেমেছি), যখন নীচের সমস্তগুলি সত্য হয়:

  • আপনার কাছে প্রচুর রেগেক্স প্যাটার্ন রয়েছে (এর চেয়ে বেশি re._MAXCACHE, যার ডিফল্ট বর্তমানে 512) এবং and
  • আপনি এই রেজিেক্সগুলি অনেক সময় ব্যবহার করেন এবং
  • আপনি একই প্যাটার্নের ক্রমাগত ব্যবহারগুলি re._MAXCACHEঅন্যান্য রেগেক্সের চেয়ে বেশি আলাদা করে আলাদা করে রেখেছেন, যাতে প্রত্যেকে পরের ব্যবহারের মধ্যে ক্যাশে থেকে সরে যায়।
import re
import time

def setup(N=1000):
    # Patterns 'a.*a', 'a.*b', ..., 'z.*z'
    patterns = [chr(i) + '.*' + chr(j)
                    for i in range(ord('a'), ord('z') + 1)
                    for j in range(ord('a'), ord('z') + 1)]
    # If this assertion below fails, just add more (distinct) patterns.
    # assert(re._MAXCACHE < len(patterns))
    # N strings. Increase N for larger effect.
    strings = ['abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'] * N
    return (patterns, strings)

def without_compile():
    print('Without re.compile:')
    patterns, strings = setup()
    print('searching')
    count = 0
    for s in strings:
        for pat in patterns:
            count += bool(re.search(pat, s))
    return count

def without_compile_cache_friendly():
    print('Without re.compile, cache-friendly order:')
    patterns, strings = setup()
    print('searching')
    count = 0
    for pat in patterns:
        for s in strings:
            count += bool(re.search(pat, s))
    return count

def with_compile():
    print('With re.compile:')
    patterns, strings = setup()
    print('compiling')
    compiled = [re.compile(pattern) for pattern in patterns]
    print('searching')
    count = 0
    for s in strings:
        for regex in compiled:
            count += bool(regex.search(s))
    return count

start = time.time()
print(with_compile())
d1 = time.time() - start
print(f'-- That took {d1:.2f} seconds.\n')

start = time.time()
print(without_compile_cache_friendly())
d2 = time.time() - start
print(f'-- That took {d2:.2f} seconds.\n')

start = time.time()
print(without_compile())
d3 = time.time() - start
print(f'-- That took {d3:.2f} seconds.\n')

print(f'Ratio: {d3/d1:.2f}')

আমি আমার ল্যাপটপটিতে পাই ফলাফল উদাহরণ (পাইথন 3.7.7):

With re.compile:
compiling
searching
676000
-- That took 0.33 seconds.

Without re.compile, cache-friendly order:
searching
676000
-- That took 0.67 seconds.

Without re.compile:
searching
676000
-- That took 23.54 seconds.

Ratio: 70.89

timeitপার্থক্যটি একেবারে সূক্ষ্ম হওয়ায় আমি মাথা ঘামাইনি, তবে আমি প্রতিবারই গুণগতভাবে অনুরূপ সংখ্যা পেয়েছি। মনে রাখবেন যে re.compileএকই ছাড়াই , একই রেজেক্সকে একাধিকবার ব্যবহার করা এবং পরেরটির দিকে এগিয়ে যাওয়া খুব খারাপ ছিল না (কেবলমাত্র 2 গুণ বেশি ধীর গতিতে re.compile) তবে অন্য ক্রমে (অনেকগুলি রেজেক্সের মধ্য দিয়ে লুপিং করা) এটি উল্লেখযোগ্যভাবে খারাপ is , প্রত্যাশিত. এছাড়াও, ক্যাশের আকার বাড়ানোও কাজ করে: কেবল উপরের দিকে সেট re._MAXCACHE = len(patterns)করা setup()(অবশ্যই আমি আন্ডারস্কোর সহ নামগুলি প্রাইভেট "উত্পাদনে এ জাতীয় জিনিসগুলি করার পরামর্শ দিই না) ২৩ সেকেন্ড পিছনে back ০.7 সেকেন্ডে নেমে যায়, এটিও আমাদের বোঝার সাথে মেলে।


পিএস: আমি যদি আমার পুরো কোডটিতে কেবলমাত্র 3 রেজেক্স প্যাটার্ন ব্যবহার করি, সেগুলির প্রত্যেকটি ব্যবহৃত হয় (কোনও নির্দিষ্ট আদেশ ছাড়াই) কয়েকবার সময়, রেজেক্স ক্যাশে প্রাক-কম্পাইলড রেজেক্সটি স্বয়ংক্রিয়ভাবে রাখবে, তা কি ঠিক?
বাসজ

@ বাসজ আমি মনে করি আপনি এটি চেষ্টা করে দেখতে পারেন :) তবে উত্তরটি, আমি বেশ নিশ্চিত, হ্যাঁ: এ ক্ষেত্রে কেবলমাত্র অতিরিক্ত ব্যয় হ'ল ক্যাশে কেবল প্যাটার্নটি অনুসন্ধান করা । এটিও নোট করুন যে ক্যাশেটি বিশ্বব্যাপী (মডিউল-স্তর), সুতরাং নীতিগতভাবে আপনার মধ্যে কিছু নির্ভরতা গ্রন্থাগার আপনার মধ্যে রেগেক্স অনুসন্ধান করতে পারে, সুতরাং আপনার প্রোগ্রামটি কেবল কখনও 3 (বা যত সংখ্যক সংখ্যক) রেজেক্স ব্যবহার করে তা পুরোপুরি আত্মবিশ্বাস পোষণ করা শক্ত fully নিদর্শনগুলি, তবে তা অন্যথায় হওয়া খুব অদ্ভুত হবে :)
শ্রীভাতসার

0

দ্বিতীয় সংস্করণ ব্যবহার করার সময় ব্যবহারের আগে নিয়মিত এক্সপ্রেশনগুলি সংকলিত হয়। আপনি যদি এটি বহুবার নির্বাহ করতে যাচ্ছেন তবে প্রথমে এটি সংকলন করা ভাল। প্রতিবার সংকলন না করে আপনি যদি এক বারের জন্য ম্যাচ করেন তবে ভাল।


0

যোগ্যতা / জ্ঞানীয় লোড অগ্রাধিকার

আমার কাছে প্রধান লাভ যে আমি শুধুমাত্র মনে রাখা, এবং পড়া, প্রয়োজন এক - জটিল Regex এপিআই সিনট্যাক্স আকারে <compiled_pattern>.method(xxx)বরং যে এর চেয়ে ফর্ম এবংre.func(<pattern>, xxx) ফর্ম।

re.compile(<pattern>)অতিরিক্ত boilerplate, একটি বিট, সত্য।

কিন্তু যেখানে রেজেক্স উদ্বিগ্ন, সেই অতিরিক্ত সংকলন পদক্ষেপটি জ্ঞানীয় বোঝার একটি বড় কারণ হওয়ার সম্ভাবনা কম। এবং প্রকৃতপক্ষে, জটিল নিদর্শনগুলিতে, আপনি এরপরে যে রেইগেক্স পদ্ধতিতে অনুরোধ করছেন তার থেকে পৃথকীকরণ থেকে আপনি স্পষ্টতা অর্জন করতে পারেন।

আমি প্রথমে রেজিএক্স 101 এর মতো কোনও ওয়েবসাইটে বা এমনকি একটি পৃথক ন্যূনতম পরীক্ষার স্ক্রিপ্টে জটিল প্যাটার্নগুলির সাথে ঝাঁকুনির ঝোঁক রাখি, তারপরে এগুলি আমার কোডে আনুন, সুতরাং এর ব্যবহার থেকে ঘোষণাটি পৃথক করা আমার কর্মপ্রবাহকেও ফিট করে।


-1

আমি অনুপ্রাণিত করতে চাই যে প্রাক-সংকলনটি ধারণামূলকভাবে এবং 'স্বাক্ষরিতভাবে' উভয়ই ('साक्षিত প্রোগ্রামিং'-এর মতো) উপকারী। এই কোড স্নিপেট দেখুন

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এক লাইনে সমস্ত পাওয়ার উপায়কে সঙ্কুচিত করেছিলাম । এই কোডটির অসুবিধা হ'ল এটি TYPOলাইব্রেরি অবজেক্টের আজীবন যা কিছু হোক তার জন্য এটি একটি সামান্য স্মৃতি দখল করে ; সুবিধাটি হ'ল কোনও ফুবার অনুসন্ধান করার সময় আপনি দুটি ফাংশন কল এবং দুটি শ্রেণির অভিধানের খোঁজ নিয়ে সরে যাবেন। কতটি রেগেক্সেস ক্যাশে হয়েছে 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 ) )

আমি সহজেই স্বীকার করি যে আমার স্টাইলটি অজগরটির জন্য অত্যন্ত অস্বাভাবিক, সম্ভবত বিতর্কযোগ্যও। তবে উদাহরণটিতে উদাহরণস্বরূপ যে পাইথনটি বেশিরভাগ ক্ষেত্রে কীভাবে ব্যবহৃত হয় তার সাথে আরও মিল রয়েছে, একটি একক ম্যাচ করার জন্য আমাদের অবশ্যই কোনও অবজেক্ট ইনস্ট্যান্ট করতে হবে, তিনটি উদাহরণস্বরূপ অভিধান করা উচিত এবং তিনটি ফাংশন কল করা উচিত; অতিরিক্তভাবে, আমরা প্রবেশ করতে পারেre 100 টিরও বেশি রেগেক্স ব্যবহার করার সময় ক্যাশে সমস্যায় পড়তে পারি। এছাড়াও, নিয়মিত এক্সপ্রেশনটি মেথড বডিটির ভিতরে লুকিয়ে যায় যা বেশিরভাগ সময় এই জাতীয় ধারণা নয়।

এটি বলা যেতে পারে যে পদক্ষেপের প্রতিটি উপসেট --- লক্ষ্যবস্তু, এলিজযুক্ত আমদানির বিবৃতি; প্রযোজ্য এলিয়জড পদ্ধতি; ফাংশন কলগুলি এবং অবজেক্ট অভিধানের হুকুম হ্রাস --- গণনা এবং ধারণাগত জটিলতা হ্রাস করতে সহায়তা করে।


2
ডব্লিউটিএফ। আপনি কেবল একটি পুরানো, উত্তর প্রশ্নের সন্ধান করেন না। আপনার কোডটি অ-প্রতিচ্ছবিযুক্ত এবং অনেক স্তরের ক্ষেত্রেও ভুল - (অব) ক্লাসের নাম যেখানে স্পেসিফিকেশন , শ্রেণীর নাম ইত্যাদিকে বড় করে দেওয়া হয় সেই জায়গাগুলি হিসাবে ক্লাস ব্যবহার করে ... আরও ভাল বাস্তবায়নের জন্য পেস্টবিন . com/ আইটিএক্সএক্স ওয়েেন দেখুন । আপনার ব্যবহৃত রেজেক্সটি ভেঙে গেছে তা উল্লেখ করার দরকার নেই। সামগ্রিকভাবে, -1

2
দোষী। এটি একটি পুরানো প্রশ্ন, তবে মন্থর হবেনা - একটি ধীরগতিতে কথোপকথনে # 100 হওয়া। প্রশ্নটি বন্ধ করা হয়নি। আমি সতর্ক করে দিয়েছিলাম যে আমার কোডটি কিছু স্বাদের বিরোধী হতে পারে। আমি মনে করি যদি আপনি এটিকে অজগরটিতে কী করণীয় তার নিছক প্রদর্শন হিসাবে দেখতে পেতেন, যেমন: আমরা যদি সমস্ত কিছু গ্রহণ করি, আমরা believeচ্ছিক হিসাবে বিশ্বাস করি, এবং তারপরে যেকোন উপায়ে একসাথে ঝাঁকুনি দিয়ে দেখি, জিনিসগুলি কীভাবে দেখতে পারা যায় পাওয়া? আমি নিশ্চিত যে আপনি এই সমাধানটির গুণাবলী এবং বিভেদগুলি বুঝতে পারবেন এবং আরও স্পষ্টভাবে অভিযোগ করতে পারেন। অন্যথায় আমার অবশ্যই আপনার ভুলের দাবিটি পিইপি 800 এর চেয়ে কিছুটা বেশি নির্ভর করে
প্রবাহিত হবে

2
না, এটি পিইপি 8 সম্পর্কে নয়। এটি কেবল কনভেনশনগুলির নামকরণ, এবং আমি সেগুলি অনুসরণ না করার জন্য কখনই হ্রাস করব না। আমি আপনাকে হ্রাস করেছি কারণ আপনি যে কোডটি দেখিয়েছেন তা কেবল খারাপভাবে লেখা হয়েছে। এটি বিনা কারণে কনভেনশন এবং আইডিয়মগুলিকে অস্বীকার করে এবং এটি অপরিবর্তনীয় অপ্টিমাইজেশনের একটি অবতার: আপনার বাধা হয়ে দাঁড়ানোর জন্য অন্য সমস্ত কোডের বাইরে আপনাকে জীবন্ত দিবালোকের অনুকূলতা বজায় রাখতে হবে, এবং তারপরেও আমি যে তৃতীয় পুনর্লিখনটি দিয়েছি তা সংক্ষিপ্ত, আরও মূর্খবাদী এবং আপনার যুক্তি দ্বারা ঠিক তত দ্রুত (বৈশিষ্ট্য অ্যাক্সেসের একই সংখ্যা)।

"খারাপ লেখা" - ঠিক কেন? "সম্মেলন এবং রীতিমতো প্রতিবন্ধকতা" - আমি আপনাকে সতর্ক করে দিয়েছি। "অকারণে" - হ্যাঁ আমার একটি কারণ আছে: জটিলতা কোনও উদ্দেশ্য করে না এমন সরলকরণ; "অকাল অপটিমাইজেশনের অবতার" - আমি এমন একটি প্রোগ্রামিং শৈলীর পক্ষে খুব বেশি যা পাঠযোগ্যতা এবং দক্ষতার ভারসাম্য বেছে নেয়; ওপি "re.compile ব্যবহারের সুবিধার্থে" অনুরোধের জন্য বলেছিল, যা আমি দক্ষতা সম্পর্কে একটি প্রশ্ন হিসাবে বুঝতে পারি। "(অ্যাবি) ক্লাসকে নেমস্পেস হিসাবে ব্যবহার করে" - এটি আপনার শব্দগুলি আপত্তিজনক। শ্রেণিটি রয়েছে তাই আপনার কাছে "স্ব" পয়েন্ট অফ রেফারেন্স রয়েছে। আমি এই উদ্দেশ্যে মডিউল ব্যবহার করার চেষ্টা করেছি, ক্লাসগুলি আরও ভাল কাজ করে।
প্রবাহিত করুন

"শ্রেণীর নামগুলি বড় করে তোলা", "না, এটি পিইপি 8 সম্পর্কে নয়" - আপনি সম্ভবত এতটা ক্ষোভের সাথে রাগ করছেন যে আপনি প্রথমে কোনটা বিকার করবেন তা বলতে পারবেন না। "ডাব্লুটিএফ", " ভুল " --- দেখুন আপনি কতটা সংবেদনশীল? আরও উদ্দেশ্যমূলকতা এবং কম ফলস দয়া করে।
প্রবাহিত করুন

-5

আমার বোঝা এই যে দুটি উদাহরণ কার্যকরভাবে সমান। পার্থক্যটি হ'ল প্রথমটিতে, আপনি সংকলিত নিয়মিত এক্সপ্রেশনটি আবার সংকলিত না করে অন্যত্র পুনরায় ব্যবহার করতে পারেন।

আপনার জন্য এখানে একটি রেফারেন্স দেওয়া হয়েছে: http://diveintopython3.ep.io/refactoring.html

সংকলিত প্যাটার্ন অবজেক্টের অনুসন্ধান ফাংশনটিকে 'এম' স্ট্রিং দিয়ে কল করা পুনরায় নিয়মিত এক্সপ্রেশন এবং স্ট্রিং 'এম' উভয়ই পুনরায় অনুসন্ধান করার মতো কাজ সম্পাদন করে। শুধুমাত্র অনেক, অনেক দ্রুত। (আসলে, পুনরায় অনুসন্ধানের ফাংশনটি কেবল নিয়মিত অভিব্যক্তি সংকলন করে এবং ফলস্বরূপ প্যাটার্ন অবজেক্টের অনুসন্ধান পদ্ধতিটি আপনার জন্য কল করে))


1
আমি আপনাকে নিম্নোক্ত করি নি, তবে প্রযুক্তিগতভাবে এটি ভুল: পাইথন যেভাবেই হোক পুনরায়
সংকলন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.