如何动态设置类名?

时间:2011-03-18 13:39:02

标签: python

我有一个函数可以创建从它的参数派生的类:

def factory(BaseClass) :
    class NewClass(BaseClass) : pass
    return NewClass

现在,当我使用它来创建新类时,这些类的名称都相同,并且实例看起来像它们具有相同的类型:

NewA = factory(ClassA)
NewB = factory(ClassB)
print type(NewA()) # <class __main__.NewClass>
print type(NewB()) # <class __main__.NewClass>

是否需要手动设置__name__属性?

NewA.__name__ = 'NewA'
print type(NewA()) # <class __main__.NewA>

当我在这里时,我还应该设置其他任何东西吗?

3 个答案:

答案 0 :(得分:42)

是的,设置__name__是正确的做法;你不需要设置任何其他东西来调整类名。

例如:

def factory(BaseClass) :
    class NewClass(BaseClass): pass
    NewClass.__name__ = "factory_%s" % BaseClass.__name__
    return NewClass

type错误的在这里使用的东西。它不允许您使用Python's normal class syntax定义类,而是让您手动设置每个类属性。它用于手动创建类,例如如果你有一个基类数组,并且你想用它创建一个类(你不能用Python的类语法)。不要在这里使用它。

答案 1 :(得分:13)

使用带有三个参数的type()函数进行检查。以下代码创建了一个新类“NewA”,其中object为基本类型,没有初始属性。

>>> type('NewA', (object,), {})
<class '__main__.NewA'>

答案 2 :(得分:3)

更新Glenn Maynard的答案:如今有__name__属性和__qualname__属性。首先是您可能会想到的;第二个是嵌套类的点缀“路径”。

如果是“简单”类,则两者相等。只需将__name____qualname__设置为您的新名称。您应该同时设置两个属性,因为不能确定将显示哪个第三方代码。

现在,对于嵌套类,两个属性之间的差异显示:

class Outer:
    class Inner:
        pass
print(Outer.__name__, Outer.__qualname__)
print(Outer.Inner.__name__, Outer.Inner.__qualname__)

打印:

Outer Outer
Inner Outer.Inner

如果要更改Outer的名称,则需要打3个位置,即Outer.__name__Outer.__qualname__Inner.__qualname__。对于后两个,您需要正确分割并连接点。

最后的警告:即使您做了所有正确的操作,狮身人面像,皮林特等东西仍可能无法100%正常工作。例如,不能像往常一样在模块名称空间中找到虚假名称。无法为类定义grep填充源;等等。