让家长班从班级工厂归还孩子

时间:2019-03-04 23:01:41

标签: python metaprogramming

我有一个父类,所以我想做一个父类,以便可以从类工厂返回它的子类,这是一些代码:

class Super:
    def __new__(cls, t):
        return class_factory(t)

# Because I need a Super class with some custom state
def class_factory(t):
    class Sub(Super):
        t = t

        def __init__(self):
            pass

    return Sub

assert isinstance(Super(1)(), Super)

我收到以下错误:

TypeError: __new__() missing 1 required positional argument: 't'

我知道它试图调用Super的{​​{1}}方法。有没有一种方法可以跳过它,或者至少以不引起无限递归的方式保留类型签名? (我需要保留两个类的类型签名)。

2 个答案:

答案 0 :(得分:1)

当我运行您的代码时,出现另一个错误,即:

cvxpy

numpy行上。

这是因为NameError: name 't' is not defined语句的主体是在其自己的名称空间中执行的,因此封闭名称空间中的t = t不在正常范围内。另一个问题是您的class没有调用其基类't

最后,对__new__()的调用是错误的。调用类将返回该类的实例(在本例中为子类的实例)。

要解决所有这些问题并使代码正常工作,您可能需要这样做:

__new__()

更新

根据您的评论,我建议改用类装饰器。 —像这样:

Super(1)()

这不会创建子类,但是您可以根据需要更改修饰类的名称。

答案 1 :(得分:0)

这可能有效:

class Super:
    def __new__(cls, t):
        return class_factory(t)

def class_factory(t):
    class Sub(Super):
        _tp = t
        def __new__(cls, *args, **kwargs):
            instance = object.__new__(cls)
            return instance

        def __init__(self, *args, **kwargs):
            pass

    return Sub

为避免错误,您需要在__new__()中定义自定义Sub方法,因此可以避免递归调用Super的{​​{1}}方法。
该类型保留在__ new__()的{​​{1}}类属性中。

使用此代码,_tp不会引发任何错误。

评论后编辑

修复了Subassert isinstance(Super(1)(), Super)。规则是*args也必须使用**kwargs中使用的任何参数签名。例如,如果您需要Sub.__init__(),那么您应该拥有Sub.__new__()

相关问题