0
# Core Utilities and Data Structures
1
2
Essential utilities and data structures that form the foundation of the fastcore ecosystem. These include null-safe operations, enhanced dictionaries, attribute access helpers, functional programming tools, and type manipulation utilities.
3
4
## Capabilities
5
6
### Basic Utilities
7
8
Core utility functions for common operations including null-safe handling, type checking, and object conversion.
9
10
```python { .api }
11
# Global configuration namespace
12
defaults = SimpleNamespace()
13
defaults.cpus = num_cpus() # Default number of CPUs for parallel operations
14
15
# Special objects for functional programming
16
Self = _SelfCls() # Special self-reference object
17
type_map = {int: to_int, float: to_float, str: str, bool: to_bool, date: to_date} # Type conversion mapping
18
19
# Argument placeholders for functional composition
20
arg0 = _Arg(0) # Placeholder for 1st argument
21
arg1 = _Arg(1) # Placeholder for 2nd argument
22
arg2 = _Arg(2) # Placeholder for 3rd argument
23
arg3 = _Arg(3) # Placeholder for 4th argument
24
arg4 = _Arg(4) # Placeholder for 5th argument
25
def ifnone(a, b):
26
"""
27
Return `b` if `a` is None else `a`.
28
29
Parameters:
30
- a: Value to test for None
31
- b: Default value if a is None
32
33
Returns:
34
`b` if `a` is None, otherwise `a`
35
"""
36
37
def maybe_attr(o, attr):
38
"""
39
Get attribute from object, returning object if attribute doesn't exist.
40
Equivalent to `getattr(o, attr, o)`.
41
42
Parameters:
43
- o: Object to get attribute from
44
- attr: Attribute name
45
46
Returns:
47
Attribute value or original object
48
"""
49
50
def is_array(x):
51
"""
52
Check if object supports array interface or iloc indexing.
53
54
Parameters:
55
- x: Object to check
56
57
Returns:
58
bool: True if object supports __array__ or iloc
59
"""
60
61
def listify(o=None, *rest, use_list=False, match=None):
62
"""
63
Convert object to list if not already iterable.
64
65
Parameters:
66
- o: Object to convert to list
67
- *rest: Additional objects to include
68
- use_list: bool, force list return type
69
- match: Object to match length against
70
71
Returns:
72
List containing the object(s)
73
"""
74
75
def tuplify(o, use_list=False, match=None):
76
"""
77
Convert object to tuple if not already iterable.
78
79
Parameters:
80
- o: Object to convert to tuple
81
- use_list: bool, return list instead of tuple
82
- match: Object to match length against
83
84
Returns:
85
Tuple containing the object(s)
86
"""
87
88
def true(x):
89
"""
90
Test whether object is truthy, handling numpy arrays correctly.
91
92
Parameters:
93
- x: Object to test
94
95
Returns:
96
bool: True if object is truthy
97
"""
98
```
99
100
### Repr and Debugging Utilities
101
102
Functions and classes for creating string representations and debugging support.
103
104
```python { .api }
105
def basic_repr(flds=None):
106
"""
107
Create minimal `__repr__` method for a class.
108
109
Parameters:
110
- flds: str or list, field names to include in repr
111
112
Returns:
113
Function that can be used as __repr__ method
114
"""
115
116
class BasicRepr:
117
"""
118
Base class that provides basic __repr__ functionality.
119
120
Automatically includes class name and key attributes in string representation.
121
"""
122
123
def num_methods(cls):
124
"""
125
Count numeric dunder methods in a class.
126
127
Parameters:
128
- cls: Class to inspect
129
130
Returns:
131
int: Number of numeric methods
132
"""
133
134
def rnum_methods(cls):
135
"""
136
Count reverse numeric dunder methods in a class.
137
138
Parameters:
139
- cls: Class to inspect
140
141
Returns:
142
int: Number of reverse numeric methods
143
"""
144
145
def inum_methods(cls):
146
"""
147
Count in-place numeric dunder methods in a class.
148
149
Parameters:
150
- cls: Class to inspect
151
152
Returns:
153
int: Number of in-place numeric methods
154
"""
155
```
156
157
### Enhanced Dictionary Classes
158
159
Dictionary subclasses with attribute-style access and additional functionality.
160
161
```python { .api }
162
class AttrDict(dict):
163
"""
164
Dictionary subclass that provides access to keys as attributes.
165
166
Features:
167
- Access keys using dot notation: obj.key
168
- Set keys using attribute assignment: obj.key = value
169
- Maintains all standard dict functionality
170
- Supports copy() method returning new AttrDict
171
- JSON-friendly repr in Jupyter notebooks
172
"""
173
174
def __getattr__(self, k): ...
175
def __setattr__(self, k, v): ...
176
def __dir__(self): ...
177
def copy(self): ...
178
179
class AttrDictDefault(AttrDict):
180
"""
181
AttrDict subclass that returns a default value for missing attributes.
182
183
Parameters:
184
- default_: Default value for missing keys (default: None)
185
186
Features:
187
- Returns default_ instead of raising AttributeError
188
- Useful for configuration objects with optional settings
189
"""
190
191
def __init__(self, *args, default_=None, **kwargs): ...
192
def __getattr__(self, k): ...
193
194
class NS(SimpleNamespace):
195
"""
196
Enhanced SimpleNamespace with dict-like interface and iteration support.
197
198
Features:
199
- Iterate over attributes: for key in obj
200
- Dict-style access: obj[key] and obj[key] = value
201
- Maintains SimpleNamespace attribute access
202
"""
203
204
def __iter__(self): ...
205
def __getitem__(self, x): ...
206
def __setitem__(self, x, y): ...
207
```
208
209
### Null Type and Special Objects
210
211
Special object types for representing null values and infinity.
212
213
```python { .api }
214
class NullType:
215
"""
216
Object that is falsy and can be safely called, chained, and indexed.
217
Always returns itself for any operation, useful as null object pattern.
218
219
Features:
220
- Falsy: bool(null) is False
221
- Callable: null() returns null
222
- Indexable: null[x] returns null
223
- Attribute access: null.attr returns null
224
"""
225
226
def __call__(self, *args, **kwargs): ...
227
def __getattr__(self, k): ...
228
def __getitem__(self, i): ...
229
def __bool__(self): ...
230
231
# Global null instance
232
null = NullType()
233
234
def tonull(x):
235
"""
236
Convert object to null if it's falsy, otherwise return unchanged.
237
238
Parameters:
239
- x: Object to potentially convert
240
241
Returns:
242
null if x is falsy, otherwise x
243
"""
244
245
class Inf:
246
"""
247
Infinity class that compares greater than any number.
248
Supports arithmetic operations and maintains infinity properties.
249
"""
250
251
def __lt__(self, other): ...
252
def __le__(self, other): ...
253
def __gt__(self, other): ...
254
def __ge__(self, other): ...
255
```
256
257
### Object Creation and Manipulation
258
259
Functions for dynamic class creation and object manipulation.
260
261
```python { .api }
262
def get_class(nm, *fld_names, sup=None, doc=None, funcs=None, anno=None, **flds):
263
"""
264
Create a class with specified name, fields, and methods.
265
266
Parameters:
267
- nm: str, class name
268
- *fld_names: Field names for the class
269
- sup: Base class or classes
270
- doc: str, class docstring
271
- funcs: dict, methods to add
272
- anno: dict, type annotations
273
- **flds: Additional field defaults
274
275
Returns:
276
New class type
277
"""
278
279
def mk_class(nm, *fld_names, sup=None, doc=None, funcs=None, mod=None, anno=None, **flds):
280
"""
281
Create class and add to module namespace.
282
283
Parameters:
284
- nm: str, class name
285
- *fld_names: Field names
286
- sup: Base class
287
- doc: str, docstring
288
- funcs: dict, methods
289
- mod: Module to add class to
290
- anno: dict, annotations
291
- **flds: Field defaults
292
293
Returns:
294
New class type
295
"""
296
297
def wrap_class(nm, *fld_names, sup=None, doc=None, funcs=None, **flds):
298
"""
299
Create class as wrapper around existing functionality.
300
301
Parameters:
302
- nm: str, class name
303
- *fld_names: Field names
304
- sup: Base class
305
- doc: str, docstring
306
- funcs: dict, methods
307
- **flds: Field defaults
308
309
Returns:
310
New class type
311
"""
312
```
313
314
### Context Managers and Exception Handling
315
316
Utilities for exception handling and context management.
317
318
```python { .api }
319
class ignore_exceptions:
320
"""
321
Context manager that ignores specified exceptions.
322
323
Parameters:
324
- *exceptions: Exception types to ignore
325
326
Usage:
327
with ignore_exceptions(ValueError, TypeError):
328
risky_operation()
329
"""
330
331
def __init__(self, *exceptions): ...
332
def __enter__(self): ...
333
def __exit__(self, type, value, traceback): ...
334
335
def exec_local(code, var_name):
336
"""
337
Execute code and return the value of specified variable.
338
339
Parameters:
340
- code: str, Python code to execute
341
- var_name: str, variable name to return
342
343
Returns:
344
Value of var_name after code execution
345
"""
346
```
347
348
### Type Checking and Introspection
349
350
Advanced type checking and annotation utilities.
351
352
```python { .api }
353
def risinstance(types, obj=None):
354
"""
355
Curried isinstance that checks if obj is instance of any of types.
356
Can be used as partial function or direct check.
357
358
Parameters:
359
- types: Type or tuple of types to check against
360
- obj: Object to check (optional for currying)
361
362
Returns:
363
Function or bool depending on usage
364
"""
365
366
def ver2tuple(v: str) -> tuple:
367
"""
368
Convert version string to tuple for comparison.
369
370
Parameters:
371
- v: str, version string like "1.2.3"
372
373
Returns:
374
tuple: Version as tuple of integers
375
"""
376
377
def get_annotations_ex(obj, *, globals=None, locals=None):
378
"""
379
Enhanced annotation extraction with globals/locals support.
380
Backport of Python 3.10 functionality.
381
382
Parameters:
383
- obj: Object to get annotations from
384
- globals: dict, global namespace
385
- locals: dict, local namespace
386
387
Returns:
388
tuple: (annotations_dict, globals, locals)
389
"""
390
391
def type_hints(f):
392
"""
393
Get type hints for function, similar to typing.get_type_hints.
394
Returns empty dict if not allowed type.
395
396
Parameters:
397
- f: Function to get hints for
398
399
Returns:
400
dict: Type hints mapping parameter names to types
401
"""
402
403
def annotations(o):
404
"""
405
Get annotations for object or its type/init method.
406
407
Parameters:
408
- o: Object to get annotations for
409
410
Returns:
411
dict: Annotations mapping names to types
412
"""
413
```
414
415
### Functional Programming Utilities
416
417
Helper functions for functional programming patterns.
418
419
```python { .api }
420
def ret_true(*args, **kwargs):
421
"""
422
Function that always returns True, useful as default predicate.
423
424
Returns:
425
bool: Always True
426
"""
427
428
def ret_false(*args, **kwargs):
429
"""
430
Function that always returns False, useful as default predicate.
431
432
Returns:
433
bool: Always False
434
"""
435
436
def stop(e=StopIteration):
437
"""
438
Raise specified exception.
439
440
Parameters:
441
- e: Exception instance to raise
442
443
Raises:
444
The provided exception
445
"""
446
447
def gen(func, seq, cond=ret_true):
448
"""
449
Generator that applies function to sequence while condition is true.
450
451
Parameters:
452
- func: Function to apply to each item
453
- seq: Iterable to process
454
- cond: Predicate function (default: ret_true)
455
456
Yields:
457
Results of func(item) while cond(item) is true
458
"""
459
460
def chunked(it, chunk_sz=None, drop_last=False, n_chunks=None):
461
"""
462
Split iterable into chunks of specified size.
463
464
Parameters:
465
- it: Iterable to chunk
466
- chunk_sz: int, size of each chunk
467
- drop_last: bool, drop incomplete last chunk
468
- n_chunks: int, number of chunks (alternative to chunk_sz)
469
470
Yields:
471
Lists containing chunk_sz items each
472
"""
473
474
def otherwise(x, tst, y):
475
"""
476
Return y if tst(x) is true, otherwise return x.
477
478
Parameters:
479
- x: Value to test and potentially return
480
- tst: Predicate function
481
- y: Alternative value
482
483
Returns:
484
y if tst(x), otherwise x
485
"""
486
```
487
488
## Usage Examples
489
490
### Configuration and Global Objects
491
492
```python
493
from fastcore.basics import defaults, Self, type_map, arg0, arg1
494
495
# Using global defaults
496
print(f"Default CPU count: {defaults.cpus}")
497
498
# Using argument placeholders with bind
499
from fastcore.basics import bind
500
def add_multiply(a, b, c):
501
return (a + b) * c
502
503
# Create function with arg placeholders
504
bound_func = bind(add_multiply, arg0, 10, arg1)
505
result = bound_func(5, 2) # (5 + 10) * 2 = 30
506
507
# Using type conversion mapping
508
converted = type_map[int]("42") # Converts "42" to integer 42
509
```
510
511
### Basic Operations
512
513
```python
514
from fastcore.basics import ifnone, listify, AttrDict
515
516
# Null-safe operations
517
config_value = ifnone(user_input, "default_setting")
518
519
# List conversion
520
items = listify("single") # ["single"]
521
items = listify(None) # []
522
items = listify([1,2,3]) # [1,2,3]
523
524
# Enhanced dictionary
525
config = AttrDict({
526
"model_name": "resnet50",
527
"learning_rate": 0.01,
528
"batch_size": 32
529
})
530
531
# Access as attributes
532
print(config.model_name) # "resnet50"
533
config.epochs = 10 # Set new attribute
534
config.learning_rate = 0.001 # Modify existing
535
```
536
537
### Advanced Type Handling
538
539
```python
540
from fastcore.basics import risinstance, annotations, type_hints
541
542
# Curried isinstance checking
543
is_numeric = risinstance((int, float))
544
print(is_numeric(42)) # True
545
print(is_numeric("42")) # False
546
547
# Type introspection
548
def example_func(x: int, y: str = "default") -> bool:
549
return True
550
551
hints = type_hints(example_func)
552
# {'x': <class 'int'>, 'y': <class 'str'>, 'return': <class 'bool'>}
553
```
554
555
### Safe Operations
556
557
```python
558
from fastcore.basics import ignore_exceptions, null
559
560
# Ignore specific exceptions
561
with ignore_exceptions(ValueError, TypeError):
562
result = risky_conversion(user_data)
563
564
# Null object pattern
565
safe_value = null
566
result = safe_value.some.deep.attribute.call() # Returns null, no errors
567
```