python中的奇淫技巧

由GPT4辅助

setattr

某个场景需要将某个类切换为export专用类:

def change_to_deploy_model(module: nn.Module, **kwargs):
    s = str(type(module))[6:-2].split('.')[-1]
    if s == 'Detect':
        if "topk" in kwargs:
            DetectionforDeploy.topk = kwargs["topk"]
        setattr(module, '__class__', DetectionforDeploy)
        pass

setattr 函数是Python的内置函数,其作用是为对象设置一个新的属性,或者修改现有属性的值。它接受三个参数:对象、属性名称(字符串形式)以及要赋予的新值。

然而,__class__属性在Python中是一个特殊的属性,它用于引用一个对象的类。更改这个属性会导致对象的类型被更改,这可能导致未预期的行为,并且在大多数情况下并不推荐。在一些特殊情况下,更改__class__可能会有用,但这通常只在高级编程或元编程中会出现。

在你的例子中,setattr(module, '__class__', DetectionforDeploy)这一行代码看起来像是在改变module对象的类型,将其类型改为DetectionforDeploy。这意味着module对象将从现在开始,展现出DetectionforDeploy类的行为。

当你使用 setattr 更改一个对象的 __class__ 属性时,你实际上改变了该对象的类型,这对于该对象的行为有很大的影响。新的类可能具有不同的方法和行为,对象现在将以这种新的方式来行为。

然而,对象的状态——也就是它的实例变量——通常不会被自动更新。如果旧的类和新的类具有相同的实例变量,那么这些变量的值将被保留。但如果新的类使用了不同的实例变量,那么这些新变量将不会自动获得任何值,除非新的类的构造器或方法被调用来初始化它们。

此外,如果新的类依赖于某些在其构造器中设置的状态,那么仅仅通过改变 __class__ 属性是不会调用新的类的构造器的,所以可能不会正确地设置这些状态。

另一方面,如果旧的类的实例变量在新的类中没有定义,那么尽管这些变量的值被保留,但新的类可能不会知道如何处理它们,这可能会导致错误。

总的来说,改变一个对象的 __class__ 属性是一个危险的操作,应该在充分理解其后果的情况下谨慎使用。通常,更好的解决方案可能是创建一个新的对象,将旧的对象的状态复制到新的对象中,然后停止使用旧的对象。