matplotlib文档中的颜色循环器示例很神秘(python)

matplotlib文档中的颜色循环器示例很神秘(python),python,matplotlib,colors,iterator,Python,Matplotlib,Colors,Iterator,有没有人能给我解释一下这个例子是如何工作的,摘自持久循环一节下面的部分 本质上,它们创建颜色循环器,我不确定它们是工厂函数、迭代器还是普通函数或对象。你可以用有限的iter(my\u cycler)和my\u cycler()用itertools.cycle生成器把它们做成一个生成器。我不明白这是怎么回事 所以我的问题是:为什么你能做iter(my\u cycler),它给出有限的东西,为什么你能做my\u cycler(),它给出相同的东西,但却是无限的(它循环) >>从Cycle导入Cycl

有没有人能给我解释一下这个例子是如何工作的,摘自持久循环一节下面的部分

本质上,它们创建颜色循环器,我不确定它们是工厂函数、迭代器还是普通函数或对象。你可以用有限的
iter(my\u cycler)
my\u cycler()
用itertools.cycle生成器把它们做成一个生成器。我不明白这是怎么回事

所以我的问题是:为什么你能做
iter(my\u cycler)
,它给出有限的东西,为什么你能做
my\u cycler()
,它给出相同的东西,但却是无限的(它循环)

>>从Cycle导入Cycle
>>>cyl=循环器(颜色=['r','g','b'])
>>>类型(cyl)
骑自行车的,骑自行车的
>>>进口自行车
>>>骑自行车的,骑自行车的__
(Cycle.Cycle,对象)
>>>类型(cyl())
itertools.cycle
>>类型(iter(cyl))
发电机
当我打字时:

>>下一步(气缸)
TypeError:“Cycle”对象不是迭代器
但不知怎的,这是可行的:

>>> for s in cyl:
...     print(s)
 
{'color': 'r'}
{'color': 'g'}
{'color': 'b'}
另一个问题是defaultdict的奇怪应用
style=defaultdict(lambda:next(finite\u cy\u iter))
。我想我大致理解了它,但我想确定:每当一个键不在dict中时,就会调用
(lambda:next(finite_cy_iter))()
或其他什么。根据defaultdicts上的文档,您必须给它一个函数,在本例中,
function=(lambda:next(finite_cy_iter))
。所以我猜每次调用dict
函数时,都会调用一个键,实际上这是一个伪装的迭代器,它会给你循环器中的下一个dict,然后它会被存储为该键的值

以下是matplotlib文档中的部分: 持续周期 通过字典查找将给定标签与样式关联并动态生成该映射非常有用。这可以使用defaultdict轻松完成

[40]中的
from cycler将cycler导入为cy
In[41]:从集合导入defaultdict
在[42]中:cyl=cy('c','rgb')+cy('lw',范围(1,4))
获取一组有限的样式

[43]中的
finite\u cy\u iter=iter(cyl)
在[44]中:dd_finite=defaultdict(lambda:next(finite_cy_iter))
或重复
在[45]中:loop\u cy\u iter=cyl()
在[46]中:dd_loop=defaultdict(lambda:next(loop_cy_iter))
这在打印既有分类又有标签的复杂数据时很有用

finite_cy_iter=iter(cyl)
styles=defaultdict(lambda:next(有限周期))
对于数据集中的组、标签和数据:
ax.plot(数据,标签=标签,**样式[组])

这将导致同一组的每个数据以相同的样式绘制。

关于问题的第一部分

所以我的问题是:为什么你能做
iter(my\u cycler)
,它给出有限的东西,为什么你能做
my\u cycler()
,它给出相同的东西,但却是无限的(它循环)

cycler
类的行为是这样的,因为它的定义是这样的,看看这个简单的例子,看看我的意思

In [13]: class callable_list(list): 
    ...:     def __call__(self): 
    ...:         from itertools import cycle 
    ...:         return cycle(self)                                                       

In [14]: l = callable_list((1,2))                                                         

In [15]: l                                                                                
Out[15]: [1, 2]

In [16]: it_l = iter(l) ; cy_l = l()                                                      

In [17]: for _ in range(3): print(next(it_l))                                             
1
2
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-17-e4324d8268a6> in <module>
----> 1 for _ in range(3): print(next(it_l))

StopIteration: 

In [18]: for _ in range(3): print(next(cy_l))                                             
1
2
1
从单循环器开始,首先
[1:2]
,对我来说,它返回一个值

In [2]: c[1:2]                                                                            
Out[2]: cycler('c', ['g'])
然后是
[1:1]
,同样是一个单一值,即空循环器

In [3]: c[1:1] # empty cycler                                                             
Out[3]: cycler('c', [])
请注意,这类似于对列表进行切片,在任何情况下,表达式的值都是单个对象、列表,可能是空列表……没有什么新内容

最后,让我们看看在切片外部产品时会发生什么,但首先让我们看看内部是什么

In [5]: for i, d in enumerate(cw): print(i, d)                                            
0 {'c': 'r', 'lw': 1}
1 {'c': 'r', 'lw': 2}
2 {'c': 'r', 'lw': 3}
3 {'c': 'r', 'lw': 4}
4 {'c': 'g', 'lw': 1}
5 {'c': 'g', 'lw': 2}
6 {'c': 'g', 'lw': 3}
7 {'c': 'g', 'lw': 4}
8 {'c': 'b', 'lw': 1}
9 {'c': 'b', 'lw': 2}
10 {'c': 'b', 'lw': 3}
11 {'c': 'b', 'lw': 4}
现在我们通过切片来解决它

In [6]: cw[3:9]                                                                           
Out[6]: (cycler('c', ['r', 'g', 'g', 'g', 'g', 'b']) + cycler('lw', [4, 1, 2, 3, 4, 1]))
结果是一个单循环器,即两个循环器的内积,在展开到上述枚举打印输出的位置3÷8时对应

最后,让我们使用
[3:3]
来解决
cw
,也就是说,一个空片段(扰流板,不会有什么好事发生!)

[7]中的
cw[3:3]
---------------------------------------------------------------------------
StopIteration回溯(最后一次调用)
在里面
---->1 cw[3:3]
~/lib/miniconda3/lib/python3.7/site-packages/cycler.py in\uuuuu getitem\uuuuuu(self,key)
219 trans=通过按键进行的自我测试()
220返回减少(添加,(_循环器(k,v[键])
-->221表示k,v在六个元素中。iteritems(trans)))
222其他:
223 raise VALUE ERROR(“只能将切片与循环器一起使用。”\uuuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuu”)
~/lib/miniconda3/lib/python3.7/site-packages/cycler.py in\uuuu添加(self,other)
241 raise VALUE ERROR(“只能添加等长循环,”
242“非{0}和{1}”。格式(len(self),len(other)))
-->243返回循环器(自身、其他、拉链)
244
245 def_uuumul_uuu(自身、其他):
~/lib/miniconda3/lib/python3.7/site-packages/cycler.py在uuuu init_uuu中(self,left,right,op)
116         """
117如果存在(左侧,循环器):
-->118 self.\u left=循环器(左。\左,左。\右,左。\ op)
119如果“左”不是“无”:
120#需要复制字典,否则这将是一个残余
~/lib/miniconda3/lib/python3.7/site-packages/cycler.py在uuuu init_uuu中(self,left,right,op)
133自右=无
134
-->135 self.\u键=\u进程\u键(self.\u左,self.\u右)
136自我。_op=op
137
进程键中的~/lib/miniconda3/lib/python3.7/site-packages/cycler.py(左、右)
66两个循环器组合中的键
67     """
--->68 l_peek=下一个(iter(左))如果左不是其他{}
69 r_peek=next(iter(right))如果right不是None-other{}
70 l_key=set(l_peek.keys())
停止迭代:
在[8]中:
以我谦卑的态度
In [6]: cw[3:9]                                                                           
Out[6]: (cycler('c', ['r', 'g', 'g', 'g', 'g', 'b']) + cycler('lw', [4, 1, 2, 3, 4, 1]))
In [7]: cw[3:3]                                                                           
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-7-1bf3cb52c570> in <module>
----> 1 cw[3:3]

~/lib/miniconda3/lib/python3.7/site-packages/cycler.py in __getitem__(self, key)
    219             trans = self.by_key()
    220             return reduce(add, (_cycler(k, v[key])
--> 221                                 for k, v in six.iteritems(trans)))
    222         else:
    223             raise ValueError("Can only use slices with Cycler.__getitem__")

~/lib/miniconda3/lib/python3.7/site-packages/cycler.py in __add__(self, other)
    241             raise ValueError("Can only add equal length cycles, "
    242                              "not {0} and {1}".format(len(self), len(other)))
--> 243         return Cycler(self, other, zip)
    244 
    245     def __mul__(self, other):

~/lib/miniconda3/lib/python3.7/site-packages/cycler.py in __init__(self, left, right, op)
    116         """
    117         if isinstance(left, Cycler):
--> 118             self._left = Cycler(left._left, left._right, left._op)
    119         elif left is not None:
    120             # Need to copy the dictionary or else that will be a residual

~/lib/miniconda3/lib/python3.7/site-packages/cycler.py in __init__(self, left, right, op)
    133             self._right = None
    134 
--> 135         self._keys = _process_keys(self._left, self._right)
    136         self._op = op
    137 

~/lib/miniconda3/lib/python3.7/site-packages/cycler.py in _process_keys(left, right)
     66         The keys in the composition of the two cyclers
     67     """
---> 68     l_peek = next(iter(left)) if left is not None else {}
     69     r_peek = next(iter(right)) if right is not None else {}
     70     l_key = set(l_peek.keys())

StopIteration: 

In [8]: