11

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

有一个超类“Unit”,我可以在运行时向其中添加属性。这已经奏效了。

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)

这将导致所需的输出:
Myarcher 的强度:5
Myarcher 的强度:2

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

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

factory = Meta()    
factory.__new__("Soldier")  

但没有运气。我想我还没有真正理解new在这里做了什么。结果我想要的是

class Soldier(Unit):
    pass

由工厂创建。如果我用参数“Knight”调用工厂,我想创建一个 Knight 类,Unit 的子类。

有任何想法吗?提前谢谢了!
再见
-佐野

4

2 回答 2

14

要从名称创建类,请使用class语句并指定名称。观察:

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

    cls.__name__ = name
    return cls

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

例如,以下两个片段做同样的事情:

class X(object): pass
X = type("X", (object,), {})

类的名称——类型的第一个参数——被分配给__name__,这基本上是结束(唯一__name__使用的时间本身可能是在默认__repr__()实现中)。要创建具有动态名称的类,您实际上可以像这样调用 type,或者您可以稍后更改类名。不过,class语法的存在是有原因的——它很方便,而且以后很容易添加和更改。例如,如果您想添加方法,它将是

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

def foo(self): print "foo"
X = type("X", (object,), {'foo':foo})

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

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

于 2010-03-17T11:49:08.030 回答
7

看看type()内置函数。

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

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

于 2010-03-17T11:46:28.910 回答