当前位置: 首页 > 知识库问答 >
问题:

Python Switch/Case语句自适应

华福
2023-03-14

好吧,冒着被嘲笑没有“更努力”的风险,我有一个场景,我一直在尝试适应一个pythonic switch案例陈述。我知道python在3.10中有新的match方法,但在我的AWS用例中我仅限于3.8.10。我一直在阅读其他语言中的switch case,我想找到一种pythonic方法,将下面混乱的if/elif/else语句转换为干净的switch case。我想知道在这种情况下其他人会怎么做

目标:我有一个文件名,该文件名将被传递到此代码序列中,我需要返回前三项(即交易\收件人\验证交易\帐户\标记化,等等)。有时代码会收到一个包含“field_results”或“issuers”的文件名,我需要确保修剪后的返回字符串包含相应的大小写。

import random

sampleKeys = [
    'transaction_recipient_notification_status_sent/transaction_recipient_notification_status_sent_2021_10_29_12_02_14.snappy',
    'transaction_recipient_payment_status_success/transaction_recipient_payment_status_success_2021_10_29_12_02_14.snappy',
    'transaction_recipient_verification_rvdm_failure/transaction_recipient_verification_rvdm_failure_2021_10_29_12_02_14.snappy',
    'transaction_recipient_verification_rvdm_failure_field_results/transaction_recipient_verification_rvdm_failure_2021_10_29_12_02_14.snappy',
    'transaction_recipient_authentication_status_success/transaction_recipient_authentication_status_success_2021_10_29_12_02_14.snappy',
    'transaction_recipient_authentication_status_success_field_results/transaction_recipient_authentication_status_success_2021_10_29_12_02_14.snappy',
    'transaction_account_tokenization_success/transaction_account_tokenization_success_2021_10_29_12_02_14.snappy',
    'transaction_account_tokenization_success_issuers/transaction_account_tokenization_success_2021_10_29_12_02_14.snappy',
    'transaction_recipient_payment_status_terminated/transaction_recipient_payment_status_terminated_2021_10_29_12_02_14.snappy',
    'transaction_recipient_verification_rvdm_success/transaction_recipient_verification_rvdm_success_2021_10_29_12_02_14.snappy',
    'transaction_recipient_verification_rvdm_success_field_results/transaction_recipient_verification_rvdm_success_2021_10_29_12_02_14.snappy',
    'transaction_recipient_notification_status_received/transaction_recipient_notification_status_received_2021_10_29_12_02_14.snappy',
    'transaction_recipient_authentication_status_success/transaction_recipient_authentication_status_success_2021_10_29_11_17_45.snappy'
    
]

key = random.choice(sampleKeys)

array_data = any(substring in key for substring in ['_issuers', '_field_results'])
if not array_data:
    if 'transaction_recipient_notification' in key:
        keySubject = 'transaction_recipient_notification'
    elif 'transaction_recipient_authentication' in key:
        keySubject = 'transaction_recipient_authentication'
    elif 'transaction_recipient_verification' in key:
        keySubject = 'transaction_recipient_verification'
    elif 'transaction_account_verification' in key:
        keySubject = 'transaction_account_verification'
    elif 'transaction_account_tokenization' in key:
        keySubject = 'transaction_account_tokenization'
    elif 'transaction_recipient_payment' in key:
        keySubject = 'transaction_recipient_payment'
else:
    if '_issuers' in key:
        if 'transaction_recipient_notification' in key:
            keySubject = 'transaction_recipient_notification_issuers'
        elif 'transaction_recipient_authentication' in key:
            keySubject = 'transaction_recipient_authentication_issuers'
        elif 'transaction_recipient_verification' in key:
            keySubject = 'transaction_recipient_verification_issuers'
        elif 'transaction_account_verification' in key:
            keySubject = 'transaction_account_verification_issuers'
        elif 'transaction_account_tokenization' in key:
            keySubject = 'transaction_account_tokenization_issuers'
        elif 'transaction_recipient_payment' in key:
            keySubject = 'transaction_recipient_payment_issuers'
    elif '_field_results' in key:
        if 'transaction_recipient_notification' in key:
            keySubject = 'transaction_recipient_notification_field_results'
        elif 'transaction_recipient_authentication' in key:
            keySubject = 'transaction_recipient_authentication_field_results'
        elif 'transaction_recipient_verification' in key:
            keySubject = 'transaction_recipient_verification_field_results'
        elif 'transaction_account_verification' in key:
            keySubject = 'transaction_account_verification_field_results'
        elif 'transaction_account_tokenization' in key:
            keySubject = 'transaction_account_tokenization_field_results'
        elif 'transaction_recipient_payment' in key:
            keySubject = 'transaction_recipient_payment_field_results'
print(f'BEFORE ===> {key}')
print(f'AFTER  ===> {keySubject}')
import re
    
class MainKeyHandleSwitch:
    
    ARRAY_OPTIONS = ['_issuers', '_field_results']
        
    def __init__(self,key):
        self._original_key = key
        self._array_data = any(substring in key for substring in self.ARRAY_OPTIONS)
        self._trimmed_dict = self.trimmed_dict()
    
    @property
    def get_trimmed_dict(self):
        return self._trimmed_dict
    
    @property
    def get_trimmed_key(self):
        return self.__get_key_subject__()
    
    def trimmed_dict(self):
        trim_dict = dict()
        trim_dict['case_one'] = re.search('transaction_recipient_notification+', self._original_key)
        trim_dict['case_two'] = re.search('transaction_recipient_authentication+', self._original_key)
        trim_dict['case_three'] = re.search('transaction_recipient_verification+', self._original_key)
        trim_dict['case_four'] = re.search('transaction_account_verification+', self._original_key)
        trim_dict['case_five'] = re.search('transaction_account_tokenization+', self._original_key)
        trim_dict['case_six'] = re.search('transaction_recipient_payment+', self._original_key)
        return trim_dict
    
    def __get_key_subject__(self):
        obj = next(item for item in list(self._trimmed_dict.values()) if item is not None)
        if not self._array_data:
            return obj.group(0)
        else:
            if '_issuers' in self._original_key:
                return f'{obj.group(0)}_issuers'
            
            elif '_field_results' in self._original_key:
                return f'{obj.group(0)}_field_results'        

以及测试类的代码:

import random

key = random.choice(sampleKeys)
print(f'before ===> {key}')
a = MainKeyHandleSwitch(key)
trimmed_key = a.get_trimmed_key
print(f'after  ===> {trimmed_key}')

共有2个答案

杨柏
2023-03-14

如果您正在寻找一种实现switch语句的方法,下面是我如何解决的:

首先像这样为开关创建一个助手函数(我把我的放在一个“myTools.py”模块中,我在所有项目中都使用这个模块):

def switch(v): yield lambda *c:v in c

它的工作方式是返回一个函数(lambda),该函数捕获开关值,如果该值在其任何参数中,则返回True。单屈服使switch()成为for循环中可用的生成器。for循环将只执行一次迭代,但是,如果它是一个循环,那么它将支持break语句和末尾的else子句(当没有执行中断时)。

这允许以非常类似于其他语言(如C)中switch语句的形式使用for循环的一次迭代:

value = 5
for case in switch(value):               # case is actually a function
    if case(0):     print("None"); break
    if case(2,4,6): print("Even"); break
    if case(3,5,7): print("Odd");  break
else:
    print("invalid value")

通过这种方法,您可以使开关功能执行任何类型的模式匹配:

def switchAllIn(v): yield lambda *c:all(s in v for s in c)

此版本的switch函数检查所有大小写参数是否都在开关值中:

value = 'The quick brown fox, jumped over the lazy dogs'

for case in switchAllIn(value):
    if case('quick','lazy'): print('oxymoron'); break
    if case('quick','fast'): print('redundant'); break
else:
    print('nothing special')

您甚至可以使用正则表达式:

def switchMatch(v): yield lambda *c:any(re.match(p,v) for p in c)         

value = 'The quick brown fox, jumped over the lazy dogs'
for case in switchMatch(value):
    if case(r'\bdog\b',r'\bfox\b') and not case('lazy'):
       print('lively canine')
       break
    if case(r'\bquick\b.+\bfox\b'):
       print('veloce vulpe')
       break

这个解决方案有很大的灵活性。

>

  • 实际上,您不必使用break,因此您可以通过多个case,甚至可以在if case(…)之间执行一些逻辑:

    如果案例(1)或案例(3):

    当使用分隔符时,您可以将for case嵌套在Switch中,而不必为case函数使用不同的名称

    例如:

    for case in switch(letter):
        if case('a','b'):
            for case in switch(number):
                if case(1,2,3): print('vitamin'); break
                ...
            break
        if case('c','d'):
            ...
            break
    
    • 可以将多个开关调用与zip()组合

    例如:

    for caseL,caseN in zip(switch(L),switch(N)):
        if caseL('a','b') and caseN(1,2,3):
           print('vitamin')
           break
        ...
    
    • 您可以使用map()将开关应用于列表的每个元素

    在这种情况下,for循环将运行多次,您必须使用continue而不是break:

    L = [1,2,3,4,5]
    for case in map(switch,L):
        if case(1,2,3):
           print('low')
           continue             # using continue instead of break 
        if case(4,5,6):
           print('medium')
           continue
        print('high')
    

    然而,对于您的特定场景,Switch语句不一定是最佳解决方案。似乎有一种前缀和后缀的组合模式,其间有一组有限的关键字。您可以在由前缀、关键字和后缀组成的正则表达式上使用一个循环来获取关键主题:

    import re
    prefixes = ('transaction_recipient_','transaction_account_')
    suffixes = ('_issuers','_field_results','') # in priority order
    keywords = r'notification|authentication|verification|tokenization|payment'
    for suffix in suffixes:
        for prefix in prefixes:
            pattern = r'\b('+prefix+keywords+suffix+')\b'
            m = re.match(pattern,key)
            if not m: continue
            keySubject = m.group()
            break
        else: continue; break
    print(f'AFTER  ===> {keySubject}')
    

  • 滑令
    2023-03-14

    我在你的代码中看到了很多重复,所以我首先想到的是:“我可以使用一个循环来简化这段代码吗?”答案是肯定的!

    由于您的代码重复使用六种主题类型,并且键主题取决于主题类型,因此创建六种类型的列表,然后使用生成器表达式使用next(),可以简化过多的if(如果没有任何相关性,则使用字典)。此外,您可以使用if elif else子句来防止额外的块级别,而不是数组_data

    sampleKeys = [...]
    key = random.choice(sampleKeys)
    
    subjectTypes = ['transaction_recipient_notification', 'transaction_recipient_authentication',
                    'transaction_recipient_verification', 'transaction_account_verification',
                    'transaction_account_tokenization', 'transaction_recipient_payment']
    
    if '_issuers' in key:
        keySubject = next(t + '_issuers' for t in subjectTypes if t in key)
    elif '_field_results' in key:
        keySubject = next(t + '_field_results' for t in subjectTypes if t in key)
    else:
        keySubject = next(t for t in subjectTypes if t in key)
    
    print(f'BEFORE ===> {key}')
    print(f'AFTER  ===> {keySubject}')
    
     类似资料:
    • Erlang提供case语句,可用于根据case语句的输出执行表达式。 本声明的一般形式是 - 语法 (Syntax) case expression of value1 -> statement#1; value2 -> statement#2; valueN -> statement#N end. 本声明的一般工作如下 - 要评估的表达式放在case语句中。 这通常会评估为

    • 除非编译器强制要求,括号在 case 语句里面是不必要的。但是当一个 case 包含了多行语句的时候,需要加上括号。 switch (condition) { case 1: // ... break; case 2: { // ... // Multi-line example using braces

    • 主要内容:语法,示例Erlang 提供 case 语句,它可以用于执行基于 case 语句的输出表达式。这个语句的一般形式是 - 语法 这条语句一般工作如下 - 待计算的表达式被放置在 case 语句中。这通常将计算为一个值在随后的语句中使用。 每个值都通过 case 表达式评估匹配排除其它。根据它的值是 true 时,case 中后续的语句将被执行。 下图显示了 case 语句的流程。 下面的程序是在 Erlang

    • 问题内容: 我有一个存储过程。我在这里传递一个布尔值,例如IS_ELIGIBLE。现在,我希望能够编写如下查询: 问题是由于IS_ELIGIBLE不是TABLE_NAME中的列之一,查询出错了。我可以使用if..else即写相同的查询。 但是我将重复两次select语句。我知道我可以创建具有该select语句的函数,这样我就不必重复两次。但是我只是很好奇是否可以在不执行if..else或创建新函数

    • 主要内容:switch 语句格式,嵌套 switch 语句,if 语句和 switch 语句的区别if…else 语句可以用来描述一个“二岔路口”,我们只能选择其中一条路来继续走,然而生活中经常会碰到“多岔路口”的情况。 switch 语句提供了 if 语句的一个变通形式,可以从多个语句块中选择其中的一个执行。 switch 语句格式 switch 语句是 Java 的多路分支语句。它提供了一种基于一个表达式的值来使程序执行不同部分的简单方法。因此,它提供了一个比一系列 if-else-if

    • C语言虽然没有限制 if else 能够处理的分支数量,但当分支过多时,用 if else 处理会不太方便,而且容易出现 if else 配对出错的情况。例如,输入一个整数,输出该整数对应的星期几的英文表示: 运行结果: Input integer number:3↙ Wednesday 对于这种情况,实际开发中一般使用 switch 语句代替,请看下面的代码: 运行结果: Input integ