0
# Chaining Module
1
2
The Chaining module provides method chaining functionality that enables fluent interface patterns for composing multiple pydash operations in a readable, left-to-right manner. This module consists of 3 main components plus the chaining class.
3
4
## Core Chaining Functions
5
6
### chain
7
8
```python { .api }
9
def chain(value: Any = None) -> _Dash
10
```
11
12
Creates a `_Dash` object which wraps `value` to enable method chaining.
13
14
**Parameters:**
15
- `value` (`Any`, optional): Value to wrap for chaining.
16
17
**Returns:**
18
- `_Dash`: Chaining wrapper object.
19
20
**Example:**
21
```python { .api }
22
from pydash import chain
23
24
result = chain([1, 2, 3, 4, 5, 6])\
25
.filter(lambda x: x % 2 == 0)\
26
.map(lambda x: x * 2)\
27
.value()
28
# [4, 8, 12]
29
30
# Complex data processing
31
data = [
32
{'name': 'John', 'age': 30, 'salary': 50000},
33
{'name': 'Jane', 'age': 25, 'salary': 60000},
34
{'name': 'Bob', 'age': 35, 'salary': 45000}
35
]
36
37
result = chain(data)\
38
.filter(lambda x: x['age'] > 25)\
39
.sort_by('salary')\
40
.map('name')\
41
.value()
42
# ['Bob', 'John']
43
```
44
45
### _ (underscore alias)
46
47
```python { .api }
48
def _(value: Any = None) -> _Dash
49
```
50
51
Shorthand alias for the `chain` function. Creates a `_Dash` object for method chaining.
52
53
**Parameters:**
54
- `value` (`Any`, optional): Value to wrap for chaining.
55
56
**Returns:**
57
- `_Dash`: Chaining wrapper object.
58
59
**Example:**
60
```python { .api }
61
from pydash import _
62
63
# Same functionality as chain()
64
result = _([1, 2, 3, 4, 5])\
65
.filter(lambda x: x > 2)\
66
.map(lambda x: x ** 2)\
67
.sum_()\
68
.value()
69
# 50 (3² + 4² + 5² = 9 + 16 + 25)
70
```
71
72
### tap
73
74
```python { .api }
75
def tap(value: Any, interceptor: Callable) -> Any
76
```
77
78
Invokes `interceptor` with `value` and returns `value`. This method is useful for debugging intermediate values in a chain.
79
80
**Parameters:**
81
- `value` (`Any`): Value to pass to interceptor and return.
82
- `interceptor` (`Callable`): Function to invoke with `value`.
83
84
**Returns:**
85
- `Any`: Returns `value`.
86
87
**Example:**
88
```python { .api }
89
from pydash import tap, _
90
91
# Debug intermediate results in a chain
92
result = _([1, 2, 3, 4, 5])\
93
.filter(lambda x: x % 2 == 1)\
94
.tap(lambda x: print(f"After filter: {x}"))\
95
.map(lambda x: x ** 2)\
96
.tap(lambda x: print(f"After map: {x}"))\
97
.value()
98
# Output: After filter: [1, 3, 5]
99
# After map: [1, 9, 25]
100
# Result: [1, 9, 25]
101
102
# Using tap for side effects
103
def log_progress(data):
104
print(f"Processing {len(data)} items")
105
return data
106
107
result = _(data)\
108
.filter(condition)\
109
.tap(log_progress)\
110
.map(transform)\
111
.value()
112
```
113
114
## Chaining Class
115
116
### _Dash
117
118
```python { .api }
119
class _Dash:
120
def __init__(self, value: Any = None)
121
```
122
123
The main chaining class that wraps values to enable method chaining. All pydash functions are available as methods on `_Dash` instances.
124
125
**Parameters:**
126
- `value` (`Any`, optional): Initial value to wrap.
127
128
**Key Methods:**
129
- `.value()`: Unwraps and returns the final result
130
- All pydash functions are available as methods
131
- Supports chaining of multiple operations
132
133
**Example:**
134
```python { .api }
135
from pydash import _
136
137
# Create a _Dash instance
138
wrapper = _([1, 2, 3, 4, 5])
139
140
# Chain operations
141
result = wrapper\
142
.filter(lambda x: x > 2)\
143
.map(lambda x: x * 2)\
144
.reverse()\
145
.value()
146
# [10, 8, 6]
147
```
148
149
## Chaining Patterns and Usage
150
151
### Basic Chaining
152
153
```python { .api }
154
from pydash import _
155
156
# Simple transformation chain
157
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
158
159
result = _(numbers)\
160
.filter(lambda x: x % 2 == 0)\
161
.map(lambda x: x ** 2)\
162
.take(3)\
163
.value()
164
# [4, 16, 36]
165
```
166
167
### Object Processing Chains
168
169
```python { .api }
170
from pydash import _
171
172
users = [
173
{'name': 'John', 'age': 30, 'active': True, 'department': 'Engineering'},
174
{'name': 'Jane', 'age': 25, 'active': True, 'department': 'Marketing'},
175
{'name': 'Bob', 'age': 35, 'active': False, 'department': 'Engineering'},
176
{'name': 'Alice', 'age': 28, 'active': True, 'department': 'Sales'}
177
]
178
179
# Complex object processing
180
active_eng_names = _(users)\
181
.filter({'active': True})\
182
.filter(lambda u: u['department'] == 'Engineering')\
183
.map('name')\
184
.value()
185
# ['John']
186
187
# Grouping and aggregation
188
dept_summary = _(users)\
189
.filter({'active': True})\
190
.group_by('department')\
191
.map_values(lambda group: {\
192
'count': len(group),\
193
'avg_age': sum(u['age'] for u in group) / len(group)\
194
})\
195
.value()
196
```
197
198
### String Processing Chains
199
200
```python { .api }
201
from pydash import _
202
203
text = " Hello, World! This is a test. "
204
205
processed = _(text)\
206
.trim()\
207
.to_lower()\
208
.replace('!', '')\
209
.split(' ')\
210
.filter(lambda x: len(x) > 2)\
211
.map(lambda x: x.capitalize())\
212
.join(' ')\
213
.value()
214
# "Hello World This Test"
215
```
216
217
### Statistical Analysis Chains
218
219
```python { .api }
220
from pydash import _
221
222
data = [
223
{'product': 'A', 'sales': 100, 'region': 'North'},
224
{'product': 'B', 'sales': 150, 'region': 'South'},
225
{'product': 'A', 'sales': 120, 'region': 'South'},
226
{'product': 'C', 'sales': 200, 'region': 'North'},
227
{'product': 'B', 'sales': 80, 'region': 'North'}
228
]
229
230
# Calculate total sales by product
231
product_totals = _(data)\
232
.group_by('product')\
233
.map_values(lambda group: sum(item['sales'] for item in group))\
234
.to_pairs()\
235
.sort_by(lambda x: x[1])\
236
.reverse()\
237
.value()
238
# [('C', 200), ('B', 230), ('A', 220)]
239
240
# Statistical summary
241
stats = _(data)\
242
.map('sales')\
243
.thru(lambda sales: {\
244
'total': _(sales).sum_().value(),\
245
'average': _(sales).mean().value(),\
246
'max': _(sales).max_().value(),\
247
'min': _(sales).min_().value()\
248
})\
249
.value()
250
```
251
252
### Debugging Chains with tap
253
254
```python { .api }
255
from pydash import _
256
257
def debug_print(label):
258
def printer(data):
259
print(f"{label}: {data}")
260
return data
261
return printer
262
263
result = _([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\
264
.tap(debug_print("Initial"))\
265
.filter(lambda x: x % 2 == 0)\
266
.tap(debug_print("After filter"))\
267
.map(lambda x: x ** 2)\
268
.tap(debug_print("After map"))\
269
.take(3)\
270
.tap(debug_print("After take"))\
271
.value()
272
273
# Output:
274
# Initial: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
275
# After filter: [2, 4, 6, 8, 10]
276
# After map: [4, 16, 36, 64, 100]
277
# After take: [4, 16, 36]
278
```
279
280
### Conditional Chaining
281
282
```python { .api }
283
from pydash import _
284
285
def conditional_process(data, include_filter=True, sort_desc=False):
286
chain_obj = _(data)
287
288
# Conditional filtering
289
if include_filter:
290
chain_obj = chain_obj.filter(lambda x: x > 0)
291
292
# Conditional sorting
293
if sort_desc:
294
chain_obj = chain_obj.sort().reverse()
295
else:
296
chain_obj = chain_obj.sort()
297
298
return chain_obj.value()
299
300
data = [3, -1, 4, -2, 5, 0]
301
result1 = conditional_process(data, True, True) # [5, 4, 3] (filtered & desc)
302
result2 = conditional_process(data, False, False) # [-2, -1, 0, 3, 4, 5] (all & asc)
303
```
304
305
### Method Availability
306
307
All pydash functions are available as methods on `_Dash` instances:
308
309
#### Array Methods
310
```python { .api }
311
_([1, 2, 3, 4]).chunk(2).flatten().uniq().compact().value()
312
```
313
314
#### Collection Methods
315
```python { .api }
316
_(users).filter({'active': True}).map('name').sort_by().value()
317
```
318
319
#### Object Methods
320
```python { .api }
321
_(obj).pick('name', 'age').merge(other_obj).value()
322
```
323
324
#### String Methods
325
```python { .api }
326
_('hello world').camel_case().capitalize().value()
327
```
328
329
#### Numerical Methods
330
```python { .api }
331
_([1, 2, 3, 4, 5]).mean().value()
332
```
333
334
#### Function Methods
335
```python { .api }
336
_(func).once().debounce(100).value()
337
```
338
339
#### Predicate Methods
340
```python { .api }
341
_(value).is_string().value() # Note: predicates return boolean, not chainable
342
```
343
344
#### Utility Methods
345
```python { .api }
346
_(data).default_to('fallback').times(3).value()
347
```
348
349
### Performance Considerations
350
351
Chaining creates intermediate wrapper objects, so for simple operations, direct function calls may be more efficient:
352
353
```python { .api }
354
# For simple operations, direct calls may be better
355
from pydash import map_, filter_
356
357
# Direct (more efficient for simple cases)
358
result = map_(filter_([1, 2, 3, 4], lambda x: x > 2), lambda x: x * 2)
359
360
# Chained (better for complex operations)
361
result = _([1, 2, 3, 4]).filter(lambda x: x > 2).map(lambda x: x * 2).value()
362
```
363
364
### Error Handling in Chains
365
366
```python { .api }
367
from pydash import _, attempt
368
369
def safe_chain(data):
370
try:
371
return _(data)\
372
.filter(lambda x: x is not None)\
373
.map(lambda x: int(x) if isinstance(x, str) else x)\
374
.filter(lambda x: x > 0)\
375
.value()
376
except Exception as e:
377
print(f"Chain processing failed: {e}")
378
return []
379
380
# Using attempt for individual operations
381
result = _(data)\
382
.map(lambda x: attempt(int, x))\
383
.filter(lambda x: not isinstance(x, Exception))\
384
.value()
385
```
386
387
The Chaining module enables fluent, readable data processing pipelines by allowing all pydash functions to be chained together in a natural left-to-right flow. This approach is particularly powerful for complex data transformations, filtering operations, and functional programming patterns.