我写了一些代码,假设对超集的检查将是内存友好的并导致更少的碎片,因为它返回一个布尔值(a_list总是不大于 2 个非常小的字符串元素,与foo
and的顺序相同bar
)。例如
OK_SET = set('foo', 'bar')
def are_args_ok(a_list):
if not OK_SET.issuperset(a_list): # expected to run a lot
raise ValueError('bad value in a_list') # virtually never
而且我认为上面比下面更可取,如果只是为了可读性,而且因为我认为最好不要创建很多不必要的列表,并且我希望它不会创建任何其他对象,因为它只返回一个布尔值。
def are_args_ok(a_list):
if [i for i in a_list if i not in ['foo', 'bar']]: # expected to run a lot
raise ValueError('bad value in a_list') # virtually never
但是,我不清楚 Python 的所有内部工作原理。因此,我一直在阅读CPython 源代码(下面的摘录),如果它还不是一个集合,则似乎检查超集会创建另一个的集合对象:
static PyObject *
set_issuperset(PySetObject *so, PyObject *other)
{
PyObject *tmp, *result;
if (!PyAnySet_Check(other)) {
tmp = make_new_set(&PySet_Type, other);
if (tmp == NULL)
return NULL;
result = set_issuperset(so, tmp);
Py_DECREF(tmp);
return result;
}
return set_issubset((PySetObject *)other, (PyObject *)so);
}
所以看起来我在给定一个列表作为另一个列表时创建了一个新集合,所以我的假设是错误的,即使它更具可读性。我认为第二个代码实际上可能更快,至少在我使用 Python 2.6 进行测试时是这样。所以我的问题是,就内存性能和碎片而言,第一个代码比第二个代码更可取吗?
有没有我还没有考虑过的严格主导的方法?
编辑:这回答了有关性能的相关问题:
must= '''MUST=set(['a','b'])
def validate(vals):
if not MUST.issuperset(vals):
raise Exception'''
mustdiff= '''MUST=set(['a','b'])
def validate(vals):
if set(vals) - MUST:
raise Exception'''
must2= '''def validate(vals):
if not set(['a','b']).issuperset(vals):
raise Exception'''
old_list = '''def validate(vals):
if [i for i in vals if i not in ['a','b']]:
raise Exception
'''
old_tup = '''def validate(vals):
if [i for i in vals if i not in ('a','b')]:
raise Exception
'''
test = "validate(['a']); validate(['a', 'b'])"
def main():
print timeit.repeat(test, setup=must)
print timeit.repeat(test, setup=mustdiff)
print timeit.repeat(test, setup=must2)
print timeit.repeat(test, setup=old_list)
print timeit.repeat(test, setup=old_tup)
输出:
[0.90473995592992651, 0.90407950738062937, 0.90170756738780256]
[1.0068785656071668, 1.0049370642036592, 1.0076947689335611]
[1.4705243140447237, 1.4697376920521492, 1.4727534788248704]
[0.74187539617878429, 0.74010685502116758, 0.74236680853618964]
[0.74886594826284636, 0.74639892541290465, 0.74475293549448907]