Python 如何动态设置类名?
我有一个函数,可以创建从其参数派生的类:Python 如何动态设置类名?,python,Python,我有一个函数,可以创建从其参数派生的类: def factory(BaseClass) : class NewClass(BaseClass) : pass return NewClass 现在,当我使用它创建新类时,这些类的名称都是相同的,实例的类型看起来也一样: NewA = factory(ClassA) NewB = factory(ClassB) print type(NewA()) # <class __main__.NewClass> print ty
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>
当我进行设置时,是否还有其他需要设置的内容?使用带有三个参数的函数进行检查。下面的代码创建了一个新类“NewA”,其基本类型为object
,没有初始属性
>>> type('NewA', (object,), {})
<class '__main__.NewA'>
>>类型('NewA',(对象,),{})
是的,设置\uuuu name\uuuu
是正确的做法;您不需要设置任何其他内容来调整类名
例如:
def factory(BaseClass) :
class NewClass(BaseClass): pass
NewClass.__name__ = "factory_%s" % BaseClass.__name__
return NewClass
类型
在这里使用是错误的。它不允许您使用定义类,而是让您手动设置每个类属性。它用于手动创建类,例如,如果您有一个基类数组,并且希望使用它创建一个类(这是Python的类语法无法做到的)。不要在这里使用它。更新格伦·梅纳德的答案:现在有了\uuuuuu name\uuuuuuu
属性和\uuuu qualname\uuuuu
属性。第一个是你的想法;第二个是嵌套类的虚线“路径”
在“简单”类的情况下,两者是相等的。只需将\uuuu name\uuuuu
和\uuuu qualname\uuuu
设置为您的新名称。您应该设置这两个属性,因为您无法确定第三方代码将查看哪一个
现在,对于嵌套类,两个属性之间的差异显示:
class Outer:
class Inner:
pass
print(Outer.__name__, Outer.__qualname__)
print(Outer.Inner.__name__, Outer.Inner.__qualname__)
印刷品:
Outer Outer
Inner Outer.Inner
如果您想更改外部
的名称,您需要修补三个位置,即外部。\uuuuu name\uuuuuuu
,外部。\uuuuuuuu质量名称
,内部。\uuuuuu质量名称
。对于后两种情况,您需要在点处正确拆分和连接
最后一个警告:即使你做得很好,像斯芬克斯,派林,等等。。。可能仍然无法100%工作。例如,像往常一样,在模块名称空间中找不到假名称;类定义的源不能是
grep
ped;等等。如果NewClass中的类定义很长,则看起来有点笨拙。我必须将所有方法累加到一个字典中(我假设doc字符串也在那里,在键“\uu doc\uu”
下)。另外,如果NewClass中的方法必须动态引用基类的方法,该怎么办?type
用于创建具有可变基列表的类;这完全是一个错误的工具。@kiyo:在您的示例代码中,NewClass除了名称和基类之外没有定义任何东西,所以这个方法可以很好地工作。如果您的新类将在其中包含实际属性,那么是的,更改\uuuuu name\uuuuu
是很好的选择。但是,这两个方法的功能都一样好。如果访问由type()创建的类,则会出现NameError。我该怎么解决呢?不再正确了,现在你还需要更改qualname。请看@TorbenKlein我们现在需要同时设置\uuuuuqualname\uuu
和\uuuu name\uuuu
还是只设置\uuuuqualname\uuuuu
:\uuuu qualname\uuuu=“工厂%s”%BaseClass__qualname_uu。这使得类创建期间的钩子(例如元类或\uuuu init\u子类)可以看到“正确”的名称。我发现我还必须更改\uuuu模块\uuuuu
以完全模拟类名。如果您需要使用str()
中使用的名称,这是正确的答案。
Outer Outer
Inner Outer.Inner