如何在Python中实现下面的C代码? (typedef、枚举和开关)
How to implement the following C code in Python? (typedef, enums and switch)
我在 C 中有以下部分代码:
typedef enum {
CAN_NORMAL_MODE = 0x00,
CAN_SLEEP_MODE = 0x01,
CAN_INTERNAL_LOOPBACK_MODE = 0x02,
CAN_LISTEN_ONLY_MODE = 0x03,
CAN_CONFIGURATION_MODE = 0x04,
CAN_EXTERNAL_LOOPBACK_MODE = 0x05,
CAN_CLASSIC_MODE = 0x06,
CAN_RESTRICTED_MODE = 0x07,
CAN_INVALID_MODE = 0xFF
} CAN_OPERATION_MODE;
//more code here in the middle...
d = something
switch (d) {
case CAN_NORMAL_MODE:
mode = CAN_NORMAL_MODE;
break;
case CAN_SLEEP_MODE:
mode = CAN_SLEEP_MODE;
break;
// more cases here, not shown for readability
default:
mode = CAN_INVALID_MODE;
break;
}
这里d是我从其他来源读取的一个字节。 switch 语句在另一个函数中,还有更多代码,但我认为没有必要显示,因为它与这部分无关。
我的问题是:由于某些原因,我正在尝试将翻译此代码Python,以便它在语法上相似 到原始 C 代码(也就是说,我不希望 Python 代码完全不同,因此使用过原始 C 代码的另一个人可以轻松理解和使用 Python 代码)。我不确定如何在不执行无穷无尽的 if-elif...else 语句的情况下以 Python 语言实现此代码片段中的功能。我认为应该有一种更简单的(pythonic)方法来做到这一点,但我不确定如何实现 typedef、enum 和 [= Python 中的 24=]switch 语句。我已经阅读了一些实现 enum 子句的方法,创建一个 class 并将别名和值作为属性,如下所示:
class myClass():
def __init__(self):
self.CAN_NORMAL_MODE = 0x00
self.CAN_SLEEP_MODE = 0x01
self.CAN_INTERNAL_LOOPBACK_MODE = 0x02
#etc
我在Python中也遇到了一个巧妙的实现switch语句的方法,函数如下(与我的实际问题无关,只是为了展示实现的结构):
def switch(argument):
switcher = {
1: "January",
2: "February",
3: "March",
4: "April",
5: "May",
6: "June",
7: "July",
8: "August",
9: "September",
10: "October",
11: "November",
12: "December"
}
print switcher.get(argument, "Invalid month")
但我想不出一种以简单易懂的方式将这两件事结合起来的方法。
谢谢你,祝你有愉快的一天!
字典怎么样?您可以将每个值分配给相应的模式,然后调用它:
modes = {
0x00 : 'CAN_NORMAL_MODE',
0x01 : 'CAN_SLEEP_MODE',
0x02 : 'CAN_INTERNAL_LOOPBACK_MODE',
0x03 : 'CAN_LISTEN_ONLY_MODE',
0x04 : 'CAN_CONFIGURATION_MODE',
0x05 : 'CAN_EXTERNAL_LOOPBACK_MODE',
0x06 : 'CAN_CLASSIC_MODE',
0x07 : 'CAN_RESTRICTED_MODE',
0xFF : 'CAN_INVALID_MODE'
}
d = something
mode = modes[d]
from enum import IntEnum
class CAN_OPERATION_MODE(IntEnum):
NORMAL_MODE = 0x00
SLEEP_MODE = 0x01
INTERNAL_LOOPBACK_MODE = 0x02
LISTEN_ONLY_MODE = 0x03
CONFIGURATION_MODE = 0x04
EXTERNAL_LOOPBACK_MODE = 0x05
CLASSIC_MODE = 0x06
RESTRICTED_MODE = 0x07
INVALID_MODE = 0xFF
@classmethod
def _missing_(cls, value):
return cls.INVALID_MODE
d = something
mode = CAN_OPERATION_MODE(d)
我还会从所有枚举名称中删除 _MODE
。
对于枚举本身,您似乎让它变得比需要的更难。枚举可以非常干净地映射到仅包含一堆变量定义的 python 模块,例如:
can_operation_mode.py:
CAN_NORMAL_MODE = 0x00
CAN_SLEEP_MODE = 0x01
CAN_INTERNAL_LOOPBACK_MODE = 0x02
CAN_LISTEN_ONLY_MODE = 0x03
CAN_CONFIGURATION_MODE = 0x04
CAN_EXTERNAL_LOOPBACK_MODE = 0x05
CAN_CLASSIC_MODE = 0x06
CAN_RESTRICTED_MODE = 0x07
CAN_INVALID_MODE = 0xFF
这提供了有用的命名空间(C 枚举没有),而且还能够将这些名称导入另一个模块以便使用它们的 C 风格,而无需模块名称。当然,权衡是它们是可修改的。
至于 switch
,不,Python 没有直接模拟 C 的 switch
,至少如果你取消 if
的资格,则不会else if
/ else
您在问题中描述的构造:
other_module.py:
import can_operation_mode.*
d = something
if d == CAN_NORMAL_MODE:
mode = CAN_NORMAL_MODE
elif d == CAN_SLEEP_MODE:
mode = CAN_SLEEP_MODE
// more cases here ...
else:
mode = CAN_INVALID_MODE
不过,坦率地说,从保持与原始 C 的句法相似性的角度来看,我看不出这有什么问题。它看起来与我非常相似,直到冒号的使用。
我在 C 中有以下部分代码:
typedef enum {
CAN_NORMAL_MODE = 0x00,
CAN_SLEEP_MODE = 0x01,
CAN_INTERNAL_LOOPBACK_MODE = 0x02,
CAN_LISTEN_ONLY_MODE = 0x03,
CAN_CONFIGURATION_MODE = 0x04,
CAN_EXTERNAL_LOOPBACK_MODE = 0x05,
CAN_CLASSIC_MODE = 0x06,
CAN_RESTRICTED_MODE = 0x07,
CAN_INVALID_MODE = 0xFF
} CAN_OPERATION_MODE;
//more code here in the middle...
d = something
switch (d) {
case CAN_NORMAL_MODE:
mode = CAN_NORMAL_MODE;
break;
case CAN_SLEEP_MODE:
mode = CAN_SLEEP_MODE;
break;
// more cases here, not shown for readability
default:
mode = CAN_INVALID_MODE;
break;
}
这里d是我从其他来源读取的一个字节。 switch 语句在另一个函数中,还有更多代码,但我认为没有必要显示,因为它与这部分无关。
我的问题是:由于某些原因,我正在尝试将翻译此代码Python,以便它在语法上相似 到原始 C 代码(也就是说,我不希望 Python 代码完全不同,因此使用过原始 C 代码的另一个人可以轻松理解和使用 Python 代码)。我不确定如何在不执行无穷无尽的 if-elif...else 语句的情况下以 Python 语言实现此代码片段中的功能。我认为应该有一种更简单的(pythonic)方法来做到这一点,但我不确定如何实现 typedef、enum 和 [= Python 中的 24=]switch 语句。我已经阅读了一些实现 enum 子句的方法,创建一个 class 并将别名和值作为属性,如下所示:
class myClass():
def __init__(self):
self.CAN_NORMAL_MODE = 0x00
self.CAN_SLEEP_MODE = 0x01
self.CAN_INTERNAL_LOOPBACK_MODE = 0x02
#etc
我在Python中也遇到了一个巧妙的实现switch语句的方法,函数如下(与我的实际问题无关,只是为了展示实现的结构):
def switch(argument):
switcher = {
1: "January",
2: "February",
3: "March",
4: "April",
5: "May",
6: "June",
7: "July",
8: "August",
9: "September",
10: "October",
11: "November",
12: "December"
}
print switcher.get(argument, "Invalid month")
但我想不出一种以简单易懂的方式将这两件事结合起来的方法。 谢谢你,祝你有愉快的一天!
字典怎么样?您可以将每个值分配给相应的模式,然后调用它:
modes = {
0x00 : 'CAN_NORMAL_MODE',
0x01 : 'CAN_SLEEP_MODE',
0x02 : 'CAN_INTERNAL_LOOPBACK_MODE',
0x03 : 'CAN_LISTEN_ONLY_MODE',
0x04 : 'CAN_CONFIGURATION_MODE',
0x05 : 'CAN_EXTERNAL_LOOPBACK_MODE',
0x06 : 'CAN_CLASSIC_MODE',
0x07 : 'CAN_RESTRICTED_MODE',
0xFF : 'CAN_INVALID_MODE'
}
d = something
mode = modes[d]
from enum import IntEnum
class CAN_OPERATION_MODE(IntEnum):
NORMAL_MODE = 0x00
SLEEP_MODE = 0x01
INTERNAL_LOOPBACK_MODE = 0x02
LISTEN_ONLY_MODE = 0x03
CONFIGURATION_MODE = 0x04
EXTERNAL_LOOPBACK_MODE = 0x05
CLASSIC_MODE = 0x06
RESTRICTED_MODE = 0x07
INVALID_MODE = 0xFF
@classmethod
def _missing_(cls, value):
return cls.INVALID_MODE
d = something
mode = CAN_OPERATION_MODE(d)
我还会从所有枚举名称中删除 _MODE
。
对于枚举本身,您似乎让它变得比需要的更难。枚举可以非常干净地映射到仅包含一堆变量定义的 python 模块,例如:
can_operation_mode.py:
CAN_NORMAL_MODE = 0x00
CAN_SLEEP_MODE = 0x01
CAN_INTERNAL_LOOPBACK_MODE = 0x02
CAN_LISTEN_ONLY_MODE = 0x03
CAN_CONFIGURATION_MODE = 0x04
CAN_EXTERNAL_LOOPBACK_MODE = 0x05
CAN_CLASSIC_MODE = 0x06
CAN_RESTRICTED_MODE = 0x07
CAN_INVALID_MODE = 0xFF
这提供了有用的命名空间(C 枚举没有),而且还能够将这些名称导入另一个模块以便使用它们的 C 风格,而无需模块名称。当然,权衡是它们是可修改的。
至于 switch
,不,Python 没有直接模拟 C 的 switch
,至少如果你取消 if
的资格,则不会else if
/ else
您在问题中描述的构造:
other_module.py:
import can_operation_mode.*
d = something
if d == CAN_NORMAL_MODE:
mode = CAN_NORMAL_MODE
elif d == CAN_SLEEP_MODE:
mode = CAN_SLEEP_MODE
// more cases here ...
else:
mode = CAN_INVALID_MODE
不过,坦率地说,从保持与原始 C 的句法相似性的角度来看,我看不出这有什么问题。它看起来与我非常相似,直到冒号的使用。