python - ইথন - সি প্রোগ্রামিং সফটওয়্যার




পাইথন সুইচ বিবৃতি জন্য প্রতিস্থাপন? (20)

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

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

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

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


অভিধান পদ্ধতির সাথে (যা আমি সত্যিই পছন্দ করি, বিটিডব্লিউ), সুইচ / কেস / ডিফল্ট কার্যকারিতা পেতে হলে আপনি-elif-else ব্যবহার করতে পারেন:

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

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


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

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

আপনি ডিফল্টগুলি চাইলে আপনি অভিধানটি get(key[, default]) পদ্ধতি:

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

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


আমি একটি সাধারণ সুইচ গঠন পাওয়া যায় যে:

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)

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


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

যেহেতু x পরিবর্তনশীলটি দুবার ব্যবহার করা উচিত, তাই আমি lambda ফাংশনকে প্যারামিটারহীনতে সংশোধন করেছি।

আমি 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 সাথে None টাইপ ব্যবহার করতে পারি না। সুতরাং এই switch ; case else অনুকরণ করা switch ; case else switch ; case else


আমি শুধু এখানে আমার দুটি সেন্ট ড্রপ যাচ্ছে। Python এ কেস / সুইচ স্টেটমেন্ট নেই কারণ পাইথন 'থ্রেসকে কিছু করার একমাত্র সঠিক উপায়' অনুসরণ করে। সুতরাং সম্ভবত আপনি সুইচ / কেস কার্যকারিতা পুনর্নির্মাণের বিভিন্ন উপায়ে আসতে পারেন, তবে এটি সম্পন্ন করার পাইথনিক উপায় যদি / elif গঠন হয়। অর্থাত

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

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


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

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] থেকে নেওয়া হয় parts[0]

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


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

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

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

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

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

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

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

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

যাইহোক, সম্পূর্ণ এমএল-স্টাইল প্যাটার্ন মিলিংয়ের ধারণা প্রতি কয়েক বছরে উদ্ভূত হয়, বিশেষ করে সুইফ্ট এবং রাস্তার মতো ভাষাগুলি এটি গ্রহণ করেছে। সমস্যাটি হল বীজগণিত ডেটা প্রকারের ব্যতীত প্যাটার্নটির সাথে অনেক বেশি ব্যবহার করা কঠিন। গুইডো এই ধারণাটির প্রতি সহানুভূতিশীল হলেও, পাইথনটিতে খুব ভালভাবে ফিট থাকার প্রস্তাবটি কেউ আসেনি।(আপনি একটি উদাহরণের জন্য আমার ২014 স্ট্রম্যানটি পড়তে পারেন ।) এটি dataclass3.7 এর সাথে পরিবর্তিত হতে পারে এবং enumসমষ্টি প্রকারগুলি পরিচালনা করার জন্য আরও শক্তিশালী কিছু প্রস্তাব , বা বিভিন্ন ধরণের বিবৃতি-স্থানীয় বাইন্ডিংগুলির জন্য বিভিন্ন প্রস্তাবের সাথে (যেমন PEP 3150 , অথবা বর্তমানে প্রস্তাবিত প্রস্তাব সেট-ideas)। কিন্তু এতদূর, এটা না।

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


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

আপনি যদি আপনার ডিবাগারে পদক্ষেপ নেওয়ার একটি ভাল ধারণা এবং অভিধানটি প্রতিটি ফাংশনটি কেমন দেখায় তা ঠিক না করে এটি না করে থাকেন।

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

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

সমাধান আমি ব্যবহার করি:

সমাধানগুলির 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)

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


আমি উত্তর পড়ার পরে বেশ বিভ্রান্ত ছিল, কিন্তু এটি সব আপ সাফ করা:

def numbers_to_strings(argument):
    switcher = {
        0: "zero",
        1: "one",
        2: "two",
    }
    return switcher.get(argument, "nothing")

এই কোড অনুরূপ:

function(argument){
    switch(argument) {
        case 0:
            return "zero";
        case 1:
            return "one";
        case 2:
            return "two";
        default:
            return "nothing";
    }
}

পরীক্ষা করে দেখুন Source ফাংশন অভিধান ম্যাপিং সম্পর্কে আরো জানার জন্য।


আমি এই ছোট এবং পরিষ্কার সমাধান তৈরি

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

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


যদি আপনি কেস স্যুটের ভিতরে সিনট্যাক্স হাইলাইট হারানোর বিষয়ে চিন্তা না করেন তবে আপনি নিম্নলিখিতগুলি করতে পারেন:

exec {
    1: """
print ('one')
""", 
    2: """
print ('two')
""", 
    3: """
print ('three')
""",
}.get(value, """
print ('None')
""")

valueমান কোথায় । সি, এই হবে:

switch (value) {
    case 1:
        printf("one");
        break;
    case 2:
        printf("two");
        break;
    case 3:
        printf("three");
        break;
    default:
        printf("None");
        break;
}

আমরা এটি করার জন্য একটি সহায়ক ফাংশন তৈরি করতে পারি:

def switch(value, cases, default):
    exec cases.get(value, default)

সুতরাং আমরা উদাহরণ হিসাবে এটি ব্যবহার করতে পারেন এক, দুই এবং তিনটি:

switch(value, {
    1: """
print ('one')
    """, 
    2: """
print ('two')
    """, 
    3: """
print ('three')
    """,
}, """
print ('None')
""")

সংজ্ঞা:

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

আপনি একটি মানচিত্রে bundled ক্ষেত্রে, একটি মোটামুটি সহজবোধ্য সিনট্যাক্স ব্যবহার করতে পারবেন:

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

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

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")
    })

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


এই সন্ত্রস্ত উত্তর দ্বারা অনুপ্রাণিত । কোন বহিরাগত কোড প্রয়োজন। পরীক্ষিত না. মাধ্যমে পতন সঠিকভাবে কাজ করে না।

for case in [expression]:
    if case == 1:
        do_stuff()
        # Fall through

    # Doesn't fall through INTO the later cases
    if case in range(2, 5):
        do_other_stuff()
        break

    do_default()

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

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

ভাল খবর হল যে এটি ইতিমধ্যেই NeoPySwitch - NeoPySwitch সম্পন্ন হয়েছে । শুধু পিপ ব্যবহার করে ইনস্টল করুন:

pip install NeoPySwitch

class Switch:
    def __init__(self, value): self._val = value
    def __enter__(self): return self
    def __exit__(self, type, value, traceback): return False # Allows traceback to occur
    def __call__(self, *mconds): return self._val in mconds

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

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.




switch-statement