如何从超类中捕获的异常创建子类实例?

2024-09-28 03:20:22 发布

您现在位置:Python中文网/ 问答频道 /正文

以下是我想要达到的目标:

  1. 包对象是通过将数据传递给超类SKBusPacket来创建的。你知道吗
  2. 数据包的子类型在__init__()中确定,并且根据该数据包的子类型(“请求”或“响应”子类型)引发异常。你知道吗
  3. 捕获此异常并将数据传递给子类SKBusRequestPacketSKBusResponsePacket。你知道吗

问题:创建子类的实例将一次又一次地引发上述异常,因为我通过super将初始化参数传递给超类(请参阅代码)。你知道吗

建议的解决方案:通过使用isinstance()检查实例是否是子类之一来避免raise。但我的印象是,这是一个糟糕的做法和非肾盂。你知道吗

我的简化代码:

class SKBusPacket(Packet):
    def __init__(self, *args, **kwargs):
        super(SKBusPacket, self).__init__(*args, **kwargs)

        self.packet_type = self.getSkbPacketType()

        if self.packet_type == 'request':
            raise ActuallySKBusReqPacket
        elif self.packet_type == 'response':
            raise ActuallySKBusPRPacket

    # Here go some attributes and methods common to all packets...

# Both Request and Response packets inherit from base-class "SKBusPacket"
class SKBusRequestPacket
    def __init__(self, *args, **kwargs):
        # Pass init arguments to super-class "SKBusPacket".
        super(SKBusRequestPacket, self).__init__(*args, **kwargs)

class SKBusResponsePacket
    def __init__(self, *args, **kwargs):
        # Pass init arguments to super-class "SKBusPacket".
        super(SKBusResponsePacket, self).__init__(*args, **kwargs)


def log_skbus(raw_pkt):
    try:
        pkt = SKBusPacket(raw_pkt.data)
    except ActuallyRequestPacket:
        pkt = SKBusRequestPacket(raw_pkt.data)
    except ActuallyResponsePacket:
        pkt = SKBusResponsePacket(raw_pkt.data)

Tags: self类型rawinitdefargs子类kwargs
1条回答
网友
1楼 · 发布于 2024-09-28 03:20:22

最好将包类型的检测与实例化过程分开。如果有一个函数detect_type(类似于getSkbPacketType方法),那么

def make_packet(raw_pkt):
    packet_type = detect_type(raw_pkt.data)
    if packet_type == 'request':
        pkt = SKBusRequestPacket(raw_pkt.data)
    elif packet_type == 'response':
        pkt = SKBusResponsePacket(raw_pkt.data)
    return pkt

是你最干净的选择。你知道吗


一个不太干净的选项是实例化一个SKBusPacket,检查packet_type属性,然后实例化正确类型的包。注:没有提出例外情况:

class SKBusPacket(Packet):
    def __init__(self, *args, **kwargs):
        super(SKBusPacket, self).__init__(*args, **kwargs)
        self.packet_type = self.getSkbPacketType()

def log_skbus(raw_pkt):
    pkt = SKBusPacket(raw_pkt.data)
    if pkt.packet_type == 'request':
        pkt = SKBusRequestPacket(raw_pkt.data)
    elif pkt.packet_type == 'response':
        pkt = SKBusResponsePacket(raw_pkt.data)

上述代码的一个问题是SKBusPacket.__init__被调用两次,一次用于确定数据包类型,第二次用于实例化SKBusRequestPacket或SKBusResponsePacket。也许调用很快,而且这个双重实例化过程不是主要的瓶颈。在这种情况下,这种变通方法就足够了。你知道吗

如果没有,则可以通过动态更改实例的类来绕过正常的实例化过程:

def make_packet(raw_pkt):
    pkt = SKBusPacket(raw_pkt.data)
    if pkt.packet_type == 'request':
        pkt.__class__ = SKBusRequestPacket
    elif pkt.packet_type == 'response':
        pkt.__class__ = SKBusResponsePacket
    return pkt

为此,SKBusPacket必须是一个新样式的类。 请注意,如果这样更改类,SKBusRequestPacket.__init__SKBusResponsePacket.__init__不会被调用。它将提供对这些类的方法的pkt访问,但是您需要将任何初始化代码放入make_packet函数本身。你知道吗

相关问题 更多 >

    热门问题