【问题标题】:Can I write program logic operating on opcodes without a big if/elif/elif/... block? [duplicate]我可以在没有大 if/elif/elif/... 块的情况下编写在操作码上运行的程序逻辑吗? [复制]
【发布时间】:2020-12-22 19:32:09
【问题描述】:

让我用一些代码更好地解释一下。

class Opcode (Enum):
    WEEK=    1
    EMAIL=   2
    NAME=    3
    DOB=     4

然后我有一个参数类,它处理服务器接收到的数据,并将其存储在适当的变量中:

class parameters:
    week = None
    email = None
    name = None
    dob = None
    
    def __init__(self, conn):
        #some initialization stuff, irrelevant
        
    def process_input(self, opcode, data):
        if opcode == Opcode.WEEK.value:
            self.week = data
            
        elif opcode == Opcode.EMAIL.value:
            self.email= data
         
        elif opcode == Opcode.NAME.value:
            self.name= data

        elif opcode == Opcode.DOB.value:
            self.dob= data
         .
         .
         .
 
        else :
            print("unknown opcode provided. disconnecting ... ")
            #disconnect from client ...

只有 4 个操作码,这似乎不好,但实际上我的程序有 12 个操作码,所以这个长 if...elif...elif...else 分支似乎是处理输入的一种不好的方式。我习惯使用 C++,在这种情况下我会使用 switch-case,但它们在 python 中似乎不是一个东西,所以也许有一个我不知道的更好的解决方案。有什么建议吗?

【问题讨论】:

  • 使用字典去掉if/elif
  • networkingserver 与它有什么关系是个谜。

标签: python


【解决方案1】:

正如我在评论中建议的那样,使用字典将提供一种避免if/elif 语句系列的方法。它也将比执行它们(对于大量操作码)更快,并且可以以使其主要由数据驱动的方式实现,因此非常易于扩展 - 只需向 enum 添加更多值。

import enum

class Opcode(enum.IntEnum):
    WEEK = 1
    EMAIL = 2
    NAME = 3
    DOB = 4

# Create a dictionary mapping Opcode values to lowercase attribute names.
opcode_dict = {opcode.value: opcode.name.lower() for opcode in Opcode}
print(opcode_dict)


class Parameters:
    def __init__(self, conn):
        #some initialization stuff, irrelevant
        ...

    def process_input(self, opcode, data):
        try:
            setattr(self, opcode_dict[opcode], data)
        except KeyError:
            print("unknown opcode provided. disconnecting...")
            # Disconnect from client...

    def __repr__(self):
        pairs = ', '.join('{}={!r}'.format(attrname, getattr(self, attrname, None))
                                            for attrname in opcode_dict.values())
        return '{}({})'.format(type(self).__name__, pairs)


if __name__ == '__main__':

    import random

    params = Parameters(None)
    for opcode in Opcode:
        params.process_input(opcode, random.randint(1, 10))
        print(params)

    # Try a bogus opcode.
    params.process_input(42, random.randint(1, 10))

【讨论】:

  • 马蒂诺!你不知道你得到了多少帮助。非常感谢您的后续回答,我一定会实施。
  • jf192210:不客气。请注意,_repr__() 方法是严格可选的,只是为了使打印类的实例提供更多信息。
  • 啊,无论如何我都挺喜欢的,所以我会保留它以便更整洁地调试啊哈
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-17
  • 1970-01-01
  • 1970-01-01
  • 2017-07-03
  • 2021-04-21
相关资源
最近更新 更多