পাইথনে সুইচ স্টেটমেন্টের প্রতিস্থাপন?


1718

আমি পাইথনে একটি ফাংশন লিখতে চাই যা একটি ইনপুট সূচকের মানের ভিত্তিতে বিভিন্ন স্থির মান দেয় returns

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


77
সম্পর্কিত পিইপি, গুইডো নিজেই লিখেছেন: পিইপি 3103
সিবিবি

28
@chb সেই পিইপি-তে, গিডো উল্লেখ করেনি যে যদি / এলিফ চেইনগুলিও ত্রুটির উত্সর্গীয় উত্স হয়। এটি একটি খুব ভঙ্গুর নির্মাণ।
ব্রুস

15
এখানে সমস্ত সমাধান থেকে অনুপস্থিত হ'ল সদৃশ কেস মানগুলির সনাক্তকরণ । ব্যর্থ-দ্রুত নীতি হিসাবে, এটি পারফরম্যান্স বা পতনের বৈশিষ্ট্যের চেয়ে আরও বেশি গুরুত্বপূর্ণ ক্ষতি হতে পারে।
বব স্টেইন

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

3
@ মালিকএ.রুমি ফ্রেজিলে কন্সট্রাক্ট, ঠিক যেমন কিছুক্ষণের জন্য লুপটি একটি ভঙ্গুর কনস্ট্রাক্ট হয় যদি আপনি এটি ... এর ... কী করার জন্য এটি ব্যবহার করার চেষ্টা করেন। আপনি কি লুপগুলি ব্যবহারের জন্য প্রোগ্রামারগুলিকে দুর্বল বলছেন? লুপগুলি আসলে তাদের যা প্রয়োজন তা হ'ল। তবে লুপগুলি স্পষ্ট অভিপ্রায় দেখায়, অর্থহীন বয়লারপ্লেট সংরক্ষণ করুন এবং শক্তিশালী বিমূর্ততা তৈরি করার সুযোগ দিন।
ব্রুস 6

উত্তর:


1486

আপনি একটি অভিধান ব্যবহার করতে পারেন:

def f(x):
    return {
        'a': 1,
        'b': 2,
    }[x]

99
এক্স না পাওয়া গেলে কী হয়?
নিক

46
@ নিক: আপনি ডিফল্টর্টিক্ট ব্যবহার করতে পারেন
এলি বেন্ডারস্কি

384
পারফরম্যান্সের সমস্যা হলে আমি ডিকটি ফাংশনের বাইরে রাখার পরামর্শ দেব, সুতরাং এটি প্রতিটি ফাংশন কলটিতে
ডিকটি

56
@ এলিবেেন্ডারস্কি, getপদ্ধতিটি ব্যবহার করা সম্ভবত collections.defaultdictএই ক্ষেত্রে ব্যবহারের চেয়ে বেশি স্বাভাবিক normal
মাইক গ্রাহাম

27
@ নিক, একটি ব্যতিক্রম নিক্ষেপ করা হয় }.get(x, default)instead পরিবর্তে যদি কোনও ডিফল্ট থাকে — (দ্রষ্টব্য: আপনি যদি সুইচ স্টেটমেন্টটি ডিফল্ট ছেড়ে দেন তবে এটি যা ঘটবে তার চেয়ে অনেক সুন্দর!)
মাইক গ্রাহাম

1374

আপনি যদি ডিফল্ট চান তবে আপনি অভিধান get(key[, default])পদ্ধতিটি ব্যবহার করতে পারেন :

def f(x):
    return {
        'a': 1,
        'b': 2
    }.get(x, 9)    # 9 is default if x not found

11
'ক' এবং 'বি' ম্যাচ 1, এবং 'সি' এবং 'ডি' ম্যাচ 2 হলে কী হবে?
জন মে

13
@ জেএম: আচ্ছা, স্পষ্টতই অভিধানের দৃষ্টিকোণগুলি পতনের মাধ্যমে সমর্থন করে না don't আপনি একটি ডাবল অভিধান অনুসন্ধান করতে পারে। উদাহরণস্বরূপ, 'এ' এবং 'বি' পয়েন্টটি উত্তর 1 এবং 'সি' এবং 'ডি' পয়েন্টটি উত্তর 2, যা দ্বিতীয় অভিধানে রয়েছে।
নিক

3
এটি একটি ডিফল্ট মান পাস করা ভাল
HaTiMSuM

এই পদ্ধতির সাথে একটি সমস্যা রয়েছে, প্রথমে আপনি যখন কল করবেন তখন আপনি ডেকে তৈরি করতে যাচ্ছেন দ্বিতীয় আপনার যদি আরও জটিল মান থাকে তবে আপনি ব্যতিক্রম ব্যতীত পেতে পারেন। যদি এক্স টিউপল হয় এবং আমরা এই x = ('a') ডিফ এফ (এক্স) এর মতো কিছু করতে চাই: ফিরে {'এ': x [0], 'বি': এক্স [1] get .get ( x [0], 9) এটি সূচিপত্র বাড়িয়ে তুলবে
হাইম শালোম

2
@ ইদান: প্রশ্নটি ছিল স্যুইচটির প্রতিলিপি করা। আমি নিশ্চিত যে আমি বিজোড় মানগুলি রাখার চেষ্টা করলে আমি এই কোডটিও ভেঙে ফেলতে পারি। হ্যাঁ, এটি পুনরায় তৈরি করা হবে তবে এটি ঠিক করা সহজ।
নিক

394

আমি সবসময় এইভাবে এটি করতে পছন্দ করি

result = {
  'a': lambda x: x * 5,
  'b': lambda x: x + 7,
  'c': lambda x: x - 2
}[value](x)

এখান থেকে


16
ডিফল্ট হ্যান্ডেল করতে get () এর সাথে মিলিত দুর্দান্ত পদ্ধতিটিও আমার সেরা পছন্দ
drAlberT

27
এই ক্ষেত্রে ল্যাম্বডা ব্যবহার করা ভাল ধারণা নয় কারণ ল্যাম্বডাটি প্রতিবার অভিধান তৈরি করার সময় বলা হয়।
আশের

13
দুঃখজনকভাবে এটি হ'ল নিকটতম লোকেরা। যে পদ্ধতিগুলি .get()(বর্তমান সর্বোচ্চ উত্তরের মতো) ব্যবহার করা হয় তাদের প্রেরণের আগে সমস্ত সম্ভাবনাটি আগ্রহের সাথে মূল্যায়ন করতে হবে এবং তাই কেবল (কেবল খুব নয়) অত্যন্ত অদক্ষ নয় এবং এর পার্শ্ব-প্রতিক্রিয়াও থাকতে পারে না; এই উত্তরটি এই সমস্যাটির আশেপাশে আসে তবে এটি আরও ভার্জোজ ose আমি / এলিফ / অন্যথায় কেবল ব্যবহার করব এবং এমনকি যারা 'কেস' হিসাবে লিখতে ঠিক সময় নেয়।
নিনজাগেকো

13
এটি কেবলমাত্র ফলাফলগুলির মধ্যে একটিরও ফিরিয়ে দিলেও, সমস্ত ক্ষেত্রে সব সময়ই সমস্ত ফাংশন / ল্যাম্বডাসকে মূল্যায়ন করবে না?
slf

23
@ এসএলএফ নং, যখন নিয়ন্ত্রণ প্রবাহ কোডের এই অংশে পৌঁছায়, এটি 3 টি ফাংশন তৈরি করবে (3 ল্যাম্বডাস ব্যবহারের মাধ্যমে) এবং তারপরে মান হিসাবে 3 টি ফাংশন সহ একটি অভিধান তৈরি করবে, তবে সেগুলি অবরুদ্ধ থাকবে ( মূল্যায়ন কিছুটা দ্বিপাক্ষিক সেই প্রসঙ্গে) প্রথমে। তারপরে ডিকশনারিটি এর মাধ্যমে সূচিকৃত হয় [value]যা 3 টি ফাংশনগুলির মধ্যে কেবল একটিতে ফিরে আসবে (ধরে valueনেওয়া 3 টির মধ্যে একটি)। ফাংশনটি এখনও সেই সময়ে ডাকা হয়নি। তারপরে (x)সবেমাত্র ফাংশনটিকে xআর্গুমেন্ট হিসাবে কল করে (এবং ফলাফলটি যায় result) the অন্যান্য 2 ফাংশন কল করা হবে না।
blubberdiblub

353

অভিধান পদ্ধতি (যা আমি সত্যিই মত BTW), তবে আপনাকে ব্যবহার করতে পারেন ছাড়াও if- elif- elseপ্রাপ্ত switch/ case/ defaultকার্যকারিতা:

if x == 'a':
    # Do the thing
elif x == 'b':
    # Do the other thing
if x in 'bc':
    # Fall-through by not using elif, but now the default case includes case 'a'!
elif x in 'xyz':
    # Do yet another thing
else:
    # Do the default

অবশ্যই এটি স্যুইচ / কেস হিসাবে অভিন্ন নয় - আপনি breakবিবৃতি ছেড়ে দেওয়ার মতো সহজেই পড়ে যেতে পারেন না তবে আপনি আরও জটিল পরীক্ষা করতে পারেন। এর বিন্যাসটি নেস্টেড এসগুলির একটি সিরিজের চেয়ে সুন্দর if, যদিও এটি কার্যকরীভাবে এটি কাছাকাছি।


51
আমি সত্যিই এটি পছন্দ করবো, এটি স্ট্যান্ডআর্ট ল্যাংগুয়েজ কনস্ট্রাক্ট ব্যবহার করে এবং কোনও মিলের কেস না পাওয়া গেলে কী-ইরার ফেলে দেয় না
শহীদগ্লাবিটজ

7
আমি অভিধান / getউপায় সম্পর্কে ভেবেছিলাম , তবে মানক উপায়টি আরও বেশি পঠনযোগ্য।
মার্টিন থোমা

2
@ সুমিউসার তবে তারা "ওভারল্যাপ" করতে পারে এমন একটি বৈশিষ্ট্য। আপনি কেবল নিশ্চিত করেছেন যে ক্রমটি ম্যাচগুলি হওয়া উচিত সেই অগ্রাধিকারটি। পুনরাবৃত্তি এক্স হিসাবে: ঠিক x = the.other.thingআগে একটি করুন । সাধারণত, আপনার যদি একটি একক, একাধিক এলিফ এবং অন্য কোনও একক থাকে, এটি বোঝা সহজ।
ম্যাথু শিংকেল

7
চমৎকার, যদিও "এলিফ ব্যবহার না করে পড়ে যাওয়া" কিছুটা বিভ্রান্তিকর। এটি সম্পর্কে কী: "মধ্য দিয়ে পড়া" সম্পর্কে ভুলে যান এবং কেবল দুটি হিসাবে গ্রহণ করবেন if/elif/else?
অ্যালোস মাহডাল

7
এছাড়াও মূল্য উল্লেখ যখন ব্যবহার পছন্দ x in 'bc', মন যে রাখতে "" in "bc"হয় True
লোহ্মার আশার

185

স্যুইচ / কেসের জন্য আমার প্রিয় পাইথন রেসিপিটি হ'ল:

choices = {'a': 1, 'b': 2}
result = choices.get(key, 'default')

সংক্ষিপ্ত এবং সাধারণ দৃশ্যের জন্য সহজ।

সি কোডের 11+ লাইনের সাথে তুলনা করুন:

// C Language version of a simple 'switch/case'.
switch( key ) 
{
    case 'a' :
        result = 1;
        break;
    case 'b' :
        result = 2;
        break;
    default :
        result = -1;
}

এমনকি টিপলস ব্যবহার করে আপনি একাধিক ভেরিয়েবল বরাদ্দ করতে পারেন:

choices = {'a': (1, 2, 3), 'b': (4, 5, 6)}
(result1, result2, result3) = choices.get(key, ('default1', 'default2', 'default3'))

16
আমি এটি গ্রহণযোগ্য চেয়ে আরও দৃ answer় উত্তর বলে মনে করি।

3
@ কিছু ব্যবহারকারীর: সি প্রয়োজনীয় যে সমস্ত ক্ষেত্রে ফিরতি মান একই রকম হয় same পাইথন না। আমি পাইথনের এই নমনীয়তাটি হাইলাইট করতে চেয়েছিলাম ঠিক যদি কারওর মতো ব্যবহারের প্রয়োজন হয় এমন পরিস্থিতি ঘটে।
চেইমজি

3
@ কিছু ব্যবহারকারী: ব্যক্তিগতভাবে আমি {} .get (,) পাঠযোগ্য find পাইথন নতুনদের জন্য অতিরিক্ত পাঠযোগ্যতা জন্য আপনি ব্যবহার করতে পারেন default = -1; result = choices.get(key, default)
চেইমজি

4
সি ++ এর 1 লাইনের সাথে তুলনা করুনresult=key=='a'?1:key==b?2:-1
জেসেন

4
@Jasen এক তর্ক করতে পারেন যে আপনার পাশাপাশি পাইথন এক লাইনে এটা করতে পারেন: result = 1 if key == 'a' else (2 if key == 'b' else 'default')। তবে এক লাইনার কি পাঠযোগ্য?
চেইমজি

101
class switch(object):
    value = None
    def __new__(class_, value):
        class_.value = value
        return True

def case(*args):
    return any((arg == switch.value for arg in args))

ব্যবহার:

while switch(n):
    if case(0):
        print "You typed zero."
        break
    if case(1, 4, 9):
        print "n is a perfect square."
        break
    if case(2):
        print "n is an even number."
    if case(2, 3, 5, 7):
        print "n is a prime number."
        break
    if case(6, 8):
        print "n is an even number."
        break
    print "Only single-digit numbers are allowed."
    break

পরীক্ষা:

n = 2
#Result:
#n is an even number.
#n is a prime number.
n = 11
#Result:
#Only single-digit numbers are allowed.

64
এটি নিরাপদ হুমকি নয়। যদি একই সাথে কয়েকটি স্যুইচ হিট হয় তবে সমস্ত সুইচগুলি সর্বশেষ স্যুইচটির মান নেয়।
ফ্রান্সস্কারটিজ

48
@ ফ্রানসেকর্টিজ সম্ভবত থ্রেড নিরাপদ হওয়ার অর্থ এটি নিরাপদ হুমকিও নয়। এটি ভেরিয়েবলের মান হুমকির সম্মুখীন!
Zizouz212

7
থ্রেড সুরক্ষা সমস্যা থ্রেড-লোকাল স্টোরেজ ব্যবহার করে প্রায় কাজ করা যেতে পারে । বা উদাহরণটি ফিরে আসার সাথে সাথে কেস তুলনার জন্য সেই উদাহরণটি ব্যবহার করে একেবারে এড়ানো যায়।
blubberdiblub

6
@ ব্লুবার্ডিব্লুব তবে তারপরে স্ট্যান্ডার্ড ifস্টেটমেন্ট ব্যবহার করা কি আরও দক্ষ নয় ?
wizzwizz4

9
এটি একাধিক ফাংশনে ব্যবহৃত হলে এটিও নিরাপদ নয়। প্রদত্ত উদাহরণে, যদি case(2)ব্লকটি স্যুইচ () ব্যবহার করে এমন কোনও ফাংশন বলে, তারপরে case(2, 3, 5, 7)পরবর্তী কেসটি কার্যকর করার জন্য ইত্যাদি করার সময় এটি অন্য ফাংশন দ্বারা সেট করা স্যুইচ মান ব্যবহার করবে যা বর্তমান স্যুইচ স্টেটমেন্টের দ্বারা সেট করা হয় না। ।
ব্যবহারকারী9876

52

আমার প্রিয় একটি সত্যিই দুর্দান্ত রেসিপি । আপনি সত্যিই এটি পছন্দ করবে। এটি প্রকৃত স্যুইচ কেস স্টেটমেন্টগুলিতে, বিশেষত বৈশিষ্ট্যগুলিতে আমি সর্বাধিক নিকটবর্তী।

class switch(object):
    def __init__(self, value):
        self.value = value
        self.fall = False

    def __iter__(self):
        """Return the match method once, then stop"""
        yield self.match
        raise StopIteration

    def match(self, *args):
        """Indicate whether or not to enter a case suite"""
        if self.fall or not args:
            return True
        elif self.value in args: # changed for v1.5, see below
            self.fall = True
            return True
        else:
            return False

এখানে একটি উদাহরণ:

# The following example is pretty much the exact use-case of a dictionary,
# but is included for its simplicity. Note that you can include statements
# in each suite.
v = 'ten'
for case in switch(v):
    if case('one'):
        print 1
        break
    if case('two'):
        print 2
        break
    if case('ten'):
        print 10
        break
    if case('eleven'):
        print 11
        break
    if case(): # default, could also just omit condition or 'if True'
        print "something else!"
        # No need to break here, it'll stop anyway

# break is used here to look as much like the real thing as possible, but
# elif is generally just as good and more concise.

# Empty suites are considered syntax errors, so intentional fall-throughs
# should contain 'pass'
c = 'z'
for case in switch(c):
    if case('a'): pass # only necessary if the rest of the suite is empty
    if case('b'): pass
    # ...
    if case('y'): pass
    if case('z'):
        print "c is lowercase!"
        break
    if case('A'): pass
    # ...
    if case('Z'):
        print "c is uppercase!"
        break
    if case(): # default
        print "I dunno what c was!"

# As suggested by Pierre Quentel, you can even expand upon the
# functionality of the classic 'case' statement by matching multiple
# cases in a single shot. This greatly benefits operations such as the
# uppercase/lowercase example above:
import string
c = 'A'
for case in switch(c):
    if case(*string.lowercase): # note the * for unpacking as arguments
        print "c is lowercase!"
        break
    if case(*string.uppercase):
        print "c is uppercase!"
        break
    if case('!', '?', '.'): # normal argument passing style also applies
        print "c is a sentence terminator!"
        break
    if case(): # default
        print "I dunno what c was!"

3
আমি প্রতিস্থাপন করবে for case in switch()সঙ্গে with switch() as case, আরো ইন্দ্রিয় তোলে, যেহেতু এটি গুলি প্রয়োজন শুধুমাত্র একবার চালানোর জন্য।
স্কি

4
@ স্কির্ম্যান্টাস: নোটটি যদিও এতে withঅনুমতি দেয় না break, সুতরাং পতনের বিকল্পটি সরিয়ে নেওয়া হয়েছে।
জোনাস শোফার

5
এটি নিজেকে নির্ধারণ করার জন্য আরও বেশি প্রচেষ্টা না করার জন্য ক্ষমা প্রার্থনা: উপরে অনুরূপ উত্তর থ্রেড নিরাপদ নয়। এটা কি?
ডেভিড উইনিস্কি

1
@ ডেভিডউইনিস্কি উপরের থেকে অনুপস্থিত কোড উপাদানগুলি (এবং সম্ভবত অ্যাক্টিস্টেট দ্বারা কপিরাইট) থ্রেড নিরাপদ বলে মনে হচ্ছে।
জেসেন

এর আর একটি সংস্করণ কি এরকম কিছু হবে if c in set(range(0,9)): print "digit" elif c in set(map(chr, range(ord('a'), ord('z')))): print "lowercase"?
এমপ্যাগ

51
class Switch:
    def __init__(self, value):
        self.value = value

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        return False # Allows a traceback to occur

    def __call__(self, *values):
        return self.value in values


from datetime import datetime

with Switch(datetime.today().weekday()) as case:
    if case(0):
        # Basic usage of switch
        print("I hate mondays so much.")
        # Note there is no break needed here
    elif case(1,2):
        # This switch also supports multiple conditions (in one line)
        print("When is the weekend going to be here?")
    elif case(3,4):
        print("The weekend is near.")
    else:
        # Default would occur here
        print("Let's go have fun!") # Didn't use case for example purposes

9
কনটেক্সট ম্যানেজার ব্যবহার করা একটি ভাল সৃজনশীল সমাধান। ); আমি ব্যাখ্যা একটি বিট যুক্ত করার প্রস্তাব দিই চাই এবং হয়ত এই পোস্টে কিছু, ভাল, প্রসঙ্গ দিতে কনটেক্সট পরিচালকের উপর কিছু তথ্য একটি লিঙ্ক
উইল

2
আমি / এলিফ চেইনগুলি বেশি পছন্দ করি না তবে এটি পাইথনের বিদ্যমান বাক্য গঠনটি ব্যবহার করে দেখেছি এমন সমস্ত সমাধানগুলির মধ্যে সৃজনশীল এবং সবচেয়ে কার্যকর উভয়ই।
ব্রুস

2
এটি সত্যিই দুর্দান্ত। একটি প্রস্তাবিত উন্নতি হ'ল valueসুইচ ক্লাসে একটি (সর্বজনীন) সম্পত্তি যুক্ত করা যাতে আপনি case.valueবিবৃতিটির মধ্যে রেফারেন্স করতে পারেন ।
পিটার

48

একটি প্যাটার্ন রয়েছে যা আমি টুইস্টেড পাইথন কোড থেকে শিখেছি।

class SMTP:
    def lookupMethod(self, command):
        return getattr(self, 'do_' + command.upper(), None)
    def do_HELO(self, rest):
        return 'Howdy ' + rest
    def do_QUIT(self, rest):
        return 'Bye'

SMTP().lookupMethod('HELO')('foo.bar.com') # => 'Howdy foo.bar.com'
SMTP().lookupMethod('QUIT')('') # => 'Bye'

টোকেনে প্রেরণ এবং কোডের বর্ধিত অংশটি কার্যকর করতে আপনার যে কোনও সময় আপনি এটি ব্যবহার করতে পারেন। একটি রাষ্ট্রের মেশিনে আপনার state_পদ্ধতি থাকবে এবং প্রেরণ করবেন self.state। বেস শ্রেণি থেকে উত্তরাধিকার সূত্রে এবং নিজস্ব do_পদ্ধতি নির্ধারণ করে এই সুইচটি পরিষ্কারভাবে বাড়ানো যেতে পারে । প্রায়শই do_আপনার বেস ক্লাসে পদ্ধতিও থাকে না।

সম্পাদনা করুন: ঠিক কীভাবে এটি ব্যবহৃত হয়

এসএমটিপি এর ক্ষেত্রে আপনি HELOতারটি থেকে পাবেন । প্রাসঙ্গিক কোড (থেকে twisted/mail/smtp.py, আমাদের ক্ষেত্রে পরিবর্তিত) এর মত দেখাচ্ছে

class SMTP:
    # ...

    def do_UNKNOWN(self, rest):
        raise NotImplementedError, 'received unknown command'

    def state_COMMAND(self, line):
        line = line.strip()
        parts = line.split(None, 1)
        if parts:
            method = self.lookupMethod(parts[0]) or self.do_UNKNOWN
            if len(parts) == 2:
                return method(parts[1])
            else:
                return method('')
        else:
            raise SyntaxError, 'bad syntax'

SMTP().state_COMMAND('   HELO   foo.bar.com  ') # => Howdy foo.bar.com

আপনি পাবেন ' HELO foo.bar.com '(বা আপনি পেতে পারেন 'QUIT'বা 'RCPT TO: foo')। এটি partsহিসাবে চিহ্নিত করা হয় ['HELO', 'foo.bar.com']। আসল পদ্ধতি দেখার নামটি নেওয়া হয়েছে parts[0]

(মূল পদ্ধতিটিও বলা হয় state_COMMAND, কারণ এটি কোনও রাষ্ট্রীয় মেশিন বাস্তবায়নের জন্য একই প্যাটার্ন ব্যবহার করে, অর্থাৎ getattr(self, 'state_' + self.mode))


4
কেবলমাত্র পদ্ধতিগুলিকে সরাসরি কল করার চেয়ে আমি এই প্যাটার্ন থেকে কোনও উপকার দেখতে পাচ্ছি না: এসএমটিপি ()। ডু হেলো ('foo.bar.com') ঠিক আছে, লকআপমথোডে সাধারণ কোড থাকতে পারে, তবে যেহেতু এটির দ্বারাও ওভাররাইট করা যেতে পারে সাবক্লাসটি আমি দেখতে পাচ্ছি না আপনি প্রেরণা থেকে কী অর্জন করেছেন।
মিঃ শার্ক

1
কোন পদ্ধতিটি আগে থেকে কল করতে হবে তা আপনি জানতেন না, তার অর্থ হল 'হেলো' একটি ভেরিয়েবল থেকে আসে। আমি আসল পোস্টে ব্যবহারের উদাহরণ যুক্ত করেছি

আমি সহজভাবে পরামর্শ দিতে পারি: eval ('SMTP ()। Do_' + কমান্ড) ('foo.bar.com')
jforberg

8
Eval? গম্ভীরভাবে? এবং প্রতি কল প্রতি একটি পদ্ধতি তাত্ক্ষণিক না করে, আমরা একবার খুব ভাল ইনস্ট্যান্টিয়েট করতে পারি এবং এটির কোনও অভ্যন্তরীণ অবস্থা না থাকলে সমস্ত কলগুলিতে এটি ব্যবহার করতে পারি provided
মহেশ

1
আইএমও-এর আসল কীটি চালানোর জন্য কোনও ফাংশন নির্দিষ্ট করতে getattr ব্যবহার করে প্রেরণ করা। যদি পদ্ধতিগুলি কোনও মডিউলে থাকে তবে আপনি এটি পাওয়ার জন্য getattr (লোকাল (), ফান_নাম) করতে পারতেন। 'Do_' অংশটি সুরক্ষা / ত্রুটির জন্য ভাল তাই কেবল উপসর্গ সহ ফানক কল করা যেতে পারে। এসএমটিপি নিজেই লুকআপকে মেঠোড বলে। আদর্শভাবে বাইরের এইগুলির কোনও সম্পর্কে জানে না। এসএমটিপি ()। লুকমুথথ মেথড (নাম) (ডেটা) করতে আসলেই তা বোঝা যায় না। যেহেতু কমান্ড এবং ডেটা এক স্ট্রিংয়ে রয়েছে এবং এসএমটিপি এটি পার্স করে, এটি আরও অর্থবোধ করে। শেষ অবধি, এসএমটিপির সম্ভবত অন্য অংশীদারি রাষ্ট্র রয়েছে যা এটি বর্গ হিসাবে ন্যায্যতা প্রমাণ করে।
শনফুমো

27

ধরা যাক আপনি কেবল কোনও মান ফিরিয়ে দিতে চান না, তবে এমন কোনও পদ্ধতি ব্যবহার করতে চান যা কোনও বস্তুর কিছু পরিবর্তন করে। এখানে বর্ণিত পদ্ধতির ব্যবহারটি হ'ল:

result = {
  'a': obj.increment(x),
  'b': obj.decrement(x)
}.get(value, obj.default(x))

এখানে যা ঘটে তা হ'ল অজগর অভিধানের সমস্ত পদ্ধতির মূল্যায়ন করে। সুতরাং আপনার মান 'এ' হলেও, অবজেক্টটি এক্স দ্বারা বাড়ানো এবং হ্রাস পাবে।

সমাধান:

func, args = {
  'a' : (obj.increment, (x,)),
  'b' : (obj.decrement, (x,)),
}.get(value, (obj.default, (x,)))

result = func(*args)

সুতরাং আপনি একটি ফাংশন এবং তার যুক্তি সমন্বিত একটি তালিকা পাবেন get এইভাবে, কেবল ফাংশন পয়েন্টার এবং যুক্তি তালিকাটি ফিরে আসে, মূল্যায়ন হয় না । 'ফলাফল' তারপরে ফিরে আসা ফাংশন কলটির মূল্যায়ন করে।


23

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

if something:
    return "first thing"
elif somethingelse:
    return "second thing"
elif yetanotherthing:
    return "third thing"
else:
    return "default thing"

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


6
তাহলে পাইথন লুপের জন্য এবং লুপগুলি কেন রাখে? লুপের জন্য আপনি যা কিছু করতে পারেন আপনি কিছুক্ষণের জন্য লুপ প্রয়োগ করতে পারেন।
ব্রুস 10

1
সত্য। প্রোগ্রামারদের শুরু করে প্রায়শই স্যুইচ / কেস ব্যবহার করা হয় না। তারা সত্যই যা চায় তা হ'ল কৌশল প্যাটার্ন
ব্যবহারকারী 228395

পাইথনের মতো শোনাচ্ছে এটি Clojure ছিল
TWR Cole

1
@ টিডব্লিউআর কোল আমার মনে হয় না, পাইথন এটি আগে করছিল। পাইথন 1990 সাল থেকে প্রায় এবং 2007 এর পরে ক্লোজার।
টেলর

কিছু করার একমাত্র সঠিক উপায়। পাইথন 2.7 বা পাইথন 3? হাঃ হাঃ হাঃ.
TWR Cole

17

"ডিক হিসাবে সুইচ" ধারণাটি প্রসারিত করা হচ্ছে। আপনি যদি আপনার সুইচের জন্য একটি ডিফল্ট মান ব্যবহার করতে চান:

def f(x):
    try:
        return {
            'a': 1,
            'b': 2,
        }[x]
    except KeyError:
        return 'default'

14
আমি মনে করি ডিফল্টে ডিফল্ট নির্দিষ্ট করে .get () ব্যবহার করা আরও পরিষ্কার cle আমি ব্যতিক্রমী পরিস্থিতিতে ব্যতিক্রমগুলি ছেড়ে যেতে পছন্দ করি এবং এটি অস্পষ্ট না হয়েই তিনটি কোডের কোড এবং একটি স্তর অবলম্বন করে।
ক্রিস বি

10
এই হল একটি ব্যতিক্রমী পরিস্থিতিতে। এটি ব্যবহারের উপর নির্ভর করে বিরল পরিস্থিতি হতে পারে বা নাও হতে পারে , তবে এটি অবশ্যই 'default'নিয়ম থেকে একটি ব্যতিক্রম (পিছিয়ে পড়া ) হতে পারে (এই ডিক্ট থেকে কিছু পান)। ডিজাইন দ্বারা, পাইথন প্রোগ্রামগুলি একটি টুপি বাদ পড়ে ব্যতিক্রম ব্যবহার করে। বলা হচ্ছে, getব্যবহারটি কোডটিকে কিছুটা সুন্দর করতে পারে।
মাইক গ্রাহাম

16

আপনার যদি জটিল কেস ব্লক থাকে তবে আপনি কোনও ফাংশন অভিধান অনুসন্ধান সারণী ব্যবহার করে বিবেচনা করতে পারেন ...

আপনি যদি এটি না করেন তবে এটির আগে আপনার ডিবাগারে প্রবেশ করার ভাল ধারণা এবং ডিকশনারিটি প্রতিটি ফাংশনটি ঠিক কীভাবে দেখায় view

দ্রষ্টব্য: কেস / অভিধানের ভিতরে "()" ব্যবহার করবেন না বা অভিধান / কেস ব্লকটি তৈরি হওয়ার সাথে সাথে এটি আপনার প্রতিটি ফাংশনকে কল করবে will এটি মনে রাখবেন কারণ আপনি কেবল হ্যাশ শৈলীর অনুসন্ধান ব্যবহার করে প্রতিটি ফাংশন কল করতে চান।

def first_case():
    print "first"

def second_case():
    print "second"

def third_case():
    print "third"

mycase = {
'first': first_case, #do not use ()
'second': second_case, #do not use ()
'third': third_case #do not use ()
}
myfunc = mycase['first']
myfunc()

আমি আপনার সমাধান পছন্দ। তবে, আমার যদি কিছু ভেরিয়েবল বা অবজেক্ট পাস করার দরকার হয় তবে?
টেডো ভার্বানেক

পদ্ধতিটি পরামিতিগুলির প্রত্যাশা রাখলে এটি কাজ করবে না।
কুলসঙ্গর

16

যদি আপনি অতিরিক্ত বক্তব্য অনুসন্ধান করেন, "সুইচ" হিসাবে, আমি পাইথন প্রসারিত একটি পাইথন মডিউল তৈরি করেছি। একে ESPY বলা হয় "পাইথনের বর্ধিত কাঠামো" হিসাবে এবং এটি পাইথন ২.x এবং পাইথন ৩.x উভয়ের জন্যই উপলব্ধ

উদাহরণস্বরূপ, এই ক্ষেত্রে, নিম্নলিখিত কোড দ্বারা একটি স্যুইচ বিবৃতি সম্পাদন করা যেতে পারে:

macro switch(arg1):
    while True:
        cont=False
        val=%arg1%
        socket case(arg2):
            if val==%arg2% or cont:
                cont=True
                socket
        socket else:
            socket
        break

এটি এভাবে ব্যবহার করা যেতে পারে:

a=3
switch(a):
    case(0):
        print("Zero")
    case(1):
        print("Smaller than 2"):
        break
    else:
        print ("greater than 1")

সুতরাং গুপ্তচর এটি পাইথনে অনুবাদ করুন:

a=3
while True:
    cont=False
    if a==0 or cont:
        cont=True
        print ("Zero")
    if a==1 or cont:
        cont=True
        print ("Smaller than 2")
        break
    print ("greater than 1")
    break

খুব দুর্দান্ত, তবে while True:উত্পন্ন পাইথন কোডের শীর্ষে বিন্দুটি কী ? এটি অনিবার্যভাবে breakউত্পন্ন পাইথন কোডের নীচে আঘাত করবে , সুতরাং এটি আমার কাছে মনে হয় যে দুটি while True:এবং breakমুছে ফেলা হতে পারে। তদুপরি, contব্যবহারকারী যদি তাদের নিজস্ব কোডে একই নাম ব্যবহার করে তবে কি নামটি পাল্টানোর জন্য ESPY যথেষ্ট স্মার্ট ? যে কোনও ইভেন্টে, আমি ভ্যানিলা পাইথনটি ব্যবহার করতে চাই তাই আমি এটি ব্যবহার করব না, তবে এটি দুর্দান্ত কিছু নয়। নিছক শীতলতার জন্য +1।
আর্টঅফ ওয়ারফেয়ার

@ আর্টঅফ ওয়ারফেয়ার while True:breakএর কারণ হ'ল অনুমতি দেওয়া কিন্তু পড়ে যাওয়ার দরকার নেই।
সলোমন উকো

এই মডিউলটি এখনও উপলব্ধ?
সলোমন উকো

15

আমি দেখতে পেলাম যে একটি সাধারণ সুইচ কাঠামো:

switch ...parameter...
case p1: v1; break;
case p2: v2; break;
default: v3;

পাইথনে নিম্নলিখিত হিসাবে প্রকাশ করা যেতে পারে:

(lambda x: v1 if p1(x) else v2 if p2(x) else v3)

বা পরিষ্কার পদ্ধতিতে ফর্ম্যাট করা:

(lambda x:
     v1 if p1(x) else
     v2 if p2(x) else
     v3)

বিবৃতি হওয়ার পরিবর্তে অজগর সংস্করণটি একটি অভিব্যক্তি, যা একটি মানকে মূল্যায়ণ করে।


এছাড়াও ... প্যারামিটার ... এবং p1 (x) এর পরিবর্তে কীভাবে parameterএবংp1==parameter
বব স্টেইন

@ BobStein-VisiBone হাই, এখানে একটি উদাহরণ যে আমার পাইথন সেশনে রান: f = lambda x: 'a' if x==0 else 'b' if x==1 else 'c'। পরে যখন ডেকেছিলাম তখন f(2)পেয়েছি 'c'; f(1), 'b'; এবং f(0), 'a'। পি 1 (এক্স) হিসাবে, এটি একটি শিকারী বোঝায়; যতক্ষণ এটি ফিরবে Trueবা False, এটি কোনও ফাংশন কল বা অভিব্যক্তি নয়, ঠিক আছে।
লিও

@ ববস্টাইন-ভিসিবিোন হ্যাঁ, আপনি ঠিক বলেছেন! ধন্যবাদ :) কাজ করার জন্য বহু-লাইন প্রকাশের জন্য, বন্ধুত্বগুলি আপনার পরামর্শ অনুসারে বা আমার পরিবর্তিত উদাহরণ হিসাবে রাখা উচিত।
লিও

চমৎকার। এখন আমি প্যারেন্স সম্পর্কে আমার সমস্ত মন্তব্য মুছব।
বব স্টেইন

15

এখানে বেশিরভাগ উত্তর বেশ পুরানো, এবং বিশেষত স্বীকৃত উত্তর, তাই এটি আপডেট করার মতো বলে মনে হচ্ছে।

প্রথমত, সরকারী পাইথন এফএকিউ এটি কভার করে এবং elifসাধারণ কেসগুলির জন্য চেইন এবং dictবৃহত্তর বা আরও জটিল মামলার জন্য সুপারিশ করে । এটি visit_কিছু ক্ষেত্রে পদ্ধতিগুলির একটি সেট (অনেকগুলি সার্ভার ফ্রেমওয়ার্ক দ্বারা ব্যবহৃত একটি স্টাইল )ও প্রস্তাব করে:

def dispatch(self, value):
    method_name = 'visit_' + str(value)
    method = getattr(self, method_name)
    method()

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


এক জিনিস যা একাধিকবার এসেছিল (এবং এটি পিআইপি 275 এ দেখা যাবে, যদিও এটি একটি আসল সুপারিশ হিসাবে কাটা হয়েছিল) এটি হ'ল আপনি যদি 4 টি কেস পরিচালনা করতে 8 লাইন কোড রেখে সত্যিই বিরক্ত হন তবে 6 টি বনাম vs আপনার সি বা বাশ লাইনে থাকা লাইনগুলি আপনি সর্বদা এটি লিখতে পারেন:

if x == 1: print('first')
elif x == 2: print('second')
elif x == 3: print('third')
else: print('did not place')

এটি পিইপি 8 দ্বারা ঠিক উত্সাহিত হয় না, তবে এটি পঠনযোগ্য এবং খুব ইউনিডিয়ম্যাটিক নয়।


পিইপি 3103 প্রত্যাখ্যান হওয়ার পরে এক দশকেরও বেশি সময় ধরে সি-স্টাইলের মামলার বিবৃতি বা গো-এর সামান্য শক্তিশালী সংস্করণটিকে মৃত হিসাবে বিবেচনা করা হয়েছে; যখনই কেউ এটিকে অজগর-ধারণা বা দেবদেবীতে নিয়ে আসে, তাদের পুরানো সিদ্ধান্তের দিকে উল্লেখ করা হয়।

যাইহোক, পুরো এমএল-স্টাইলের প্যাটার্ন ম্যাচিংয়ের ধারণাটি প্রতি কয়েক বছর পরে উত্থাপিত হয়, বিশেষত যেহেতু সুইফ্ট এবং মরিচা ভাষাগুলি এটি গ্রহণ করেছে। সমস্যাটি হ'ল বীজগণিত ডেটা ধরণের ছাড়াই প্যাটার্ন মেলানো থেকে বেশি ব্যবহার করা শক্ত। যদিও গিডো এই ধারণার প্রতি সহানুভূতিশীল ছিলেন, তবুও কেউই এমন প্রস্তাব নিয়ে আসেনি যা পাইথনের সাথে খুব ভাল ফিট করে। ( উদাহরণস্বরূপ আপনি আমার ২০১৪ স্ট্রোম্যান পড়তে পারেন )) এটি যোগ করতে পারে 7.7 এরdataclass মধ্যে এবং সামান্য enumধরণের হ্যান্ডেল করার জন্য আরও শক্তিশালী করার জন্য বা কিছু ধরণের স্টেটমেন্ট-লোকাল বাইন্ডিংয়ের বিভিন্ন প্রস্তাবের (যেমন পিইপি 3150 এর মতো বিভিন্ন প্রস্তাবের সাথে) পরিবর্তিত হতে পারে , বা প্রস্তাবসমূহের সেট বর্তমানে অন-বিদেশে আলোচনা করা হচ্ছে)। তবে এখনও পর্যন্ত তা হয়নি।

পার্ল--স্টাইলের মিলের জন্য মাঝে মধ্যে প্রস্তাবনাও রয়েছে যা মূলত elifরেগেক্স থেকে একক-প্রেরণে টাইপ-স্যুইচিং পর্যন্ত সমস্ত কিছুর একটি মিশ্র্যাশ ।


15

ফাংশনগুলি চালনার সমাধান:

result = {
    'case1':     foo1, 
    'case2':     foo2,
    'case3':     foo3,
    'default':   default,
}.get(option)()

যেখানে foo1 (), foo2 (), foo3 () এবং ডিফল্ট () ফাংশন


1
হ্যাঁ, উদাহরণস্বরূপ, যদি আপনার চলক বিকল্প == "কেস 2" আপনার ফলাফল = foo2 ()
আলেজান্দ্রো কুইন্টানার

এবং তাই এবং আরও।
আলেজান্দ্রো কুইন্টানার

হ্যাঁ, আমি উদ্দেশ্যটি বুঝতে পারি। তবে আমার উদ্বেগটি হ'ল যদি আপনি কেবল চান foo2(), তবে foo1(), foo3()এবং default()কার্যাদি সমস্ত চলতে চলেছে, যার অর্থ জিনিসগুলিতে অনেক বেশি সময় লাগতে পারে
ব্রায়ান আন্ডারউড

1
অভিধানের ভিতরে () বাদ দিন। ব্যবহার get(option)()। সমস্যা সমাধান.
টিম্বেজ

1
() এর দুর্দান্ত ব্যবহার একটি গ্রেট সমাধান, এটি পরীক্ষা করার জন্য আমি একটি গিস্ট
আলেজান্দ্রো কুইন্টানর

13

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

l = ['Dog', 'Cat', 'Bird', 'Bigfoot',
     'Dragonfly', 'Snake', 'Bat', 'Loch Ness Monster']

for x in l:
    if x in ('Dog', 'Cat'):
        x += " has four legs"
    elif x in ('Bat', 'Bird', 'Dragonfly'):
        x += " has wings."
    elif x in ('Snake',):
        x += " has a forked tongue."
    else:
        x += " is a big mystery by default."
    print(x)

print()

for x in range(10):
    if x in (0, 1):
        x = "Values 0 and 1 caught here."
    elif x in (2,):
        x = "Value 2 caught here."
    elif x in (3, 7, 8):
        x = "Values 3, 7, 8 caught here."
    elif x in (4, 6):
        x = "Values 4 and 6 caught here"
    else:
        x = "Values 5 and 9 caught in default."
    print(x)

প্রদান করে:

Dog has four legs
Cat has four legs
Bird has wings.
Bigfoot is a big mystery by default.
Dragonfly has wings.
Snake has a forked tongue.
Bat has wings.
Loch Ness Monster is a big mystery by default.

Values 0 and 1 caught here.
Values 0 and 1 caught here.
Value 2 caught here.
Values 3, 7, 8 caught here.
Values 4 and 6 caught here
Values 5 and 9 caught in default.
Values 4 and 6 caught here
Values 3, 7, 8 caught here.
Values 3, 7, 8 caught here.
Values 5 and 9 caught in default.

ঠিক এখানে পড়াশোনা কোথায়?
জোনাস শোফার

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

2
এখানে "কুকুর" এবং "বিড়াল" উভয়ই মানগুলি পড়ে এবং একই কার্যকারিতা দ্বারা পরিচালিত হয়, যা এটিকে "চার পা" বলে সংজ্ঞায়িত করা হয়। এটি একই বিস্ময়ের সমতুল্য এবং একই মানের ক্ষেত্রে বিবৃতি যেখানে একটি বিরতি ঘটে সেখানে পরিচালিত বিভিন্ন মান values
জেডি গ্রাহাম

@ জেডিগ্রাহাম আমি মনে করি জোনাস মানে পতনের আরেকটি দিক, যা প্রোগ্রামার মাঝে মাঝে কোডটির breakশেষে লিখতে ভুলে গেলে ঘটে যায় case। তবে আমি মনে করি আমাদের এ জাতীয় "ফলথ্রু" দরকার নেই :)
মিখাইল ব্যাটার

12

আমি যে সমাধানগুলি ব্যবহার করি:

এখানে পোস্ট করা সমাধানগুলির 2 টির সংমিশ্রণ, যা পড়তে তুলনামূলকভাবে সহজ এবং ডিফল্টগুলিকে সমর্থন করে।

result = {
  'a': lambda x: x * 5,
  'b': lambda x: x + 7,
  'c': lambda x: x - 2
}.get(whatToUse, lambda x: x - 22)(value)

কোথায়

.get('c', lambda x: x - 22)(23)

"lambda x: x - 2"ডিকটিতে দেখায় এবং এটি ব্যবহার করেx=23

.get('xxx', lambda x: x - 22)(44)

এটি ডিকটিতে খুঁজে পায় না এবং এটির "lambda x: x - 22"সাথে ডিফল্ট ব্যবহার করে x=44


10
# simple case alternative

some_value = 5.0

# this while loop block simulates a case block

# case
while True:

    # case 1
    if some_value > 5:
        print ('Greater than five')
        break

    # case 2
    if some_value == 5:
        print ('Equal to five')
        break

    # else case 3
    print ( 'Must be less than 5')
    break

10
def f(x):
    dictionary = {'a':1, 'b':2, 'c':3}
    return dictionary.get(x,'Not Found') 
##Returns the value for the letter x;returns 'Not Found' if x isn't a key in the dictionary

আপনার কোডের সংক্ষিপ্ত বিবরণ এবং এটি কীভাবে পোস্ট করা প্রশ্নের সমাধান করে
হেনরি উডি

ঠিক আছে, আমি এখন এটির জন্য একটি মন্তব্য যুক্ত করেছি।
বিদ্যায়াত আগরওয়াল

8

আমি মার্ক বিসের উত্তর পছন্দ করেছি

যেহেতু x ভেরিয়েবলটি অবশ্যই দু'বার ব্যবহার করা উচিত, তাই আমি ল্যাম্বডা ফাংশনগুলিকে প্যারামিটারলেসে পরিবর্তন করেছি।

আমাকে সাথে চালাতে হবে results[value](value)

In [2]: result = {
    ...:   'a': lambda x: 'A',
    ...:   'b': lambda x: 'B',
    ...:   'c': lambda x: 'C'
    ...: }
    ...: result['a']('a')
    ...: 
Out[2]: 'A'

In [3]: result = {
    ...:   'a': lambda : 'A',
    ...:   'b': lambda : 'B',
    ...:   'c': lambda : 'C',
    ...:   None: lambda : 'Nothing else matters'

    ...: }
    ...: result['a']()
    ...: 
Out[3]: 'A'

সম্পাদনা: আমি লক্ষ্য করেছি যে আমি Noneঅভিধানের সাথে টাইপ ব্যবহার করতে পারি । সুতরাং এই অনুকরণ করা হবেswitch ; case else


কোনওটিই কি সরলভাবে অনুকরণ করে না result[None]()?
বব স্টেইন

হ্যাঁ অবশ্যই. আমার অর্থresult = {'a': 100, None:5000}; result[None]
গুনেইসাস

4
শুধু পরীক্ষণ যে কোন এক চিন্তা করছে None:মত আচরণ default:
বব স্টেইন

7
def f(x):
     return 1 if x == 'a' else\
            2 if x in 'bcd' else\
            0 #default

সংক্ষিপ্ত এবং পড়তে সহজ, এর একটি ডিফল্ট মান রয়েছে এবং উভয় শর্তে এবং ফেরতের মানগুলিতে এক্সপ্রেশনকে সমর্থন করে।

তবে এটি অভিধানের সাথে সমাধানের চেয়ে কম দক্ষ। উদাহরণস্বরূপ, পাইথনকে ডিফল্ট মানটি ফেরত দেওয়ার আগে সমস্ত অবস্থার মধ্য দিয়ে স্ক্যান করতে হয়।


6

আপনি প্রেরণ ডিক ব্যবহার করতে পারেন:

#!/usr/bin/env python


def case1():
    print("This is case 1")

def case2():
    print("This is case 2")

def case3():
    print("This is case 3")


token_dict = {
    "case1" : case1,
    "case2" : case2,
    "case3" : case3,
}


def main():
    cases = ("case1", "case3", "case2", "case1")
    for case in cases:
        token_dict[case]()


if __name__ == '__main__':
    main()

আউটপুট:

This is case 1
This is case 3
This is case 2
This is case 1

6

সরল, পরীক্ষিত নয়; প্রতিটি শর্তটি স্বাধীনভাবে মূল্যায়ন করা হয়: কোনও পতনের মধ্য দিয়ে নেই, তবে সমস্ত ক্ষেত্রেই মূল্যায়ন করা হয় (যদিও স্যুইচ করার অভিব্যক্তিটি কেবল একবারই মূল্যায়ন করা হয়), যদি না কোনও ব্রেক স্টেটমেন্ট থাকে। উদাহরণ স্বরূপ,

for case in [expression]:
    if case == 1:
        print(end='Was 1. ')

    if case == 2:
        print(end='Was 2. ')
        break

    if case in (1, 2):
        print(end='Was 1 or 2. ')

    print(end='Was something. ')

কপি করে প্রিন্ট Was 1. Was 1 or 2. Was something. (শালা! কেন আমি ইনলাইন কোড ব্লকগুলিতে হোয়াইটস্পেস trailing করতে নি?) যদি expressionমূল্যায়ন করতে 1, Was 2.যদি expressionমূল্যায়ন করতে 2, অথবা Was something.যদি expressionঅন্য কিছু মূল্যায়ন করে।


1
ঠিক আছে, কাজগুলি পড়ে তবে কেবল do_default এ যেতে।
সোকোকিট

5

সংজ্ঞা:

def switch1(value, options):
  if value in options:
    options[value]()

কেসগুলি একটি মানচিত্রে বান্ডিল করা সহ আপনাকে মোটামুটি সোজা সরল বাক্য গঠন ব্যবহার করতে দেয়:

def sample1(x):
  local = 'betty'
  switch1(x, {
    'a': lambda: print("hello"),
    'b': lambda: (
      print("goodbye," + local),
      print("!")),
    })

আমি এমনভাবে সুইচটিকে নতুন করে সংজ্ঞায়িত করার চেষ্টা চালিয়েছি যা আমাকে "ল্যাম্বদা:" থেকে মুক্তি দিতে পারে, কিন্তু ছেড়ে দিয়েছিল। সংজ্ঞা টুইঙ্কিং:

def switch(value, *maps):
  options = {}
  for m in maps:
    options.update(m)
  if value in options:
    options[value]()
  elif None in options:
    options[None]()

আমাকে একই কোডে একাধিক কেস ম্যাপ করার এবং একটি ডিফল্ট বিকল্প সরবরাহ করার অনুমতি দিয়েছে:

def sample(x):
  switch(x, {
    _: lambda: print("other") 
    for _ in 'cdef'
    }, {
    'a': lambda: print("hello"),
    'b': lambda: (
      print("goodbye,"),
      print("!")),
    None: lambda: print("I dunno")
    })

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


5

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

class ChoiceManager:

    def __init__(self):
        self.__choice_table = \
        {
            "CHOICE1" : self.my_func1,
            "CHOICE2" : self.my_func2,
        }

    def my_func1(self, data):
        pass

    def my_func2(self, data):
        pass

    def process(self, case, data):
        return self.__choice_table[case](data)

ChoiceManager().process("CHOICE1", my_data)

"__Choice_table" এর কী হিসাবে ক্লাসগুলি ব্যবহার করে এই পদ্ধতির সুবিধা নেওয়া সম্ভব । এই উপায়ে আপনি আইসনস্ট্যান্স অপব্যবহার এড়াতে এবং সমস্ত পরিষ্কার এবং পরীক্ষামূলক রাখতে পারেন ।

ধরুন আপনাকে নেট বা আপনার এমকিউ থেকে প্রচুর বার্তা বা প্যাকেট প্রক্রিয়াকরণ করতে হবে। প্রতিটি প্যাকেটের নিজস্ব কাঠামো এবং তার পরিচালনা কোড থাকে (সাধারণ পদ্ধতিতে)। উপরের কোডের মাধ্যমে এটির মতো কিছু করা সম্ভব:

class PacketManager:

    def __init__(self):
        self.__choice_table = \
        {
            ControlMessage : self.my_func1,
            DiagnosticMessage : self.my_func2,
        }

    def my_func1(self, data):
        # process the control message here
        pass

    def my_func2(self, data):
        # process the diagnostic message here
        pass

    def process(self, pkt):
        return self.__choice_table[pkt.__class__](pkt)

pkt = GetMyPacketFromNet()
PacketManager().process(pkt)


# isolated test or isolated usage example
def test_control_packet():
    p = ControlMessage()
    PacketManager().my_func1(p)

সুতরাং কোড প্রবাহে জটিলতা ছড়িয়ে পড়ে না তবে এটি কোড কাঠামোয় রেন্ডার হয়


সত্যিই কুৎসিত ... পড়ার সময় স্যুইচ কেসটি এত পরিষ্কার। পাইথনে এটি প্রয়োগ করা হচ্ছে না তা বুঝতে পারি না।
jmcollin92

@ অ্যান্ডি ক্লিফটন: আমি দুঃখিত ... একটি উদাহরণ? প্রতিবার আপনার একাধিক সিদ্ধান্ত শাখাগুলি কোড থাকা দরকার তা ভেবে দেখুন এবং আপনি এই পদ্ধতিটি প্রয়োগ করতে পারেন।
J_Zar

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

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

1
@ অ্যান্ডি ক্লিফটন: আমি দুঃখিত, আমি দেরি করে ফেলেছি তবে কিছু উদাহরণ পোস্ট করেছি।
J_Zar

5

গ্রেগ হিউগিলের উত্তরের সম্প্রসারণ - আমরা একটি ডিকোরেটর ব্যবহার করে অভিধান-সমাধানটি encapsulate করতে পারি:

def case(callable):
    """switch-case decorator"""
    class case_class(object):
        def __init__(self, *args, **kwargs):
            self.args = args
            self.kwargs = kwargs

        def do_call(self):
            return callable(*self.args, **self.kwargs)

return case_class

def switch(key, cases, default=None):
    """switch-statement"""
    ret = None
    try:
        ret = case[key].do_call()
    except KeyError:
        if default:
            ret = default.do_call()
    finally:
        return ret

এটি তখন- @caseডিসকোরেটারের সাথে ব্যবহার করা যেতে পারে

@case
def case_1(arg1):
    print 'case_1: ', arg1

@case
def case_2(arg1, arg2):
    print 'case_2'
    return arg1, arg2

@case
def default_case(arg1, arg2, arg3):
    print 'default_case: ', arg1, arg2, arg3

ret = switch(somearg, {
    1: case_1('somestring'),
    2: case_2(13, 42)
}, default_case(123, 'astring', 3.14))

print ret

সুসংবাদটি হ'ল এটি ইতিমধ্যে নিওপাইসুইচ - মডুল্যালে সম্পন্ন হয়েছে । কেবল পাইপ ব্যবহার করে ইনস্টল করুন:

pip install NeoPySwitch

5

আমি যে সমাধানটি ব্যবহার করতে চাইছি তা অভিধানেরও ব্যবহার করে:

def decision_time( key, *args, **kwargs):
    def action1()
        """This function is a closure - and has access to all the arguments"""
        pass
    def action2()
        """This function is a closure - and has access to all the arguments"""
        pass
    def action3()
        """This function is a closure - and has access to all the arguments"""
        pass

   return {1:action1, 2:action2, 3:action3}.get(key,default)()

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


5

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

def ToUpper(lcChar):
    if (lcChar == 'a' or lcChar == 'A'):
        return 'A'
    elif (lcChar == 'b' or lcChar == 'B'):
        return 'B'
    ...
    elif (lcChar == 'z' or lcChar == 'Z'):
        return 'Z'
    else:
        return None        # or something

এখন, আপনি একটি সুইচ-বিবৃতি দিয়ে এটি করতে পারেন (পাইথন যদি একটি প্রস্তাব দেয়) তবে আপনি আপনার সময় নষ্ট করবেন কারণ এমন পদ্ধতি রয়েছে যা এই কাজটি ঠিক করে দেয়। বা হতে পারে, আপনার কিছু কম স্পষ্ট হয়েছে:

def ConvertToReason(code):
    if (code == 200):
        return 'Okay'
    elif (code == 400):
        return 'Bad Request'
    elif (code == 404):
        return 'Not Found'
    else:
        return None

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

এবং স্যুইচ বিবৃতিগুলির জন্য "ব্যবহারের মামলার" বিশাল সংখ্যা এই দুটি ক্ষেত্রে একটির মধ্যে পড়ে যাবে; আপনি যদি নিজের সমস্যা সম্পর্কে পুরোপুরি চিন্তা করে থাকেন তবে এটি ব্যবহার করার খুব কম কারণ রয়েছে।

সুতরাং, "আমি পাইথনে কীভাবে স্যুইচ করব?" জিজ্ঞাসা করার পরিবর্তে, আমাদের আমাদের জিজ্ঞাসা করা উচিত, "আমি পাইথনে স্যুইচ করতে চাই কেন?" কারণ এটি প্রায়শই আকর্ষণীয় প্রশ্ন এবং আপনি যা কিছু নির্মাণ করছেন তার নকশায় প্রায়শই ত্রুটিগুলি প্রকাশ করে দেবে।

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

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