Class 访问嵌套字典到属性通过打印和 __dict__ 显示不同的值
Class to access nested dics via attributes shows different values via print and __dict__
我正在做一个项目,我需要具有一些属性(例如日期、名称)的对象,然后是值的集合(通常 pd.DataFrames 具有不同的聚合,但我将使用整数作为示例这里)。与其执行多个嵌套的字典并为 data["df"]["yearly"] 等键键入许多额外的字符,不如使用 data.df.yearly 访问值会更容易。 (有没有更好的结构?)
因此我使用 class 将键设置为属性。但是根据访问数据的方式,我会得到不同的输出。
代码如下:
class Map(dict):
"""
Example:
m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
"""
def __init__(self, *args, **kwargs):
super(Map, self).__init__(*args, **kwargs)
for arg in args:
if isinstance(arg, dict):
for k, v in arg.items():
self[k] = v
if kwargs:
for k, v in kwargs.items():
self[k] = v
def __getattr__(self, attr):
super( Map, self ).__getattr__( attr )
return self.get(attr)
def __setattr__(self, key, value):
self.__setitem__(key, value)
def __setitem__( self, key, value ):
super( Map, self ).__setitem__( key, value )
if isinstance( value, dict ):
self.__dict__.update( {key: Map(value) } )
else:
self.__dict__.update( {key: value} )
def __delattr__(self, item):
self.__delitem__(item)
def __delitem__(self, key):
super(Map, self).__delitem__(key)
del self.__dict__[key]
现在,当我初始化一个实例并按以下方式为其分配一些数据时,我将有两个不同的输出,具体取决于我写的是 data.df.yearly 还是 data.df["yearly"]。
有人看出错误了吗(或者有更好的数据结构的建议?)。
创建 Map() 实例
data = Map()
data.start_date = "2020-01-01"
data.finish_date = '2021-01-01'
data.name = "Type A"
data.df = {"yearly" : 0, "monthly" : 0, "weekly" : 0}
更改 data.df
的值
for time in data.df.keys():
data.df[time] = 123
预期输出:
data
> {'start_date': '2020-01-01',
> 'finish_date': '2021-01-01',
> 'name': 'Type A',
> 'df': {'yearly': 123, 'monthly': 123, 'weekly': 123}}
输出(与 print(data) 相同):
data
> {'start_date': '2020-01-01',
> 'finish_date': '2021-01-01',
> 'name': 'Type A',
> 'df': {'yearly': 0, 'monthly': 0, 'weekly': 0}}
通过 dict 的输出匹配预期的输出:
data.__dict__
> {'start_date': '2020-01-01',
> 'finish_date': '2021-01-01',
> 'name': 'Type A',
> 'df': {'yearly': 123, 'monthly': 123, 'weekly': 123}}
您的 __setitem__
方法使用原始值调用超类方法,但如果该值是字典,则在将其放入 self.__dict__
时将其转换为 Map
。所以这两个位置包含不同的对象,没有任何东西可以使它们保持同步。
您应该先将值转换为 Map
,然后再将其存储在这两个地方。
def __setitem__( self, key, value ):
if isinstance(value, dict):
value = Map(value)
super( Map, self ).__setitem__( key, value )
self.__dict__.update({key: value})
我正在做一个项目,我需要具有一些属性(例如日期、名称)的对象,然后是值的集合(通常 pd.DataFrames 具有不同的聚合,但我将使用整数作为示例这里)。与其执行多个嵌套的字典并为 data["df"]["yearly"] 等键键入许多额外的字符,不如使用 data.df.yearly 访问值会更容易。 (有没有更好的结构?)
因此我使用 class 将键设置为属性。但是根据访问数据的方式,我会得到不同的输出。
代码如下:
class Map(dict):
"""
Example:
m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
"""
def __init__(self, *args, **kwargs):
super(Map, self).__init__(*args, **kwargs)
for arg in args:
if isinstance(arg, dict):
for k, v in arg.items():
self[k] = v
if kwargs:
for k, v in kwargs.items():
self[k] = v
def __getattr__(self, attr):
super( Map, self ).__getattr__( attr )
return self.get(attr)
def __setattr__(self, key, value):
self.__setitem__(key, value)
def __setitem__( self, key, value ):
super( Map, self ).__setitem__( key, value )
if isinstance( value, dict ):
self.__dict__.update( {key: Map(value) } )
else:
self.__dict__.update( {key: value} )
def __delattr__(self, item):
self.__delitem__(item)
def __delitem__(self, key):
super(Map, self).__delitem__(key)
del self.__dict__[key]
现在,当我初始化一个实例并按以下方式为其分配一些数据时,我将有两个不同的输出,具体取决于我写的是 data.df.yearly 还是 data.df["yearly"]。
有人看出错误了吗(或者有更好的数据结构的建议?)。
创建 Map() 实例
data = Map()
data.start_date = "2020-01-01"
data.finish_date = '2021-01-01'
data.name = "Type A"
data.df = {"yearly" : 0, "monthly" : 0, "weekly" : 0}
更改 data.df
的值for time in data.df.keys():
data.df[time] = 123
预期输出:
data
> {'start_date': '2020-01-01',
> 'finish_date': '2021-01-01',
> 'name': 'Type A',
> 'df': {'yearly': 123, 'monthly': 123, 'weekly': 123}}
输出(与 print(data) 相同):
data
> {'start_date': '2020-01-01',
> 'finish_date': '2021-01-01',
> 'name': 'Type A',
> 'df': {'yearly': 0, 'monthly': 0, 'weekly': 0}}
通过 dict 的输出匹配预期的输出:
data.__dict__
> {'start_date': '2020-01-01',
> 'finish_date': '2021-01-01',
> 'name': 'Type A',
> 'df': {'yearly': 123, 'monthly': 123, 'weekly': 123}}
您的 __setitem__
方法使用原始值调用超类方法,但如果该值是字典,则在将其放入 self.__dict__
时将其转换为 Map
。所以这两个位置包含不同的对象,没有任何东西可以使它们保持同步。
您应该先将值转换为 Map
,然后再将其存储在这两个地方。
def __setitem__( self, key, value ):
if isinstance(value, dict):
value = Map(value)
super( Map, self ).__setitem__( key, value )
self.__dict__.update({key: value})