简体   繁体   English

从现有超类实例化子类

[英]instantiate subclass from existing superclass

So I'm interacting with a 3rd party library, which raises exceptions someti0mes, but it raises the same exception for basically everything (specifically suds.WebFault . It's possible however to determine the exact type of exception it is from the data on the exception raised. I'm looking to abstract this exception into exceptions that subclass this type, ie: 所以我正在与第三方库进行交互,这会引发例外情况,但它基本上都会引发相同的异常(特别是suds.WebFault 。但是,有可能从异常引发的数据中确定异常的确切类型。我希望将这个异常抽象为子类化这种类型的异常,即:

from suds import WebFault

class MoreSpecificError(WebFault):
    pass

I like the subclassing, because it won't break existing implementations that expect a WebFault . 我喜欢子类化,因为它不会破坏期望WebFault现有实现。 The problem I'm having is passing the data already on the WebFault into the MoreSpecificError . 我遇到的问题是将WebFault上已有的数据传递给MoreSpecificError What I would like to do is take the existing exception object and just 'turn it into' the subclass, without any changes or re-running __init__ . 我想做的是获取现有的异常对象,然后将其“转换为”子类,不做任何更改或重新运行__init__ What I've done so far to accomplish this is something like: 到目前为止我完成的工作是这样的:

from suds import WebFault

class MoreSpecificError(WebFault):
    # You pass the old WebFault when instantiating this exception.
    # Then it gets poofed into a MoreSpecificError type
    def __new__(cls, internal_fault):
        return internal_fault
    # This is necessary to prevent the parent class' __init__ from being run
    def __init__(self, internal_fault):
        pass

Edit: I now know this doesn't work, the new object will not be of the subclass' type 编辑:我现在知道这不起作用,新对象将不是子类的类型

Which 'works', but the need to put that __init__ that's just a pass feels really gross to me. 哪个“有用”,但是需要把__init__这个只是一个pass感觉真的很重要。 Not to mention some stuff doesn't like custom __new__ methods (read: deepcopy , it's not a choice, the testing framework we use (lettuce) uses it and we're pretty far invested already). 更不用说一些东西不喜欢自定义的__new__方法(阅读: deepcopy ,它不是一个选择,我们使用的测试框架(生菜)使用它,我们已经投入很多)。

I'm wondering if there's a better way to do this? 我想知道是否有更好的方法来做到这一点? I know the ideal way is just to raise the subclass initially, but I'd really rather not start working with a forked copy of this library. 我知道理想的方法是最初提升子类,但我真的不想开始使用这个库的分叉副本。 I'm really hoping there's some magic somewhere in Python I just don't know yet. 我真的希望Python中有一些魔法,我还不知道。

I think this is what you're asking for: 我认为这就是你要求的:

class MoreSpecificError(WebFault):
    def __new__(self, old):
        old.__class__ = MoreSpecificError
        return old

However, it is risky for reasons described here . 但是,由于此处描述的原因,它存在风险。 If all you are doing is catching the exception it should probably work, but no guarantees. 如果您所做的只是捕获异常它应该可以工作,但不能保证。

I still think it'd be better to just actually create a new exception object in the normal way. 我仍然认为以正常方式实际创建一个新的异常对象会更好。 If you're worried about losing the information from the original exception, look in the documentation for that exception to see what information is documented to be part of its public API, and copy that information. 如果您担心丢失原始异常中的信息,请查看该异常的文档,以查看哪些信息记录为其公共API的一部分,并复制该信息。 Code that was relying on exception info that was not part of the original API is not something you need to support with your new API. 依赖于不属于原始API的异常信息的代码不是您需要支持新API的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM