如何生成扩展子类?

zour9fqk  于 2021-08-20  发布在  Java
关注(0)|答案(2)|浏览(470)

关闭。这个问题需要更加关注。它目前不接受答案。
**想改进这个问题吗?**编辑这篇文章,更新这个问题,使它只关注一个问题。

昨天关门了。
改进这个问题
tldr:
3个文件:main.py、scriptclass.py、newscript.py
scriptclass:作为脚本蓝图的主类
newscript:scriptclass的一个子类示例
main:每帧运行scriptclass的所有子示例
如能提供这些文件的任何示例,将不胜感激
更短的tldr:除了脚本不是由游戏对象运行之外,如何在python中剽窃unity的脚本api
我无法将我的详细问题放在标题中,因此这里有更好的解释:我如何创建一种脚本类,如unity中的monobehavior,并基于该类创建新脚本?
基本上我想复制unity的脚本系统。我想以某种方式创建一个脚本类,如下所示:

  1. class Script:
  2. def RunAllInstances():
  3. *run all child instances*
  4. def StartAllInstances():
  5. *start all child instances*

并在另一个文件中创建如下内容:

  1. from script import Script
  2. class NewScript(Script):
  3. def run():
  4. print(True)

并创建如下主文件:

  1. from script import Script
  2. Script.StartAllInstances()
  3. while True:
  4. Script.RunAllInstances()

我知道monobehavior很重要,因为如果不将脚本类指定为monobehavior的子类,脚本将无法运行。这难道不意味着script类可以运行它的所有子类吗?unity(也许)通过将脚本作为一个组件,并让gameobjects运行其所有组件来处理这个问题。

yc0p9oo0

yc0p9oo01#

这看起来与注册表模式匹配。基本上,您必须将创建的所有“脚本”子类保存在某个位置,以便以后可以执行它们。有两种方法可以解决这个问题——这一种相对简单-

  1. # main.py
  2. __registry = []
  3. def register_class(cls):
  4. __registry.append(cls)
  5. class Script:
  6. pass
  1. # subclass.py
  2. from main import Script, register
  3. @register
  4. class SubScript(Script):
  5. pass
  1. # runner.py
  2. from main import __registry
  3. for cls in __registry:
  4. cls.run()

另一种方法使用 __init_subclass__ 方法将子类直接存储在注册表对象上-

  1. _subclasses = []
  2. class Script:
  3. def __init_subclass__(cls,**kwargs):
  4. _subclasses.append(cls)
  5. @classmethod
  6. def run_all(cls):
  7. for cls in _subclasses:
  8. cls.run()
  9. class SubScript(Script):
  10. @classmethod
  11. def run(cls):
  12. print("a")
  13. Script.run_all()

最后一种方法是使用元类(尽管magic init方法一直允许我从代码中删除元类,所以我可能更喜欢这样)
这三种方法都有一个警告——如果一个文件没有被导入,注册表就不知道它。您可以将代码放入主文件中搜索目录并导入所有模块,但这不会自动发生。

展开查看全部
wvyml7n5

wvyml7n52#

您可以动态导入模块类并执行它们的 run() 方法,如果它们是主类的子类。
以下是一个例子:
具有这种树状结构:

  1. .
  2. ├── main.py
  3. ├── new_script.py
  4. └── script.py

script.py:

  1. import os
  2. class Script:
  3. def run(self):
  4. print('Running Script class')
  5. def run_all(self):
  6. print('Running all scritps from Script class')
  7. # you can improve listing valid files for your case
  8. valid_files = [
  9. k.split('.')[0] for k in os.listdir() if (
  10. not k.startswith('__') and not k.endswith('__') and (
  11. k != __file__.split(os.sep)[-1]
  12. )
  13. )
  14. ]
  15. for file_name in valid_files:
  16. module = __import__(file_name)
  17. # listing all attributes of the module
  18. for k in dir(module):
  19. cls = getattr(module, k)
  20. # Check if cls have __name__ attribute
  21. if hasattr(cls, '__name__'):
  22. # the imported attribute should be a class
  23. # and should not be the current module class
  24. if isinstance(cls, type) and (
  25. cls.__name__ != self.__class__.__name__
  26. ):
  27. # if the imported module is a subclass
  28. # of the current class; then excecute run method
  29. if issubclass(cls, self.__class__):
  30. cls.run(cls)

新建_script.py:

  1. from script import Script
  2. class NewScript(Script):
  3. def run(self):
  4. print('Running newScript')

main.py:

  1. from script import Script
  2. if __name__ == '__main__':
  3. instance = Script()
  4. instance.run_all()

演示:

  1. $> python main.py

输出:

  1. Running all scritps from Script class
  2. Running newScript
展开查看全部

相关问题