【问题标题】:Meta-programming - How to generate class from template when __class__ is used?元编程 - 使用 __class__ 时如何从模板生成类?
【发布时间】:2019-12-09 11:45:27
【问题描述】:

我创建了这样的类来解决签名和特征名称的问题:

import copy
from sklearn.feature_selection import VarianceTreshold


class VarianceThresholdN(VarianceThreshold):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.feature_names = None

    #hack from https://stackoverflow.com/questions/51430484/how-to-subclass-a-vectorizer-in-scikit-learn-without-repeating-all-parameters-in    
    def get_params(self, deep=True): 
        params = super().get_params(deep)
        cp = copy.copy(self)
        cp.__class__ = VarianceThreshold
        params.update(cp.__class__.get_params(cp, deep))
        return params

    def fit(self, X, y=None):
        self.feature_names = list(X.columns)
        return super().fit(X, y)

不幸的是,我需要创建很多这样的类,所以需要大量复制粘贴和替换两件事: class VarianceThresholdN(VarianceThreshold):class DifferentClassN(DifferentClass):cp.__class__ = VarianceThresholdcp.__class__ = DifferentClass

所以有一个明确的模板,但是由于cp.__class__ = ...我不能使用mix-ins。

可能这段代码可以使用 jinja 模板生成,但是有什么方法可以避免它,使用元编程中的一些 Python 技巧?

【问题讨论】:

    标签: python python-3.x oop scikit-learn metaprogramming


    【解决方案1】:

    我真的不明白那应该做什么,据我所知,您几乎只是调用了 super() 两次,而第二个版本明确地这样做了。

    可能这段代码可以使用 jinja 模板生成,但是有什么方法可以避免它,使用元编程中的一些 Python 技巧?

    如果您的模式是您总是想“交换”self.__class__ 为其父级,您可以使用__bases__mro()[1] 访问它:

    • cls.__bases__cls 的所有超类的元组,这正是您放入括号中的内容(不包括 kwargs)
    • cls.mro() 是“方法解析顺序”,它适用于这种特定(完全线性)的情况:它是处理属性或方法调用时要经过的所有类的序列,从 cls 开始(包括)和以 object 结尾(这是所有 Python 类的原始祖先)。

    【讨论】:

    • 如果您的意思是用cp.__class__ = cp.__class__.__bases__[-1] 替换cp.__class__ = VarianceThreshold,它似乎适用于我的情况。谢谢!
    • 是的。如果您使用的是__bases__,那么__bases__[0] 也应该可以工作:您的__bases__ 是一个具有单个元素的元组。
    • 感谢您的确认。在我原来的情况下,我在基类的“左侧”也有一些混合,在这种情况下,我需要获取元组的最后一个元素,所以 [-1]。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 2023-03-20
    • 2013-02-18
    • 1970-01-01
    相关资源
    最近更新 更多