我正在写另一个“自行车”来读取.ini文件,以获得一些高级Python和OOP的经验。另外,我发现默认的Python的configparser访问样式对于眼睛来说有点不愉快,即:something = config['section']['parameter']
而不是更让人眼花{乱的something = config.section.parameter
。
我最终完成了这种设计:
ConfigStorage
对象可将参数/值对保留为字典; Config
对象来管理存储对象中的数据。__getattribute__
对象中的 Config
被覆盖,因此我可以通过ConfigStorage
对象的属性名称来访问Config
字典中的值(目标! )。
只有Config
对象的一个实例时,系统运行正常。当我尝试使用多个配置(并因此实例化新的Config
对象来管理它们)时,我意识到ConfigStorage
是所有人的唯一选择。
我尝试为每个ConfigStorage
对象创建Config
的新实例,但是Python在此代码中达到了最大递归深度(为什么?):
class _ConfigStorage(object):
def __init__(self):
self.config = dict()
class Config(object):
def __getattribute__(self, name):
if name in self.c.config:
return self.c.config[name]
else:
raise AttributeError("No parameter named [%s]" % name)
def __init__(self, file):
self.c = _ConfigStorage()
with open(file, 'r') as f:
for config_line in f:
key = # getting key from line
value = # getting value
self.c.config[key] = value
最后,我使我的代码正常工作,但是我发现此解决方案非常粗糙,并充满了黑魔法。我通过在字典键中添加Config
对象ID的字符串表示形式来分离存储对象中的数据。 ConfigStorage
对象仍然是单个。
此外,还需要__del__
方法,因为GC不知道存储中是否有不必要的数据,因此我必须手动删除它们。糟透了。
class _ConfigStorage(object):
config = dict()
class Config(object):
def __getattribute__(self, name):
key = str(id(self)) + name
if key in _ConfigStorage.config:
return _ConfigStorage.config[key]
else:
raise AttributeError("No parameter named [%s]" % name)
def __init__(self, file):
with open(file, 'r') as f:
for config_line in f:
key = str(id(self) + # getting key from line
value = # getting value
_ConfigStorage.config[key] = value
def __del__(self):
instance_id = str(id(self))
keys_to_delete = []
for key in _ConfigStorage.config:
if instance_id in key:
keys_to_delete.append(key)
for key_to_delete in keys_to_delete:
del _ConfigStorage.config[key_to_delete]
如何通过对象属性访问词典数据来改进设计?
答案 0 :(得分:1)
我认为此实现适合您的需求:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<link
rel="stylesheet"
href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css"
/>
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script>
<div id="map"></div>
无需编写class Config(object):
def __getattr__(self, name):
if name in self.config:
return self.config[name]
else:
raise AttributeError("No parameter named [%s]" % name)
def __init__(self, file=None):
# changed to make it work without real file
self.config = {'key': 'value'}
config = Config()
print(config.key) # value
print(config.not_a_key) # AttributeError: ...
和_ConfigStorage
,无需无限递归,可以通过点表示法进行访问。
答案 1 :(得分:0)
傻,但是我找到了解决问题的更优雅的方法。
class Config(object):
config = dict()
def __getattribute__(self, name):
if name in Config.config:
return Config.config[name]
else:
raise AttributeError("No parameter named [%s]" % name)
def __init__(self, file):
try:
with open(file, 'r') as f:
for config_line in f:
config_line = config_line.strip()
eq_position = config_line.find('=')
key = config_line[:eq_position].strip()
value = config_line[eq_position + 1:].strip()
Config.config[key] = value
except FileNotFoundError:
print('File not found')