有没有办法即时创建子类?

发布于 2025-01-05 01:15:00 字数 450 浏览 5 评论 0原文

我正在创建一个游戏,其中我有一个有点复杂的方法来创建实体。

加载关卡时,加载代码会读取一堆 YAML 文件,其中包含所有不同可能单元的属性。它使用 YAML 文件创建一个所谓的 EntityResource 对象。该 EntityResource 对象在生成新单位时充当权威信息源。目标有两个:

  1. 通过对 YAML 文件的输出实施哈希检查来阻止作弊
  2. 通过让所有单元信息都来自单一的权威来源来帮助调试。

然后,这些 EntityResource 对象被输入到 EntityFactory 对象中以生成特定类型的单元。

我的问题如下。有没有办法根据读入的 YAML 文件的内容动态创建 EntityResource 的子类?

另外,我希望为每个 YAML 文件派生的子类分配一个单例元类。有什么注意事项吗?

I'm creating a game in which I have a somewhat complex method for creating entities.

When a level is loaded, the loading code reads a bunch of YAML files that contain attributes of all the different possible units. Using the YAML file, it creates a so-called EntityResource object. This EntityResource object serves as the authoritative source of information when spawning new units. The goal is twofold:

  1. Deter cheating by implementing a hash check on the output of the YAML file
  2. Aid in debugging by having all unit information come from a single, authoritative source.

These EntityResource objects are then fed into an EntityFactory object to produce units of a specific type.

My question is as follows. Is there a way to create sublcasses of EntityResource dynamically, based on the contents of the YAML file being read in?

Also, I would like each of these YAML-file-derived subclasses to be assigned a singleton metaclass. Any caveats?

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

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

发布评论

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

评论(3

方觉久 2025-01-12 01:15:00

我不确定这是否是您要找的,但您可以使用 type 动态创建子类:

SubClass = type('SubClass', (EntityResource,), {})

编辑:要了解 type 的工作原理,您只需翻译如何编写该类并将其转换为 type 调用。例如,如果您想编写如下内容:

class SubClass(EntityResource):
    A=1
    B=2

then,则将被翻译为:

 SubClass = type('SubClass', (EntityResource,), {'A': 1, 'B': 2})

其中:

  • 第一个参数只是类名
  • 第二个参数是父类列表
  • 第三个参数是初始化类对象的字典。这不仅包括类属性,还包括方法。

I'm not sure if this is what you're looking for, but you can use type to create subclasses dynamically:

SubClass = type('SubClass', (EntityResource,), {})

Edit: To understand how type works, you just need to translate how would you write the class and translate that into a type call. For example, if you want to write something like:

class SubClass(EntityResource):
    A=1
    B=2

then, that would be translated to:

 SubClass = type('SubClass', (EntityResource,), {'A': 1, 'B': 2})

where:

  • The first argument is just the class name
  • The second argument is the list of parent classes
  • The third argument is the dictionary initialize the class object. This includes not only class attributes, but also methods.
谁对谁错谁最难过 2025-01-12 01:15:00

可以动态创建子类。这并不意味着您应该这样做。无论如何,我都会提供一个机制。

每个类中的 bases 属性告诉您继承链:

class Animal(object):
    pass

class Dog(Animal):
    pass

print Animal.__bases__
print Dog.__bases__
# prints:
#(<type 'object'>,)
#(<class '__main__.Animal'>,)

因此,__bases__ 是一个具有“继承基”的元组。您可以替换此元组(您不能“追加到它”或“从中弹出”,因为它是一个元组,并且元组是不可变的)。例如,假设您有一个“mixin 类”,它向某些动物子类添加功能,但不向其他动物子类添加功能:

class Animal(object):
    pass

class Dog(Animal):
    pass

class Cat(Animal):
    pass

class TalkMixin(object):
    def talk(self):
        print("I talk like a {0}".format(self.__class__.__name__))

if __name__ == "__main__":

    dog = Dog()
    cat = Cat()

    try:
        dog.talk() 
        cat.talk()
    except AttributeError:
        print("Great - the program raised AttributeError, as expected")

    # now, add the MixIn to the class "Dog", but not to the class
    # "Cat" - do this on the fly:
    old_dog_bases = Dog.__bases__
    Dog.__bases__ = (Animal, TalkMixin)

    # this should be successful!
    dog.talk()

    try:
        cat.talk()
    except AttributeError:
        print("As expected, cat.talk() raised AttributeError")

    # now do the same (add the mixin dynamically - via inheritance) to
    # the Cat
    old_cat_bases = Cat.__bases__
    Cat.__bases__ = (Animal, TalkMixin)

    # this should be successful!
    cat.talk()

    # Now, remove the mixin (drop from the inheritance) for both cats
    # and dogs:
    Dog.__bases__ = old_dog_bases
    Cat.__bases__ = old_cat_bases

    try:
        dog.talk()
        cat.talk()
    except AttributeError:
        print("as expected, they can no longer talk")

产生以下输出:

Great - the program raised AttributeError, as expected
I talk like a Dog
As expected, cat.talk() raised AttributeError
I talk like a Cat
as expected, they can no longer talk

很多人认为 MixIn 类是邪恶的。他们可能是对的!您可以想象,如果您弄乱了 bases 属性,那么您的程序几乎就毁了。所以,就是这样 - 您可以动态更改对象的继承,但这并不意味着您应该(可能是抽象类或概念实现?)

It is possible to create subclasses on the fly. This does not mean that you should. In any case, I will provide a mechanism.

The bases attribute in each class tells you the inheritance chain:

class Animal(object):
    pass

class Dog(Animal):
    pass

print Animal.__bases__
print Dog.__bases__
# prints:
#(<type 'object'>,)
#(<class '__main__.Animal'>,)

So, __bases__ is a tuple with the "inheritance bases". You can replace this tuple (you cannot "append to it" or "pop from it" because it is a a tuple, and tuples are immutable). For example, say that you have a "mixin class" which adds functionalities to some animal subclasses but not others:

class Animal(object):
    pass

class Dog(Animal):
    pass

class Cat(Animal):
    pass

class TalkMixin(object):
    def talk(self):
        print("I talk like a {0}".format(self.__class__.__name__))

if __name__ == "__main__":

    dog = Dog()
    cat = Cat()

    try:
        dog.talk() 
        cat.talk()
    except AttributeError:
        print("Great - the program raised AttributeError, as expected")

    # now, add the MixIn to the class "Dog", but not to the class
    # "Cat" - do this on the fly:
    old_dog_bases = Dog.__bases__
    Dog.__bases__ = (Animal, TalkMixin)

    # this should be successful!
    dog.talk()

    try:
        cat.talk()
    except AttributeError:
        print("As expected, cat.talk() raised AttributeError")

    # now do the same (add the mixin dynamically - via inheritance) to
    # the Cat
    old_cat_bases = Cat.__bases__
    Cat.__bases__ = (Animal, TalkMixin)

    # this should be successful!
    cat.talk()

    # Now, remove the mixin (drop from the inheritance) for both cats
    # and dogs:
    Dog.__bases__ = old_dog_bases
    Cat.__bases__ = old_cat_bases

    try:
        dog.talk()
        cat.talk()
    except AttributeError:
        print("as expected, they can no longer talk")

Produces the following output:

Great - the program raised AttributeError, as expected
I talk like a Dog
As expected, cat.talk() raised AttributeError
I talk like a Cat
as expected, they can no longer talk

A lot of people consider MixIn classes evil. And they may be right! You can imagine that if you mess up the bases attribute, you pretty much destroyed your program. So, there it is - you can dynamically change the inheritance of an object, but it does not mean you should (probably abstract classes or concept implementation?)

看透却不说透 2025-01-12 01:15:00

当我听到“动态创建子类”时,我理解“动态创建行为不同的对象”,这实际上是一个配置问题。

有没有什么东西是您无法通过读取某些数据并创建一个对象来获得的,该对象根据读取的内容来决定它的行为方式?

这是一个比喻:我是一个手巧的人——我可以组装你扔给我的任何宜家物品。但我每次都不是不同的人,我只是同一个人,阅读不同的图表并寻找不同类型的螺钉和木块。这就是我认为子类化不是自然解决方案的原因。

When I hear "creating subclasses on the fly" I understand "create objects that behave differently on the fly", which is really a question of configuration.

Is there anything you need that you can't get by just reading in some data and creating an object that decides how it is going to behave based on what it reads?

Here's the metaphor: I'm a handy guy -- I can put together any IKEA item you throw at me. But I'm not a different person each time, I'm just the same handy guy reading a different set of diagrams and looking for different kinds of screws and pieces of wood. That's my reasoning for subclassing not being the natural solution here.

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