57
57
58
58
def _process_keys (left , right ):
59
59
"""
60
- Helper function to compose cycler keys
60
+ Helper function to compose cycler keys.
61
61
62
62
Parameters
63
63
----------
64
64
left, right : iterable of dictionaries or None
65
- The cyclers to be composed
65
+ The cyclers to be composed.
66
+
66
67
Returns
67
68
-------
68
69
keys : set
69
- The keys in the composition of the two cyclers
70
+ The keys in the composition of the two cyclers.
70
71
"""
71
72
l_peek = next (iter (left )) if left is not None else {}
72
73
r_peek = next (iter (right )) if right is not None else {}
@@ -78,28 +79,22 @@ def _process_keys(left, right):
78
79
79
80
80
81
def concat (left , right ):
81
- """
82
- Concatenate two cyclers , as if chained using `itertools.chain`.
82
+ r """
83
+ Concatenate `Cycler`\s , as if chained using `itertools.chain`.
83
84
84
85
The keys must match exactly.
85
86
86
87
Examples
87
88
--------
88
-
89
89
>>> num = cycler('a', range(3))
90
90
>>> let = cycler('a', 'abc')
91
91
>>> num.concat(let)
92
92
cycler('a', [0, 1, 2, 'a', 'b', 'c'])
93
93
94
- Parameters
95
- ----------
96
- left, right : `Cycler`
97
- The two `Cycler` instances to concatenate
98
-
99
94
Returns
100
95
-------
101
- ret : `Cycler`
102
- The concatenated `Cycler`
96
+ `Cycler`
97
+ The concatenated cycler.
103
98
"""
104
99
if left .keys != right .keys :
105
100
raise ValueError ("Keys do not match:\n "
@@ -114,7 +109,7 @@ def concat(left, right):
114
109
115
110
class Cycler (object ):
116
111
"""
117
- Composable cycles
112
+ Composable cycles.
118
113
119
114
This class has compositions methods:
120
115
@@ -130,25 +125,22 @@ class Cycler(object):
130
125
``*=``
131
126
in-place ``*``
132
127
133
- and supports basic slicing via ``[]``
128
+ and supports basic slicing via ``[]``.
134
129
135
130
Parameters
136
131
----------
137
- left : Cycler or None
138
- The 'left' cycler
139
-
140
- right : Cycler or None
141
- The 'right' cycler
142
-
132
+ left, right : Cycler or None
133
+ The 'left' and 'right' cyclers.
143
134
op : func or None
144
135
Function which composes the 'left' and 'right' cyclers.
145
-
146
136
"""
137
+
147
138
def __call__ (self ):
148
139
return cycle (self )
149
140
150
141
def __init__ (self , left , right = None , op = None ):
151
- """Semi-private init
142
+ """
143
+ Semi-private init.
152
144
153
145
Do not use this directly, use `cycler` function instead.
154
146
"""
@@ -178,9 +170,7 @@ def __contains__(self, k):
178
170
179
171
@property
180
172
def keys (self ):
181
- """
182
- The keys this Cycler knows about
183
- """
173
+ """The keys this Cycler knows about."""
184
174
return set (self ._keys )
185
175
186
176
def change_key (self , old , new ):
@@ -191,7 +181,6 @@ def change_key(self, old, new):
191
181
Does nothing if the old key is the same as the new key.
192
182
Raises a ValueError if the new key is already a key.
193
183
Raises a KeyError if the old key isn't a key.
194
-
195
184
"""
196
185
if old == new :
197
186
return
@@ -235,8 +224,8 @@ def _from_iter(cls, label, itr):
235
224
236
225
Returns
237
226
-------
238
- cycler : Cycler
239
- New 'base' `Cycler`
227
+ ` Cycler`
228
+ New 'base' cycler.
240
229
"""
241
230
ret = cls (None )
242
231
ret ._left = list ({label : v } for v in itr )
@@ -264,12 +253,11 @@ def __iter__(self):
264
253
265
254
def __add__ (self , other ):
266
255
"""
267
- Pair-wise combine two equal length cycles (zip)
256
+ Pair-wise combine two equal length cyclers (zip).
268
257
269
258
Parameters
270
259
----------
271
260
other : Cycler
272
- The second Cycler
273
261
"""
274
262
if len (self ) != len (other ):
275
263
raise ValueError ("Can only add equal length cycles, "
@@ -278,13 +266,12 @@ def __add__(self, other):
278
266
279
267
def __mul__ (self , other ):
280
268
"""
281
- Outer product of two cycles (`itertools.product`) or integer
269
+ Outer product of two cyclers (`itertools.product`) or integer
282
270
multiplication.
283
271
284
272
Parameters
285
273
----------
286
274
other : Cycler or int
287
- The second Cycler or integer
288
275
"""
289
276
if isinstance (other , Cycler ):
290
277
return Cycler (self , other , product )
@@ -307,12 +294,11 @@ def __len__(self):
307
294
308
295
def __iadd__ (self , other ):
309
296
"""
310
- In-place pair-wise combine two equal length cycles (zip)
297
+ In-place pair-wise combine two equal length cyclers (zip).
311
298
312
299
Parameters
313
300
----------
314
301
other : Cycler
315
- The second Cycler
316
302
"""
317
303
if not isinstance (other , Cycler ):
318
304
raise TypeError ("Cannot += with a non-Cycler object" )
@@ -326,12 +312,11 @@ def __iadd__(self, other):
326
312
327
313
def __imul__ (self , other ):
328
314
"""
329
- In-place outer product of two cycles (`itertools.product`)
315
+ In-place outer product of two cyclers (`itertools.product`).
330
316
331
317
Parameters
332
318
----------
333
319
other : Cycler
334
- The second Cycler
335
320
"""
336
321
if not isinstance (other , Cycler ):
337
322
raise TypeError ("Cannot *= with a non-Cycler object" )
@@ -344,14 +329,10 @@ def __imul__(self, other):
344
329
return self
345
330
346
331
def __eq__ (self , other ):
347
- """
348
- Check equality
349
- """
350
332
if len (self ) != len (other ):
351
333
return False
352
334
if self .keys ^ other .keys :
353
335
return False
354
-
355
336
return all (a == b for a , b in zip (self , other ))
356
337
357
338
def __ne__ (self , other ):
@@ -385,7 +366,8 @@ def _repr_html_(self):
385
366
return output
386
367
387
368
def by_key (self ):
388
- """Values by key
369
+ """
370
+ Values by key.
389
371
390
372
This returns the transposed values of the cycler. Iterating
391
373
over a `Cycler` yields dicts with a single value for each key,
@@ -416,20 +398,18 @@ def by_key(self):
416
398
_transpose = by_key
417
399
418
400
def simplify (self ):
419
- """Simplify the Cycler
420
-
421
- Returned as a composition using only sums (no multiplications)
401
+ """
402
+ Simplify the cycler into a sum (but no products) of cyclers.
422
403
423
404
Returns
424
405
-------
425
406
simple : Cycler
426
- An equivalent cycler using only summation """
407
+ """
427
408
# TODO: sort out if it is worth the effort to make sure this is
428
409
# balanced. Currently it is is
429
410
# (((a + b) + c) + d) vs
430
411
# ((a + b) + (c + d))
431
412
# I would believe that there is some performance implications
432
-
433
413
trans = self .by_key ()
434
414
return reduce (add , (_cycler (k , v ) for k , v in trans .items ()))
435
415
@@ -459,12 +439,10 @@ def cycler(*args, **kwargs):
459
439
----------
460
440
arg : Cycler
461
441
Copy constructor for Cycler (does a shallow copy of iterables).
462
-
463
442
label : name
464
443
The property key. In the 2-arg form of the function,
465
444
the label can be any hashable object. In the keyword argument
466
445
form of the function, it must be a valid python identifier.
467
-
468
446
itr : iterable
469
447
Finite length iterable of the property values.
470
448
Can be a single-property `Cycler` that would
@@ -499,14 +477,12 @@ def cycler(*args, **kwargs):
499
477
500
478
def _cycler (label , itr ):
501
479
"""
502
- Create a new `Cycler` object from a property name and
503
- iterable of values.
480
+ Create a new `Cycler` object from a property name and iterable of values.
504
481
505
482
Parameters
506
483
----------
507
484
label : hashable
508
485
The property key.
509
-
510
486
itr : iterable
511
487
Finite length iterable of the property values.
512
488
0 commit comments