向指向字典中项目的Python类动态添加属性

向指向字典中项目的Python类动态添加属性,python,python-3.x,Python,Python 3.x,为了方便访问dict中的值,我尝试将属性动态附加到类(Registry),我使用defaultdict定义字典,默认值为空的列表 但是,由于我在定义属性时访问字典中列表值的方式,最终所有属性都指向同一个列表对象 要点: 从集合导入defaultdict 从枚举导入枚举 类元素类型(枚举): PHONE=“PHONE” CAR=“CAR” 类注册表: 定义(cls,*ARG,**kwargs): cls.setup_properties() instance=super(注册表,cls)。\uu

为了方便访问dict中的值,我尝试将属性动态附加到类(
Registry
),我使用
defaultdict
定义字典,默认值为空的
列表

但是,由于我在定义属性时访问字典中列表值的方式,最终所有属性都指向同一个列表对象

要点:


从集合导入defaultdict
从枚举导入枚举
类元素类型(枚举):
PHONE=“PHONE”
CAR=“CAR”
类注册表:
定义(cls,*ARG,**kwargs):
cls.setup_properties()
instance=super(注册表,cls)。\uuuuu新的\uuuuuu(cls,*args,**kwargs)
返回实例
定义初始化(自):
self._元素={}
def寄存器(自身、元件类型、项目):
如果元素\u type.value不在self.\u元素中:
self.\u元素[元素类型.值]=[]
self.\u元素[元素类型.值].追加(项)
def get(自身,元素类型):
返回self.\u元素[元素类型.值]
@类方法
def设置_属性(cls):
对于ElementTypes中的项:
prop_name=item.value
prop=属性(lambda self:getattr(self,“get”)(item))
setattr(注册表,prop_name.lower(),prop)
注册表=注册表()
registry.register(ElementTypes.PHONE,“phone1”)
registry.register(ElementTypes.PHONE,“phone2”)
registry.register(ElementTypes.CAR,“car1”)
registry.register(ElementTypes.CAR,“car2”)
断言dict(注册表元素)={
“CAR”:[“car1”、“car2”],
“电话”:[“电话1”、“电话2”],
}
断言hasattr(注册表,“电话”)
断言hasattr(注册表,“car”)
assert registry.car==[“car1”,“car2”]
assert registry.phone=[“phone1”、“phone2”]#此操作失败

如何定义属性为真正动态的代码,并访问dict中的各个列表值?

首先,不要在
\uuuuuu new\uuuu
中设置属性,因为创建的每个
注册表
对象都会调用这些属性!相反,只需在类定义之外指定属性

其次,这会让很多人感到困惑,但是如果在for循环中使用
lambda
,并且希望使用
item
变量,则需要确保添加名为
item
的参数,默认值为
item
,否则,所有属性都将引用循环的最后一个

class Registry:
    def __init__(self):
        self._elements = defaultdict(list)

    def register(self, element_type, item):
        self._elements[element_type.value].append(item)

    def get(self, element_type):
        return self._elements[element_type.value]


for item in ElementTypes:
    prop_name = item.value
    prop = property(lambda self, item=item: self.get(item))

    setattr(Registry, prop_name.lower(), prop)

首先,不要在
\uuuuu new\uuuu
中设置属性,因为创建的每个
注册表
对象都会调用这些属性!相反,只需在类定义之外指定属性

其次,这会让很多人感到困惑,但是如果在for循环中使用
lambda
,并且希望使用
item
变量,则需要确保添加名为
item
的参数,默认值为
item
,否则,所有属性都将引用循环的最后一个

class Registry:
    def __init__(self):
        self._elements = defaultdict(list)

    def register(self, element_type, item):
        self._elements[element_type.value].append(item)

    def get(self, element_type):
        return self._elements[element_type.value]


for item in ElementTypes:
    prop_name = item.value
    prop = property(lambda self, item=item: self.get(item))

    setattr(Registry, prop_name.lower(), prop)

你把事情搞得太复杂了。您所需要的只是一个点符号dict包装器,比如or(还有更多的例子,只需搜索“python dict dot notation”),您将事情复杂化了。您所需要的只是一个点符号dict包装器,如or(还有更多的示例,只需搜索“python dict dot notation”)