Python 在模块级或类内定义列表
我有一个类方法,通过将字典与列表进行比较,验证字典是否包含我期望它包含的所有键 目前,我在类的模块级别定义了集合,如下所示:Python 在模块级或类内定义列表,python,python-3.x,oop,Python,Python 3.x,Oop,我有一个类方法,通过将字典与列表进行比较,验证字典是否包含我期望它包含的所有键 目前,我在类的模块级别定义了集合,如下所示: expected_keys = { 'key1', 'key2', 'key3', 'key4', } class Spam(object): def __init__(self, config_dict): try: self.validate_configs(configs)
expected_keys = {
'key1',
'key2',
'key3',
'key4',
}
class Spam(object):
def __init__(self, config_dict):
try:
self.validate_configs(configs)
except TypeError, ValueError:
raise
...
def validate_configs(self, config_dict):
if not isinstance (config_dict, dict):
raise TypeError('Config structure is not a dictionary.')
if not expected_keys == config_dict.keys():
raise ValueError('Config dict does not have all necessary keys.')
这是最好的(性能和实践方面的)方法吗?我计划一次实例化数百个这样的对象,我不确定当前方法是否会导致性能下降。真正的
预期的\u键集也包含约30个条目。只要我做得正确,我就可以克服它在源文件中的丑陋(“应该有一种——最好只有一种——明显的方法来做”)。扩展@PM2Ring的评论,你应该做几件事:
1.)将期望的\u键
更改为集
(当前它是元组
。一个集用{}
表示)。根据@PM2Ring的注释,如果类对象已修复,则可以将其作为类属性来保持整洁:
class Spam(object):
expected_keys = {
'key1',
'key2',
'key3',
'key4',
}
def __init__(self, config_dict):
# continue defining the rest of your class...
2.)将上次验证更改为:
if not expected_keys.issubset(config_dict.keys()):
raise ValueError('Config dict does not have all necessary keys.')
这将检查config_dict
是否包含所有预期的密钥
,但仍将验证config_dict
是否有其他与预期不同的密钥
如果根据您的注释,config\u dict
必须具有与预期的\u键
完全相同的键(不多也不少),则您应验证为:
if not expected_keys == config_dict.keys():
raise ValueError('Config dict does not have all necessary keys.')
您的all
测试将检查期望的\u键是否是config\u dict
键的子集。使用set操作可以更快地完成这项操作,因此期望的_键应该是set,而不是list。(config_dict.keys()
自动成为类似集合的对象)。它应该是一个子集,还是这两个集合应该相等?这两个集合应该相等。我想也许我应该检查config_dict.keys()
和期望的键之间是否相等?我知道config\u dict.keys()
会返回一个dict\u keys
对象,不过顺便说一句,如果在中除了是raise
之外,你不需要在初始化中尝试。这将自动发生。@PM2Ring fair point-尽管在实际实现中,它发生在类中其他位置的不同函数中。这是我的quick-n'-肮脏但仍然有效的例子。我绝对会在未来的项目中牢记这一点。@problem_代码,前提是您的预期_键在整个类中保持不变(即实例之间没有区别),将其放在类中最有意义,因为它真正属于对象而不是主体。就性能而言,我认为这不会有什么不同。但是,如果您确实将其设置为实例属性(self.expected\u keys
),则如果您实例化了不合理的数量,则可能会影响性能。@problem\u代码类属性由所有实例共享,不会复制到实例中。因此,它使用的内存量与使其成为一个全局的内存量相同。是的,通常的做法是在\uuuu init\uuu
之前定义类属性。您只需使用裸名称expected\u keys
进行定义,但在方法中,您可以使用Spam从中读取。expected\u keys
或self。expected\u keys
@problem\u code FWIW,您可能希望向该值错误消息添加更多信息。例如,您可以执行keys=config_dict.keys()
,查看keys
是否等于self.expected_-keys,如果失败,则计算missing=self.expected_-keys;unknown=keys-self.expected_keys`并打印结果。@pm2很有趣,我不相信self.expected_keys
会是一个有效的引用,但确实是。我会想象它仅限于垃圾邮件。仅应为\u keys
。self.expected\u keys
上的名称解析首先检查实例属性,如果找不到实例属性,则查找类属性。