更新 class 中字典中使用的 属性
Updating a property used in dict in a class
我正在尝试实现动态更新对象中的一些参数。
让我们在某些字典中使用 属性 ->
class Test():
def __init__(self):
self._id = None
self.some_dict = {"id": self.id}
@property
def id(self):
return self._id
@id.setter
def id(self, new_id: int):
self._id = new_id
tst = Test()
tst.id = 112
print(tst.id) # 112
print(tst.some_dict) # {'id': None}
期望的结果是:
print(tst.some_dict) # {'id': 112}
如何在某些参数 (id
) 之后更新字典,因为 属性 将被更新?
编辑:
我当然可以做到:
@id.setter
def id(self, new_id: int):
self._id = new_id
self._some_dict.update({"id": self._id})
但是很多参数写起来有点累,有没有自动的办法?
您必须将行 self.some_dict['id'] = new_id
添加到 def id
。
您可以访问实例的 __dict__
属性和 return 此 dict
的净化版本。
示例:(应该按原样工作)
class A:
_prohibited_keys = ["instance", "variables", "you", "dont", "want", "to", "show"]
def __init__(self):
self._id = None
@property
def id(self):
return self._id
@id.setter
def id(self, value: int):
self._id = value
@property
def dict(self):
return {self._private_to_pub_key(k): v for k, v in self.__dict__.items()
if k not in self._prohibited_keys and not k.startswith('__')}
def _private_to_pub_key(self, k):
return k[1:] if k.startswith('_') else k
a = A()
print(a.dict)
>>> {'id': None}
class Test():
def __init__(self):
self._id = None
self.some_dict = {"id": self.id}
@property
def id(self):
return self._id
@id.setter
def id(self, new_id: int):
self._id = new_id
self.some_dict['id'] = new_id
tst = Test()
tst.id = 112
print(tst.id) # 112
print(tst.some_dict) # {'id': 112}
您可以在 id.setter
函数中更新它:
@id.setter
def id(self, new_id: int):
self._id = new_id
self.some_dict.update({'id': new_id})
在某种程度上可以实现自动化,就像消除大量重复编码一样。在下面的代码中,这是通过结合使用创建属性的效用函数以及 post 处理 class 定义并初始化字典的元 class 来完成的也想要它也有
后者涉及搜索那些已定义的实例并初始化与其 属性 名称关联的实例存储属性以及此附加字典中的相应项目。这个要求使得 class 实例的创建变得如此复杂,尤其是需要有一个 metaclass — 所以你可能想重新考虑这是否真的有必要。
def dict_property(name):
""" Define property with given name that updates a private attribute and the
instance's dictionary named some_dict.
"""
storage_name = '_' + name
@property
def prop(self):
return getattr(self, storage_name)
@prop.setter
def prop(self, value):
setattr(self, storage_name, value)
self.some_dict.update({name: value})
return prop
class MyMetaClass(type):
def __new__(cls, name, bases, classdict, **kwargs):
""" Initialize dict_property values in class and some_dict to None. """
names = []
for name, value in classdict.items():
if isinstance(value, property):
#print(f'found property named {name!r}')
names.append(name)
some_dict = {}
for name in names:
storage_name = '_' + name
classdict[storage_name] = None
some_dict[name] = None
classdict['some_dict'] = some_dict # Add dict to class.
# Create the class.
return type.__new__(cls, name, bases, classdict, **kwargs)
class Test(metaclass=MyMetaClass):
id = dict_property('id')
age = dict_property('age')
tst = Test()
print(f'{tst.id=}') # -> tst.id=None
print(f'{tst.age=}') # -> tst.age=None
print(f'{tst.some_dict=}') # -> tst.some_dict={'id': None, 'age': None}
print()
tst.id = 112
print(f'{tst.id=}') # -> tst.id=112
print(f'{tst.age=}') # -> tst.age=None
print(f'{tst.some_dict=}') # -> tst.some_dict={'id': 112, 'age': None}
print()
tst.age = 42
print(f'{tst.id=}') # -> tst.id=112
print(f'{tst.age=}') # -> tst.age=42
print(f'{tst.some_dict=}') # -> tst.some_dict={'id': 112, 'age': 42}
尝试 @property
装饰器 some_dict
:
class Test():
def __init__(self):
self._id = None
@property
def id(self):
return self._id
@id.setter
def id(self, new_id: int):
self._id = new_id
@property
def some_dict(self):
return {'id': self.id}
tst = Test()
tst.id = 112
print(tst.id) # 112
print(tst.some_dict) # {'id': 112}
我正在尝试实现动态更新对象中的一些参数。 让我们在某些字典中使用 属性 ->
class Test():
def __init__(self):
self._id = None
self.some_dict = {"id": self.id}
@property
def id(self):
return self._id
@id.setter
def id(self, new_id: int):
self._id = new_id
tst = Test()
tst.id = 112
print(tst.id) # 112
print(tst.some_dict) # {'id': None}
期望的结果是:
print(tst.some_dict) # {'id': 112}
如何在某些参数 (id
) 之后更新字典,因为 属性 将被更新?
编辑: 我当然可以做到:
@id.setter
def id(self, new_id: int):
self._id = new_id
self._some_dict.update({"id": self._id})
但是很多参数写起来有点累,有没有自动的办法?
您必须将行 self.some_dict['id'] = new_id
添加到 def id
。
您可以访问实例的 __dict__
属性和 return 此 dict
的净化版本。
示例:(应该按原样工作)
class A:
_prohibited_keys = ["instance", "variables", "you", "dont", "want", "to", "show"]
def __init__(self):
self._id = None
@property
def id(self):
return self._id
@id.setter
def id(self, value: int):
self._id = value
@property
def dict(self):
return {self._private_to_pub_key(k): v for k, v in self.__dict__.items()
if k not in self._prohibited_keys and not k.startswith('__')}
def _private_to_pub_key(self, k):
return k[1:] if k.startswith('_') else k
a = A()
print(a.dict)
>>> {'id': None}
class Test():
def __init__(self):
self._id = None
self.some_dict = {"id": self.id}
@property
def id(self):
return self._id
@id.setter
def id(self, new_id: int):
self._id = new_id
self.some_dict['id'] = new_id
tst = Test()
tst.id = 112
print(tst.id) # 112
print(tst.some_dict) # {'id': 112}
您可以在 id.setter
函数中更新它:
@id.setter
def id(self, new_id: int):
self._id = new_id
self.some_dict.update({'id': new_id})
在某种程度上可以实现自动化,就像消除大量重复编码一样。在下面的代码中,这是通过结合使用创建属性的效用函数以及 post 处理 class 定义并初始化字典的元 class 来完成的也想要它也有
后者涉及搜索那些已定义的实例并初始化与其 属性 名称关联的实例存储属性以及此附加字典中的相应项目。这个要求使得 class 实例的创建变得如此复杂,尤其是需要有一个 metaclass — 所以你可能想重新考虑这是否真的有必要。
def dict_property(name):
""" Define property with given name that updates a private attribute and the
instance's dictionary named some_dict.
"""
storage_name = '_' + name
@property
def prop(self):
return getattr(self, storage_name)
@prop.setter
def prop(self, value):
setattr(self, storage_name, value)
self.some_dict.update({name: value})
return prop
class MyMetaClass(type):
def __new__(cls, name, bases, classdict, **kwargs):
""" Initialize dict_property values in class and some_dict to None. """
names = []
for name, value in classdict.items():
if isinstance(value, property):
#print(f'found property named {name!r}')
names.append(name)
some_dict = {}
for name in names:
storage_name = '_' + name
classdict[storage_name] = None
some_dict[name] = None
classdict['some_dict'] = some_dict # Add dict to class.
# Create the class.
return type.__new__(cls, name, bases, classdict, **kwargs)
class Test(metaclass=MyMetaClass):
id = dict_property('id')
age = dict_property('age')
tst = Test()
print(f'{tst.id=}') # -> tst.id=None
print(f'{tst.age=}') # -> tst.age=None
print(f'{tst.some_dict=}') # -> tst.some_dict={'id': None, 'age': None}
print()
tst.id = 112
print(f'{tst.id=}') # -> tst.id=112
print(f'{tst.age=}') # -> tst.age=None
print(f'{tst.some_dict=}') # -> tst.some_dict={'id': 112, 'age': None}
print()
tst.age = 42
print(f'{tst.id=}') # -> tst.id=112
print(f'{tst.age=}') # -> tst.age=42
print(f'{tst.some_dict=}') # -> tst.some_dict={'id': 112, 'age': 42}
尝试 @property
装饰器 some_dict
:
class Test():
def __init__(self):
self._id = None
@property
def id(self):
return self._id
@id.setter
def id(self, new_id: int):
self._id = new_id
@property
def some_dict(self):
return {'id': self.id}
tst = Test()
tst.id = 112
print(tst.id) # 112
print(tst.some_dict) # {'id': 112}