2016-08-30 43 views
1

我有两份名单,我拉链(一起:如何解包())通过压缩创建的列表

>> x1 = ['1', '2', '3'] 
>> y1 = ['a', 'b', 'c'] 
>> zipped = zip(x1, y1) 

如到目前为止预期:

>> print(list(zipped) 
[('1', 'a'), ('2', 'b'), ('3', 'c')] 

从文档,它似乎像我可以做到这一点从拉链对象拿回两个列表:

>> x2, y2 = zip(*zipped) 

而是我得到的错误:

Traceback (most recent call last):  
File "/usr/lib/python3.5/site-packages/IPython/core/interactiveshell.py", line 2869, in run_code 
exec(code_obj, self.user_global_ns, self.user_ns)  
File "<ipython-input-6-58fe68d00d1c>", line 1, in <module> 
x2, y2 = zip(*zipped) 
ValueError: not enough values to unpack (expected 2, got 0) 

很明显,我并不了解有关zip对象的简单东西。

编辑:

正如下面@daragua所指出的,印刷(列表(压缩))实际上消耗压缩的对象,从而使得空。这是真的,我的简单例子。我的真实代码仍然存在问题。

我想要写的是一个Django视图的单元测试,在它的上下文中有一个压缩对象。视图正常工作,我只是在努力为它写测试。

在我看来方面,我有这样的:

for season in context['pools']: 
    commissioner.append(season.pool.is_commish(self.request.user)) 
context['pools'] = zip(context['pools'], commissioner) 

可正常工作。池上下文对象是两个列表,该模板处理就好了:

{% for season, commissioner in pools %} 

我挣扎写的测试是检查commissioner值是用于登录的用户一个池对象正确。在我的测试:

context = self.response.context['pools'] 
print(list(context)) 

在这种情况下,context是一个空列表[]

回答

2

zip函数返回一个迭代器。因此print(list(zipped))调用运行迭代器直到它结束,并且下一个zip(*zipped)没有任何东西可吃。

+0

也许这是同样的事情发生:测试框架或Django代码中的某些东西可能会窥探'context'对象,在获取它之前使用迭代器。试试'context ['pools'] = list(zip(context ['pools'],commissioner))'? – daragua

1

只是zip回反向:

>>> zipped=zip(x1, y1) 
>>> x2, y2=zip(*zipped) 
>>> x2 
('1', '2', '3') 

并使用map如果你想要得到的结果是一个列表,而不是一个元组:

>>> zipped=zip(x1, y1) 
>>> x2, y2=map(list, zip(*zipped)) 
>>> x2 
['1', '2', '3'] 
>>> y2 
['a', 'b', 'c'] 

边注:在Python 3,压缩收益一次性使用迭代器。这就是为什么zip需要在每次使用后再次调用(仅在Python 3中)

0

最终,问题根本不在于zip对象。

如果要发送一个压缩对象的Django的背景:

x = ['1', '2', '3'] 
y = ['a', 'b', 'c'] 
context['zipped'] = zip(x, y) 

如果你正在尝试写上下文数据的单元测试,你并不需要解压缩,因为它可以从响应上下文拉已经拉开:

def test_zipped_data(TestCase): 
    x, y = self.response.context_data['zipped'] 
    self.assertIn('b', y) 

但是,如果您的上下文数据为空(zipped == []),那么你会得到ValueError例外。但那只是因为你的上下文是空的,而且你的测试工作正常!