【问题标题】:Accessing dictionary inside a dictionary as attribute in python访问字典中的字典作为python中的属性
【发布时间】:2021-10-08 23:39:10
【问题描述】:

我正在使用字典在 python 中制作一个简单的实体组件系统(我听说它们在某种程度上具有更好的性能),但我不想访问像foo['bar']['x'] 这样的数据,我想访问它更像foo.bar.x(只是个人喜好)

所以我做了这个代码

class Entity(dict):
    def __init__(self, dictionary={}):
        super().__init__(dictionary)

    def __getattr__(self, attribute):
        return self[attribute]

foo = Entity([('PositionComponent', {'x': 0, 'y': 0})])

所以,我可以使用 foo.PositionComponent 访问 PositionComponent 但我无法以foo.PositionComponent.x

的形式访问 x 值

我怎样才能让它工作?有没有更好的方法来制作我已经制作的东西?


更新

我用python做了三个版本的同一个ECS

  1. 使用实体类而不扩展 dict foo.component(bar).x(foo.component 中的 for 循环)
  2. 使用实体类扩展字典foo['bar']['x']
  3. 使用实体类扩展 dict 并使用自定义 __getattr__ foo.bar.x 访问组件

使用粒子系统,屏幕上随时有133个粒子,作为测试我得到了每个ECS的FPS

这是结果:

  1. FPS 大约 750
  2. FPS 大约 1050
  3. FPS 大约 500

因此这证明使用自定义 __getattr__ 会使代码运行速度比使用普通字典慢 2 倍

屏幕上的最大粒子数

(左:FPS,右粒子)
(禁用颜色,即使半径为 0 也会绘制圆)
(12000 达到 30 FPS)

【问题讨论】:

    标签: python python-3.x dictionary


    【解决方案1】:

    您无法访问 x 值,因为它属于 dict 实例,而不是 Entity 实例。一种可能的解决方法是只使用Entity

    此外,由于您继承自 dict,因此您可以使用 **kwargs 来构建您的对象。

    class Entity(dict):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
    
        def __getattr__(self, attribute):
            return self[attribute]
    
    foo = Entity(PositionComponent=Entity(x=0, y=1))
    print(foo.PositionComponent.x)
    >>> 0
    

    【讨论】:

    • 如果我使用 kwargs 它会给出这个错误TypeError: __init__() takes 1 positional argument but 2 were given。第一部分效果很好
    • @Nath 你能分享一下你是如何使用它的吗?
    • 哦,我发现了问题,我像之前 Entity([('PositionComponent', {'x': 0, 'y': 0})]) 所做的那样声明实体,当我使用 Entity(PositionComponent = Entity(x=0,y=1)) 时它起作用了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-27
    • 2021-09-20
    • 1970-01-01
    • 2015-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多