You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+26-26Lines changed: 26 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ Python is a powerful, dynamic language. Rather than bake everything into the lan
6
6
7
7
## Installing
8
8
9
-
To install fastcore run: `conda install -c fastai fastcore` (if you use Anaconda, which we strongly recommend) or `pip install fastcore`. For an [editable install](https://stackoverflow.com/questions/35064426/when-would-the-e-editable-option-be-useful-with-pip-install), clone this repo and run: `pip install -e ".[dev]"`.
9
+
To install fastcore run: `conda install fastcore` (if you use Anaconda, which we strongly recommend) or `pip install fastcore`. For an [editable install](https://stackoverflow.com/questions/35064426/when-would-the-e-editable-option-be-useful-with-pip-install), clone this repo and run: `pip install -e ".[dev]"`.
10
10
11
11
## A tour
12
12
@@ -24,7 +24,7 @@ Here's a (somewhat) quick tour of a few higlights, showing examples from each of
24
24
25
25
All fast.ai projects, including this one, are built with [nbdev](https://nbdev.fast.ai), which is a full literate programming environment built on Jupyter Notebooks. That means that every piece of documentation, including the page you're reading now, can be accessed as interactive Jupyter notebooks. In fact, you can even grab a link directly to a notebook running interactively on Google Colab - if you want to follow along with this tour, click the link below, or click the badge at the top of the page:
26
26
27
-
```python
27
+
```
28
28
colab_link('index')
29
29
```
30
30
@@ -34,7 +34,7 @@ colab_link('index')
34
34
35
35
The full docs are available at [fastcore.fast.ai](https://fastcore.fast.ai). The code in the examples and in all fast.ai libraries follow the [fast.ai style guide](https://docs.fast.ai/dev/style.html). In order to support interactive programming, all fast.ai libraries are designed to allow for `import *` to be used safely, particular by ensuring that [`__all__`](https://riptutorial.com/python/example/2894/the---all---special-variable) is defined in all packages. In order to see where a function is from, just type it:
36
36
37
-
```python
37
+
```
38
38
coll_repr
39
39
```
40
40
@@ -61,13 +61,13 @@ fastcore's testing module is designed to work well with [nbdev](https://nbdev.fa
That's an example from the docs for `coll_repr`. As you see, it's not showing you the output directly. Here's what that would look like:
69
69
70
-
```python
70
+
```
71
71
coll_repr(range(1000), 5)
72
72
```
73
73
@@ -84,7 +84,7 @@ So every test shown in the docs is also showing you the behavior of the library
84
84
85
85
Test functions always start with `test_`, and then follow with the operation being tested. So `test_eq` tests for equality (as you saw in the example above). This includes tests for equality of arrays and tensors, lists and generators, and many more:
86
86
87
-
```python
87
+
```
88
88
test_eq([0,1,2,3], np.arange(4))
89
89
```
90
90
@@ -105,28 +105,28 @@ If you want to check that objects are the same type, rather than the just contai
105
105
106
106
You can test with any comparison function using `test`, e.g test whether an object is less than:
107
107
108
-
```python
108
+
```
109
109
test(2, 3, operator.lt)
110
110
```
111
111
112
112
You can even test that exceptions are raised:
113
113
114
-
```python
114
+
```
115
115
def divide_zero(): return 1/0
116
116
test_fail(divide_zero)
117
117
```
118
118
119
119
...and test that things are printed to stdout:
120
120
121
-
```python
121
+
```
122
122
test_stdout(lambda: print('hi'), 'hi')
123
123
```
124
124
125
125
### Foundations
126
126
127
127
fast.ai is unusual in that we often use [mixins](https://en.wikipedia.org/wiki/Mixin) in our code. Mixins are widely used in many programming languages, such as Ruby, but not so much in Python. We use mixins to attach new behavior to existing libraries, or to allow modules to add new behavior to our own classes, such as in extension modules. One useful example of a mixin we define is `Path.ls`, which lists a directory and returns an `L` (an extended list class which we'll discuss shortly):
128
128
129
-
```python
129
+
```
130
130
p = Path('images')
131
131
p.ls()
132
132
```
@@ -140,7 +140,7 @@ p.ls()
140
140
141
141
You can easily add you own mixins with the `patch`[decorator](https://realpython.com/primer-on-python-decorators/), which takes advantage of Python 3 [function annotations](https://www.python.org/dev/peps/pep-3107/#parameters) to say what class to patch:
142
142
143
-
```python
143
+
```
144
144
@patch
145
145
def num_items(self:Path): return len(self.ls())
146
146
@@ -158,7 +158,7 @@ We also use `**kwargs` frequently. In python `**kwargs` in a parameter like mean
158
158
159
159
`GetAttr` solves a similar problem (and is also discussed in the article linked above): it's allows you to use Python's exceptionally useful `__getattr__` magic method, but avoids the problem that normally in Python tab-completion and docs break when using this. For instance, you can see here that Python's `dir` function, which is used to find the attributes of a python object, finds everything inside the `self.default` attribute here:
160
160
161
-
```python
161
+
```
162
162
class Author:
163
163
def __init__(self, name): self.name = name
164
164
@@ -179,7 +179,7 @@ p = ProductPage(Author("Jeremy"), 1.50, 0.50)
179
179
180
180
Looking at that `ProductPage` example, it's rather verbose and duplicates a lot of attribute names, which can lead to bugs later if you change them only in one place. `fastcore` provides `store_attr` to simplify this common pattern. It also provides `basic_repr` to give simple objects a useful `repr`:
One of the most interesting `fastcore` functions is the `funcs_kwargs` decorator. This allows class behavior to be modified without sub-classing. This can allow folks that aren't familiar with object-oriented progressing to customize your class more easily. Here's an example of a class that uses `funcs_kwargs`:
198
198
199
-
```python
199
+
```
200
200
@funcs_kwargs
201
201
class T:
202
202
_methods=['some_method']
@@ -222,7 +222,7 @@ Like most languages, Python allows for very concise syntax for some very common
222
222
223
223
On this basis, `fastcore` has just one type that has a single letter name:`L`. The reason for this is that it is designed to be a replacement for `list`, so we want it to be just as easy to use as `[1,2,3]`. Here's how to create that as an `L`:
224
224
225
-
```python
225
+
```
226
226
L(1,2,3)
227
227
```
228
228
@@ -235,49 +235,49 @@ L(1,2,3)
235
235
236
236
The first thing to notice is that an `L` object includes in its representation its number of elements; that's the `(#3)` in the output above. If there's more than 10 elements, it will automatically truncate the list:
237
237
238
-
```python
238
+
```
239
239
p = L.range(20).shuffle()
240
240
p
241
241
```
242
242
243
243
244
244
245
245
246
-
(#20) [17,10,7,18,12,13,5,16,15,19...]
246
+
(#20) [18,7,1,11,10,14,3,16,13,15...]
247
247
248
248
249
249
250
250
`L` contains many of the same indexing ideas that NumPy's `array` does, including indexing with a list of indexes, or a boolean mask list:
251
251
252
-
```python
252
+
```
253
253
p[2,4,6]
254
254
```
255
255
256
256
257
257
258
258
259
-
(#3) [7,12,5]
259
+
(#3) [1,10,3]
260
260
261
261
262
262
263
263
It also contains other methods used in `array`, such as `L.argwhere`:
264
264
265
-
```python
265
+
```
266
266
p.argwhere(ge(15))
267
267
```
268
268
269
269
270
270
271
271
272
-
(#5) [0,3,7,8,9]
272
+
(#5) [0,7,9,16,17]
273
273
274
274
275
275
276
276
As you can see from this example, `fastcore` also includes a number of features that make a functional style of programming easier, such as a full range of boolean functions (e.g `ge`, `gt`, etc) which give the same answer as the functions from Python's `operator` module if given two parameters, but return a [curried function](https://en.wikipedia.org/wiki/Currying) if given one parameter.
277
277
278
278
There's too much functionality to show it all here, so be sure to check the docs. Many little things are added that we thought should have been in `list` in the first place, such as making this do what you'd expect (which is an error with `list`, but works fine with `L`):
279
279
280
-
```python
280
+
```
281
281
1 + L(2,3,4)
282
282
```
283
283
@@ -292,7 +292,7 @@ There's too much functionality to show it all here, so be sure to check the docs
292
292
293
293
Most Python programmers use object oriented methods and inheritance to allow different objects to behave in different ways even when called with the same method name. Some languages use a very different approach, such as Julia, which uses [multiple dispatch generic functions](https://docs.julialang.org/en/v1/manual/methods/). Python provides [single dispatch generic functions](https://www.python.org/dev/peps/pep-0443/) as part of the standard library. `fastcore` provides multiple dispatch, with the `typedispatch` decorator (which is actually an instance of `DispatchReg`):
294
294
295
-
```python
295
+
```
296
296
@typedispatch
297
297
def _f(x:numbers.Integral, y): return x+1
298
298
@typedispatch
@@ -321,7 +321,7 @@ This approach to dispatch is particularly useful for adding implementations of f
321
321
322
322
`Transform` looks for three special methods, <code>encodes</code>, <code>decodes</code>, and <code>setups</code>, which provide the implementation for [`__call__`](https://www.python-course.eu/python3_magic_methods.php), `decode`, and `setup` respectively. For instance:
323
323
324
-
```python
324
+
```
325
325
class A(Transform):
326
326
def encodes(self, x): return x+1
327
327
@@ -337,7 +337,7 @@ A()(1)
337
337
338
338
For simple transforms like this, you can also use `Transform` as a decorator:
0 commit comments