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

发布于 2024-08-25 06:40:36 字数 966 浏览 2 评论 0原文

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

有一个超类“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)

这会产生所需的输出:
我的弓箭手强度: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 的子类。

有什么想法吗?非常感谢!
再见
-佐野

I want to add class atttributes to a superclass dynamically. Furthermore, I want to create classes that inherit from this superclass dynamically, and the name of those subclasses should depend on user input.

There is a superclass "Unit", to which I can add attributes at runtime. This already works.

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)

This leads to the desired output:
Strenght ofmyarcher: 5
Strenght ofmyarcher: 2

But now I don't want to predefine the subclass Archer, but I'd rather let the user decide how to call this subclass. I've tried something like this:

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

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

but no luck. I guess I haven't really understood what new does here.
What I want as a result here is

class Soldier(Unit):
    pass

being created by the factory. And if I call the factory with the argument "Knight", I'd like a class Knight, subclass of Unit, to be created.

Any ideas? Many thanks in advance!
Bye
-Sano

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

壹場煙雨 2024-09-01 06:40:36

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

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

    cls.__name__ = name
    return cls

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

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

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

类的名称(类型的第一个参数)被分配给 __name__,这基本上就结束了(唯一一次 < code>__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()

To create a class from a name, use the class statement and assign the name. Observe:

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

    cls.__name__ = name
    return cls

Now I suppose I should explain myself, and so on. When you create a class using the class statement, it is done dynamically-- it is equivalent of calling type().

For example, the following two snippets do the same thing:

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

The name of a class-- the first argument to type-- is assigned to __name__, and that's basically the end of that (the only time __name__ is itself used is probably in the default __repr__() implementation). To create a class with a dynamic name, you can in fact call type like so, or you can just change the class name afterward. The class syntax exists for a reason, though-- it's convenient, and it's easy to add to and change things later. If you wanted to add methods, for example, it would be

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

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

and so on. So I would advise using the class statement-- if you had known you could do so from the beginning, you likely would have done so. Dealing with type and so on is a mess.

(You should not, by the way, call type.__new__() by hand, only type())

木有鱼丸 2024-09-01 06:40:36

查看 type() 内置函数。

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

但就您而言,如果子类没有实现不同的行为,也许为 Unit 类提供 name 属性就足够了。

Have a look at the type() builtin function.

knight_class = type('Knight', (Unit,), {})
  • First parameter: Name of new class
  • Second parameter: Tuple of parent classes
  • Third parameter: dictionary of class attributes.

But in your case, if the subclasses don't implement a different behaviour, maybe giving the Unit class a name attribute is sufficient.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文