Python:使用用户输入作为类名的类工厂

San*_*o98 11 python factory metaprogramming metaclass

我想动态地将类atttributes添加到超类.此外,我想创建动态继承自这个超类的类,这些子类的名称应该取决于用户输入.

有一个超类"单元",我可以在运行时添加属性.这已经有效了.

def add_attr (cls, name, value):
    setattr(cls, name, value)

class Unit(object):
    pass

class Archer(Unit):
    pass

myArcher = Archer()
add_attr(Unit, 'strength', 5)
print "Strenght ofmyarcher: " + str(myArcher.strength)
Unit.strength = 2
print "Strenght ofmyarcher: " + str(myArcher.strength)
Run Code Online (Sandbox Code Playgroud)

这导致了期望的输出:
肌肉的强度:5个
强度的肌肉:2

但是现在我不想预定义子类Archer,但我宁愿让用户决定如何调用这个子类.我尝试过这样的事情:

class Meta(type, subclassname):
    def __new__(cls, subclassname, bases, dct):
    return type.__new__(cls, subclassname, Unit, dct)

factory = Meta()    
factory.__new__("Soldier")  
Run Code Online (Sandbox Code Playgroud)

但没有运气.我想我还没有真正理解这里的功能.我想要的结果是

class Soldier(Unit):
    pass
Run Code Online (Sandbox Code Playgroud)

由工厂创建.如果我用"Knight"这个参数调用工厂,我会想要创建一个类Knight,Unit的子类.

有任何想法吗?提前谢谢了!
再见 -
萨诺

Dev*_*rre 14

要从名称创建类,请使用该class语句并指定名称.注意:

def meta(name):
    class cls(Unit):
        pass

    cls.__name__ = name
    return cls
Run Code Online (Sandbox Code Playgroud)

现在我想我应该解释自己,等等.使用class语句创建类时,它是动态完成的 - 它相当于调用type().

例如,以下两个代码段执行相同的操作:

class X(object): pass
X = type("X", (object,), {})
Run Code Online (Sandbox Code Playgroud)

类的名称 - 类型的第一个参数 - 被分配给__name__,并且基本上是它的结束(唯一的时间__name__本身可能在默认__repr__()实现中).要创建一个具有动态名称的类,您实际上可以像这样调用类型,或者您可以稍后更改类名.该class语法存在是有原因的,though--很方便,而且很容易添加到后来改变的事情.例如,如果你想添加方法,那就是

class X(object):
    def foo(self): print "foo"

def foo(self): print "foo"
X = type("X", (object,), {'foo':foo})
Run Code Online (Sandbox Code Playgroud)

等等.所以我建议使用类声明 - 如果你知道你可以从一开始就这样做,你可能会这样做.处理type等等是一团糟.

(顺便说一句,你不应该type.__new__()只是手工打电话type())


Fel*_*ing 7

看看type()内置函数.

knight_class = type('Knight', (Unit,), {})
Run Code Online (Sandbox Code Playgroud)
  • 第一个参数:新类的名称
  • 第二个参数:父类的元组
  • 第三个参数:类属性的字典.

但在你的情况下,如果子类没有实现不同的行为,可能给Unit类一个name属性就足够了.