অন্যটি সবচেয়ে বেশি হলে ইফ-এলিফ-এলিফ-অন্য বিবৃতি দেওয়ার সবচেয়ে কার্যকর উপায়?


102

আমি যদি এলিফ-এলিফ-অন্য বিবৃতি পেয়েছি, যেখানে 99% সময়, অন্য বিবৃতিটি কার্যকর করা হয়:

if something == 'this':
    doThis()
elif something == 'that':
    doThat()
elif something == 'there':
    doThere()
else:
    doThisMostOfTheTime()

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

এটি কীভাবে এবং কীভাবে আরও দক্ষতার সাথে করা যেতে পারে তা কি কেউ জানেন বা এটি করার সহজ উপায় এটি কি?


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


4
তিনটি বিশেষ ক্ষেত্রে সাধারণ কিছু মিল রয়েছে কি? উদাহরণস্বরূপ, আপনি if not something.startswith("th"): doThisMostOfTheTime()ক্লজটিতে আরও একটি তুলনা করতে এবং করতে পারেন else
টিম পিটজ্যাকার

4
@ kramer65 যদি যদি / Elif ... এটা ধীর হতে পারে, কিন্তু নিশ্চিত আসলে করা যেমন একটি দীর্ঘ শৃঙ্খল এর প্রফাইল আপনার কোড এবং সর্বোচ্চকরন যাই হোক না কেন অংশ সবচেয়ে সময় লাগে করে শুরু করুন।
জোর্গকা

4
এই তুলনাগুলি কি প্রতি মূল্য অনুসারে একবার সম্পাদন করা হয় something, বা একই তুলনায় একই মানের সাথে একাধিকবার সম্পাদনা করা হয়?
ক্রিস পিটম্যান

উত্তর:


101

কোড...

options.get(something, doThisMostOfTheTime)()

... দেখে মনে হচ্ছে এটি দ্রুত হওয়া উচিত, তবে এটি আসলে if... elif... elseনির্মাণের চেয়ে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে বেড়ে যায় ।

এই উদাহরণগুলি বিবেচনা করুন ...

1.পি

something = 'something'

for i in xrange(1000000):
    if something == 'this':
        the_thing = 1
    elif something == 'that':
        the_thing = 2
    elif something == 'there':
        the_thing = 3
    else:
        the_thing = 4

২.পি

something = 'something'
options = {'this': 1, 'that': 2, 'there': 3}

for i in xrange(1000000):
    the_thing = options.get(something, 4)

3.পি

something = 'something'
options = {'this': 1, 'that': 2, 'there': 3}

for i in xrange(1000000):
    if something in options:
        the_thing = options[something]
    else:
        the_thing = 4

4.পি

from collections import defaultdict

something = 'something'
options = defaultdict(lambda: 4, {'this': 1, 'that': 2, 'there': 3})

for i in xrange(1000000):
    the_thing = options[something]

... এবং তারা কতটা সিপিইউ ব্যবহার করে তা নোট করুন ...

1.py: 160ms
2.py: 170ms
3.py: 110ms
4.py: 100ms

... ব্যবহারকারীর সময় থেকে time(1)

অপশন # 4 এর প্রতিটি স্বতন্ত্র কী মিসের জন্য একটি নতুন আইটেম যুক্ত করার অতিরিক্ত মেমরির ওভারহেড রয়েছে, সুতরাং আপনি যদি সীমাহীন সংখ্যক স্বতন্ত্র কী মিস করতে চান তবে আমি বিকল্প # 3 নিয়ে যাব, যা এখনও একটি উল্লেখযোগ্য উন্নতি মূল নির্মাণ।


4
অজগর একটি সুইচ স্টেটমেন্ট আছে?
নাথান হাইফিল্ড

উগ ... ঠিক এখন পর্যন্ত আমি পাইথনটি সম্পর্কে একমাত্র শুনেছি যে আমি যত্ন করি না ... অনুমান করা দরকার যে কিছু হবে
নাথান হ্যাফিল্ড

4
-1 আপনি বলছেন যে একটি ব্যবহার dictকরা ধীর গতিযুক্ত, কিন্তু তারপরে আপনার সময়গুলি প্রকৃতপক্ষে দেখায় যে এটি দ্বিতীয় দ্রুততম বিকল্প।
মার্সিন

11
@ মার্সিন আমি বলছি যে dict.get()এটি ধীর, যা 2.py- এটি সবার থেকে ধীর।
আয়া

রেকর্ডটির জন্য, তিনটি এবং চারটি নির্মাণের ব্যতীত / চেষ্টা ব্যতীত মূল ত্রুটি ক্যাপচার করার চেয়ে নাটকীয়ভাবে দ্রুত হয়।
জেফ

80

আমি একটি অভিধান তৈরি করব:

options = {'this': doThis,'that' :doThat, 'there':doThere}

এখন শুধু ব্যবহার করুন:

options.get(something, doThisMostOfTheTime)()

ডিকটিতে যদি somethingপাওয়া না যায় তবে ডিফল্ট মানটি ফিরিয়ে দেবেoptionsdict.getdoThisMostOfTheTime

কিছু সময়ের তুলনা:

লিপি:

from random import shuffle
def doThis():pass
def doThat():pass
def doThere():pass
def doSomethingElse():pass
options = {'this':doThis, 'that':doThat, 'there':doThere}
lis = range(10**4) + options.keys()*100
shuffle(lis)

def get():
    for x in lis:
        options.get(x, doSomethingElse)()

def key_in_dic():
    for x in lis:
        if x in options:
            options[x]()
        else:
            doSomethingElse()

def if_else():
    for x in lis:
        if x == 'this':
            doThis()
        elif x == 'that':
            doThat()
        elif x == 'there':
            doThere()
        else:
            doSomethingElse()

ফলাফল:

>>> from so import *
>>> %timeit get()
100 loops, best of 3: 5.06 ms per loop
>>> %timeit key_in_dic()
100 loops, best of 3: 3.55 ms per loop
>>> %timeit if_else()
100 loops, best of 3: 6.42 ms per loop

জন্য 10**5অবর্তমান কী ও 100 বৈধ কী ::

>>> %timeit get()
10 loops, best of 3: 84.4 ms per loop
>>> %timeit key_in_dic()
10 loops, best of 3: 50.4 ms per loop
>>> %timeit if_else()
10 loops, best of 3: 104 ms per loop

সুতরাং, একটি সাধারণ অভিধানের জন্য কীটি ব্যবহার করে পরীক্ষা করা key in optionsএখানে সর্বাধিক দক্ষ উপায়:

if key in options:
   options[key]()
else:
   doSomethingElse()

options = collections.defaultdict(lambda: doThisMostOfTheTime, {'this': doThis,'that' :doThat, 'there':doThere}); options[something]()প্রান্তিকভাবে আরও দক্ষ।
আয়া

দুর্দান্ত ধারণা, তবে পাঠযোগ্য নয়। এছাড়াও আপনি সম্ভবত optionsএটি পুনর্নির্মাণ এড়ানোর জন্য ডিককে আলাদা করতে চাইবেন , যার ফলে যুক্তির অংশটি (কিন্তু সমস্ত নয়) ব্যবহারের দিক থেকে অনেক দূরে সরিয়ে নেওয়া উচিত। তবুও, দুর্দান্ত কৌশল!
অ্যান্ডারস জোহানসন

7
আপনি কি জানেন যে এটি আরও দক্ষ কিনা? আমার অনুমান যে এটি কোনও শর্তযুক্ত চেক বা তিনটির পরিবর্তে হ্যাশ লুচিং করছে তাই এটি ধীর। প্রশ্নটি কোডের সংযোগের চেয়ে দক্ষতার বিষয়ে।
ব্রায়ান ওকলে

4
@ ব্রায়ানওকলে আমি কিছু সময়ের তুলনা যুক্ত করেছি।
অশ্বিনী চৌধুরী চৌধুরী

4
আসলে এটি করা আরও দক্ষ হওয়া উচিত try: options[key]() except KeyError: doSomeThingElse()(যেহেতু if key in options: options[key]()আপনি key
অভিধানটি

9

আপনি কি পাইপি ব্যবহার করতে পারবেন?

আপনার মূল কোডটি রাখা কিন্তু এটি পাইপিতে চালানো আমার জন্য 50x গতি বাড়িয়ে দেয়।

সিপিথন:

matt$ python
Python 2.6.8 (unknown, Nov 26 2012, 10:25:03)
[GCC 4.2.1 Compatible Apple Clang 3.0 (tags/Apple/clang-211.12)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> from timeit import timeit
>>> timeit("""
... if something == 'this': pass
... elif something == 'that': pass
... elif something == 'there': pass
... else: pass
... """, "something='foo'", number=10000000)
1.728302001953125

পাইপাই:

matt$ pypy
Python 2.7.3 (daf4a1b651e0, Dec 07 2012, 23:00:16)
[PyPy 2.0.0-beta1 with GCC 4.2.1] on darwin
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``a 10th of forever is 1h45''
>>>>
>>>> from timeit import timeit
>>>> timeit("""
.... if something == 'this': pass
.... elif something == 'that': pass
.... elif something == 'there': pass
.... else: pass
.... """, "something='foo'", number=10000000)
0.03306388854980469

হাই ফোজ টিপ জন্য ধন্যবাদ. আসলে আমি ইতিমধ্যে পাইপি ব্যবহার করছি (এটি ভালবাসি) তবে এখনও আমার গতির উন্নতি প্রয়োজন .. :)
kramer65

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

4

এখানে একটি অভিধানে অনুবাদিত গতিশীল অবস্থার সাথে একটি এর উদাহরণ।

selector = {lambda d: datetime(2014, 12, 31) >= d : 'before2015',
            lambda d: datetime(2015, 1, 1) <= d < datetime(2016, 1, 1): 'year2015',
            lambda d: datetime(2016, 1, 1) <= d < datetime(2016, 12, 31): 'year2016'}

def select_by_date(date, selector=selector):
    selected = [selector[x] for x in selector if x(date)] or ['after2016']
    return selected[0]

এটি একটি উপায়, তবে এটি করার পক্ষে সর্বাধিক পাইথোনিক উপায় নাও হতে পারে কারণ পাইথনে যাদের পক্ষে সাবলীল নয় তারা কম পাঠযোগ্য।


0

execসুরক্ষার কারণে লোকেরা সতর্ক করে , তবে এটি এটির জন্য আদর্শ বিষয়।
এটি একটি সহজ রাষ্ট্র মেশিন।

Codes = {}
Codes [0] = compile('blah blah 0; nextcode = 1')
Codes [1] = compile('blah blah 1; nextcode = 2')
Codes [2] = compile('blah blah 2; nextcode = 0')

nextcode = 0
While True:
    exec(Codes[nextcode])
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.